interrogate should support long long

This commit is contained in:
David Rose 2004-09-14 22:24:13 +00:00
parent 95bdf94020
commit e2a27fabda
9 changed files with 207 additions and 8 deletions

View File

@ -20,6 +20,7 @@ AT_bool = 4
AT_char = 5 AT_char = 5
AT_void = 6 AT_void = 6
AT_string = 7 AT_string = 7
AT_longlong = 8
def cullOverloadedMethods(fullMethodDict): def cullOverloadedMethods(fullMethodDict):
""" """
@ -65,6 +66,9 @@ def getTypeName(classTypeDesc, typeDesc):
(typeDesc.atomicType == AT_double)): (typeDesc.atomicType == AT_double)):
return 'types.FloatType' return 'types.FloatType'
elif ((typeDesc.atomicType == AT_longlong)):
return 'types.LongType'
# Strings are treated as Python strings # Strings are treated as Python strings
elif ((typeDesc.atomicType == AT_string)): elif ((typeDesc.atomicType == AT_string)):
return 'types.StringType' return 'types.StringType'
@ -416,8 +420,9 @@ class FFIMethodArgumentTree:
# Otherwise, we'll check the particular type of # Otherwise, we'll check the particular type of
# the object. # the object.
condition = '(isinstance(_args[' + `level` + '], ' + typeName + '))' condition = '(isinstance(_args[' + `level` + '], ' + typeName + '))'
# If it is looking for a float, make it accept an integer too # If it is looking for a float or a long, make it
if (typeName == 'types.FloatType'): # accept an integer too
if (typeName == 'types.FloatType' or typeName == 'types.LongType'):
condition += (' or (isinstance(_args[' + `level` + '], ' condition += (' or (isinstance(_args[' + `level` + '], '
+ 'types.IntType' + 'types.IntType'
+ '))') + '))')

View File

@ -41,13 +41,18 @@ class FunctionSpecification:
typeName = FFIOverload.getTypeName(methodClass, typeDesc) typeName = FFIOverload.getTypeName(methodClass, typeDesc)
# Special case: # Special case:
# If it is looking for a float, accept an int as well # If it is looking for a float or a long, accept an int as well
# C++ will cast it properly, and it is much more convenient # C++ will cast it properly, and it is much more convenient
if (typeName == 'types.FloatType'): if (typeName == 'types.FloatType'):
indent(file, nesting, 'assert((isinstance(' + indent(file, nesting, 'assert((isinstance(' +
methodArgSpec.name + ', types.FloatType) or isinstance(' + methodArgSpec.name + ', types.FloatType) or isinstance(' +
methodArgSpec.name + ', types.IntType)))\n') methodArgSpec.name + ', types.IntType)))\n')
elif (typeName == 'types.LongType'):
indent(file, nesting, 'assert((isinstance(' +
methodArgSpec.name + ', types.LongType) or isinstance(' +
methodArgSpec.name + ', types.IntType)))\n')
elif typeDesc.__class__ != FFITypes.PyObjectTypeDescriptor: elif typeDesc.__class__ != FFITypes.PyObjectTypeDescriptor:
# Get the real return type (not derived) # Get the real return type (not derived)
if ((not typeDesc.isNested) and if ((not typeDesc.isNested) and

View File

@ -56,6 +56,7 @@ class BaseTypeDescriptor:
# AT_char = 5 # AT_char = 5
# AT_void = 6 # AT_void = 6
# AT_string = 7 # AT_string = 7
# AT_longlong = 8
# By default this type is not atomic # By default this type is not atomic
self.atomicType = 0 self.atomicType = 0

View File

@ -321,6 +321,9 @@ write_function_instance(ostream &out, int indent_level,
string format_specifiers; string format_specifiers;
string parameter_list; string parameter_list;
vector_string pexprs; vector_string pexprs;
string extra_convert;
string extra_param_check;
string extra_cleanup;
// Make one pass through the parameter list. We will output a // Make one pass through the parameter list. We will output a
// one-line temporary variable definition for each parameter, while // one-line temporary variable definition for each parameter, while
@ -371,6 +374,26 @@ write_function_instance(ostream &out, int indent_level,
pexpr_string = "(PyObject_IsTrue(" + param_name + ")!=0)"; pexpr_string = "(PyObject_IsTrue(" + param_name + ")!=0)";
expected_params += "bool"; expected_params += "bool";
} else if (TypeManager::is_unsigned_longlong(type)) {
out << "PyObject *" << param_name;
format_specifiers += "O";
parameter_list += ", &" + param_name;
extra_convert += " PyObject *" + param_name + "_long = PyNumber_Long(" + param_name + ");";
extra_param_check += "|| (" + param_name + "_long == NULL)";
pexpr_string = "PyLong_AsUnsignedLongLong(" + param_name + "_long)";
extra_cleanup += " Py_XDECREF(" + param_name + "_long);";
expected_params += "long";
} else if (TypeManager::is_longlong(type)) {
out << "PyObject *" << param_name;
format_specifiers += "O";
parameter_list += ", &" + param_name;
extra_convert += " PyObject *" + param_name + "_long = PyNumber_Long(" + param_name + ");";
extra_param_check += "|| (" + param_name + "_long == NULL)";
pexpr_string = "PyLong_AsLongLong(" + param_name + "_long)";
extra_cleanup += " Py_XDECREF(" + param_name + "_long);";
expected_params += "long";
} else if (TypeManager::is_integer(type)) { } else if (TypeManager::is_integer(type)) {
out << "int " << param_name; out << "int " << param_name;
format_specifiers += "i"; format_specifiers += "i";
@ -417,6 +440,26 @@ write_function_instance(ostream &out, int indent_level,
<< "if (PyArg_ParseTuple(args, \"" << format_specifiers << "if (PyArg_ParseTuple(args, \"" << format_specifiers
<< "\"" << parameter_list << ")) {\n"; << "\"" << parameter_list << ")) {\n";
if (!extra_convert.empty()) {
indent(out, indent_level + 3)
<< extra_convert << "\n";
}
if (!extra_param_check.empty()) {
indent(out, indent_level + 4)
<< "if (" << extra_param_check.substr(3) << ") {\n";
if (!extra_cleanup.empty()) {
indent(out, indent_level + 5)
<< extra_cleanup << "\n";
}
indent(out, indent_level + 6)
<< "PyErr_SetString(PyExc_TypeError, \"Invalid parameters.\");\n";
indent(out, indent_level + 6)
<< "return (PyObject *)NULL;\n";
indent(out, indent_level + 4)
<< "}\n";
}
if (track_interpreter) { if (track_interpreter) {
indent(out, indent_level + 4) indent(out, indent_level + 4)
<< "in_interpreter = 0;\n"; << "in_interpreter = 0;\n";
@ -438,6 +481,10 @@ write_function_instance(ostream &out, int indent_level,
indent(out, indent_level + 4) indent(out, indent_level + 4)
<< "in_interpreter = 1;\n"; << "in_interpreter = 1;\n";
} }
if (!extra_cleanup.empty()) {
indent(out, indent_level + 3)
<< extra_cleanup << "\n";
}
return_expr = manage_return_value(out, indent_level + 4, remap, "return_value"); return_expr = manage_return_value(out, indent_level + 4, remap, "return_value");
test_assert(out, indent_level + 4); test_assert(out, indent_level + 4);
@ -451,6 +498,10 @@ write_function_instance(ostream &out, int indent_level,
indent(out, indent_level + 4) indent(out, indent_level + 4)
<< "in_interpreter = 1;\n"; << "in_interpreter = 1;\n";
} }
if (!extra_cleanup.empty()) {
indent(out, indent_level + 3)
<< extra_cleanup << "\n";
}
test_assert(out, indent_level + 4); test_assert(out, indent_level + 4);
indent(out, indent_level + 4) indent(out, indent_level + 4)
<< "return Py_BuildValue(\"\");\n"; << "return Py_BuildValue(\"\");\n";
@ -464,6 +515,10 @@ write_function_instance(ostream &out, int indent_level,
indent(out, indent_level + 4) indent(out, indent_level + 4)
<< "in_interpreter = 1;\n"; << "in_interpreter = 1;\n";
} }
if (!extra_cleanup.empty()) {
indent(out, indent_level + 3)
<< extra_cleanup << "\n";
}
return_expr = manage_return_value(out, indent_level + 4, remap, "return_value"); return_expr = manage_return_value(out, indent_level + 4, remap, "return_value");
test_assert(out, indent_level + 4); test_assert(out, indent_level + 4);
@ -501,6 +556,14 @@ pack_return_value(ostream &out, int indent_level,
<< return_expr << ".data(), " << return_expr << ".length());\n"; << return_expr << ".data(), " << return_expr << ".length());\n";
} }
} else if (TypeManager::is_unsigned_longlong(type)) {
indent(out, indent_level)
<< "return PyLong_FromUnsignedLongLong(" << return_expr << ");\n";
} else if (TypeManager::is_longlong(type)) {
indent(out, indent_level)
<< "return PyLong_FromLongLong(" << return_expr << ");\n";
} else if (TypeManager::is_integer(type)) { } else if (TypeManager::is_integer(type)) {
indent(out, indent_level) indent(out, indent_level)
<< "return PyInt_FromLong(" << return_expr << ");\n"; << "return PyInt_FromLong(" << return_expr << ");\n";

View File

@ -242,6 +242,9 @@ write_function_instance(ostream &out, InterfaceMaker::Function *func,
string parameter_list; string parameter_list;
string container; string container;
vector_string pexprs; vector_string pexprs;
string extra_convert;
string extra_param_check;
string extra_cleanup;
// Make one pass through the parameter list. We will output a // Make one pass through the parameter list. We will output a
// one-line temporary variable definition for each parameter, while // one-line temporary variable definition for each parameter, while
@ -283,6 +286,24 @@ write_function_instance(ostream &out, InterfaceMaker::Function *func,
parameter_list += ", &" + param_name; parameter_list += ", &" + param_name;
pexpr_string = "(PyObject_IsTrue(" + param_name + ")!=0)"; pexpr_string = "(PyObject_IsTrue(" + param_name + ")!=0)";
} else if (TypeManager::is_unsigned_longlong(type)) {
out << "PyObject *" << param_name;
format_specifiers += "O";
parameter_list += ", &" + param_name;
extra_convert += " PyObject *" + param_name + "_long = PyNumber_Long(" + param_name + ");";
extra_param_check += "|| (" + param_name + "_long == NULL)";
pexpr_string = "PyLong_AsUnsignedLongLong(" + param_name + "_long)";
extra_cleanup += " Py_XDECREF(" + param_name + "_long);";
} else if (TypeManager::is_longlong(type)) {
out << "PyObject *" << param_name;
format_specifiers += "O";
parameter_list += ", &" + param_name;
extra_convert += " PyObject *" + param_name + "_long = PyNumber_Long(" + param_name + ");";
extra_param_check += "|| (" + param_name + "_long == NULL)";
pexpr_string = "PyLong_AsLongLong(" + param_name + "_long)";
extra_cleanup += " Py_XDECREF(" + param_name + "_long);";
} else if (TypeManager::is_integer(type)) { } else if (TypeManager::is_integer(type)) {
out << "int " << param_name; out << "int " << param_name;
format_specifiers += "i"; format_specifiers += "i";
@ -327,6 +348,20 @@ write_function_instance(ostream &out, InterfaceMaker::Function *func,
out << " if (PyArg_ParseTuple(args, \"" << format_specifiers out << " if (PyArg_ParseTuple(args, \"" << format_specifiers
<< "\"" << parameter_list << ")) {\n"; << "\"" << parameter_list << ")) {\n";
if (!extra_convert.empty()) {
out << " " << extra_convert << "\n";
}
if (!extra_param_check.empty()) {
out << " if (" << extra_param_check.substr(3) << ") {\n";
if (!extra_cleanup.empty()) {
out << " " << extra_cleanup << "\n";
}
out << " PyErr_SetString(PyExc_TypeError, \"Invalid parameters.\");\n"
<< " return (PyObject *)NULL;\n"
<< " }\n";
}
if (track_interpreter) { if (track_interpreter) {
out << " in_interpreter = 0;\n"; out << " in_interpreter = 0;\n";
} }
@ -336,7 +371,6 @@ write_function_instance(ostream &out, InterfaceMaker::Function *func,
// Treat strings as a special case. We don't want to format the // Treat strings as a special case. We don't want to format the
// return expression. // return expression.
string return_expr = remap->call_function(out, 4, false, container, pexprs); string return_expr = remap->call_function(out, 4, false, container, pexprs);
CPPType *type = remap->_return_type->get_orig_type(); CPPType *type = remap->_return_type->get_orig_type();
out << " "; out << " ";
type->output_instance(out, "return_value", &parser); type->output_instance(out, "return_value", &parser);
@ -345,6 +379,9 @@ write_function_instance(ostream &out, InterfaceMaker::Function *func,
if (track_interpreter) { if (track_interpreter) {
out << " in_interpreter = 1;\n"; out << " in_interpreter = 1;\n";
} }
if (!extra_cleanup.empty()) {
out << " " << extra_cleanup << "\n";
}
return_expr = manage_return_value(out, 4, remap, "return_value"); return_expr = manage_return_value(out, 4, remap, "return_value");
test_assert(out, 4); test_assert(out, 4);
@ -356,6 +393,9 @@ write_function_instance(ostream &out, InterfaceMaker::Function *func,
if (track_interpreter) { if (track_interpreter) {
out << " in_interpreter = 1;\n"; out << " in_interpreter = 1;\n";
} }
if (!extra_cleanup.empty()) {
out << " " << extra_cleanup << "\n";
}
test_assert(out, 4); test_assert(out, 4);
out << " return Py_BuildValue(\"\");\n"; out << " return Py_BuildValue(\"\");\n";
@ -367,6 +407,9 @@ write_function_instance(ostream &out, InterfaceMaker::Function *func,
if (track_interpreter) { if (track_interpreter) {
out << " in_interpreter = 1;\n"; out << " in_interpreter = 1;\n";
} }
if (!extra_cleanup.empty()) {
out << " " << extra_cleanup << "\n";
}
return_expr = manage_return_value(out, 4, remap, "return_value"); return_expr = manage_return_value(out, 4, remap, "return_value");
test_assert(out, 4); test_assert(out, 4);
@ -403,6 +446,14 @@ pack_return_value(ostream &out, int indent_level,
<< return_expr << ".data(), " << return_expr << ".length());\n"; << return_expr << ".data(), " << return_expr << ".length());\n";
} }
} else if (TypeManager::is_unsigned_longlong(type)) {
indent(out, indent_level)
<< "return PyLong_FromUnsignedLongLong(" << return_expr << ");\n";
} else if (TypeManager::is_longlong(type)) {
indent(out, indent_level)
<< "return PyLong_FromLongLong(" << return_expr << ");\n";
} else if (TypeManager::is_integer(type)) { } else if (TypeManager::is_integer(type)) {
indent(out, indent_level) indent(out, indent_level)
<< "return PyInt_FromLong(" << return_expr << ");\n"; << "return PyInt_FromLong(" << return_expr << ");\n";

View File

@ -1787,7 +1787,11 @@ define_atomic_type(InterrogateType &itype, CPPSimpleType *cpptype) {
break; break;
case CPPSimpleType::T_int: case CPPSimpleType::T_int:
if ((cpptype->_flags & CPPSimpleType::F_longlong) != 0) {
itype._atomic_token = AT_longlong;
} else {
itype._atomic_token = AT_int; itype._atomic_token = AT_int;
}
break; break;
case CPPSimpleType::T_float: case CPPSimpleType::T_float:

View File

@ -489,6 +489,7 @@ is_bool(CPPType *type) {
simple_type->_type == CPPSimpleType::T_bool; simple_type->_type == CPPSimpleType::T_bool;
} }
} }
break;
default: default:
break; break;
@ -523,6 +524,67 @@ is_integer(CPPType *type) {
simple_type->_type == CPPSimpleType::T_int); simple_type->_type == CPPSimpleType::T_int);
} }
} }
break;
default:
break;
}
return false;
}
////////////////////////////////////////////////////////////////////
// Function: TypeManager::is_unsigned_longlong
// Access: Public, Static
// Description: Returns true if the indicated type is an unsigned
// "long long" type or larger, or at least a 64-bit
// unsigned integer.
////////////////////////////////////////////////////////////////////
bool TypeManager::
is_unsigned_longlong(CPPType *type) {
switch (type->get_subtype()) {
case CPPDeclaration::ST_const:
return is_unsigned_longlong(type->as_const_type()->_wrapped_around);
case CPPDeclaration::ST_simple:
{
CPPSimpleType *simple_type = type->as_simple_type();
if (simple_type != (CPPSimpleType *)NULL) {
return (simple_type->_type == CPPSimpleType::T_int &&
(simple_type->_flags & (CPPSimpleType::F_longlong | CPPSimpleType::F_unsigned)) == (CPPSimpleType::F_longlong | CPPSimpleType::F_unsigned));
}
}
break;
default:
break;
}
return false;
}
////////////////////////////////////////////////////////////////////
// Function: TypeManager::is_longlong
// Access: Public, Static
// Description: Returns true if the indicated type is the "long long"
// type or larger, or at least a 64-bit integer, whether
// signed or unsigned.
////////////////////////////////////////////////////////////////////
bool TypeManager::
is_longlong(CPPType *type) {
switch (type->get_subtype()) {
case CPPDeclaration::ST_const:
return is_longlong(type->as_const_type()->_wrapped_around);
case CPPDeclaration::ST_simple:
{
CPPSimpleType *simple_type = type->as_simple_type();
if (simple_type != (CPPSimpleType *)NULL) {
return (simple_type->_type == CPPSimpleType::T_int &&
(simple_type->_flags & CPPSimpleType::F_longlong) != 0);
}
}
break;
default: default:
break; break;
@ -553,6 +615,7 @@ is_float(CPPType *type) {
simple_type->_type == CPPSimpleType::T_double); simple_type->_type == CPPSimpleType::T_double);
} }
} }
break;
default: default:
break; break;
@ -609,10 +672,13 @@ is_reference_count(CPPType *type) {
} }
} }
} }
break;
default: default:
return false; break;
} }
return false;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////

View File

@ -70,6 +70,8 @@ public:
static bool is_const_ref_to_basic_string_char(CPPType *type); static bool is_const_ref_to_basic_string_char(CPPType *type);
static bool is_bool(CPPType *type); static bool is_bool(CPPType *type);
static bool is_integer(CPPType *type); static bool is_integer(CPPType *type);
static bool is_unsigned_longlong(CPPType *type);
static bool is_longlong(CPPType *type);
static bool is_float(CPPType *type); static bool is_float(CPPType *type);
static bool is_void(CPPType *type); static bool is_void(CPPType *type);
static bool is_reference_count(CPPType *type); static bool is_reference_count(CPPType *type);

View File

@ -85,7 +85,9 @@ enum AtomicToken {
// convention wrappers, atomic string means (const char *); for // convention wrappers, atomic string means (const char *); for
// other calling convention wrappers, atomic string means whatever // other calling convention wrappers, atomic string means whatever
// the native string representation is. // the native string representation is.
AT_string = 7 AT_string = 7,
AT_longlong = 8
}; };
EXPCL_DTOOLCONFIG void interrogate_add_search_directory(const char *dirname); EXPCL_DTOOLCONFIG void interrogate_add_search_directory(const char *dirname);