mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-01 01:07:51 -04:00
Improve interrogate code readability, use METH_STATIC for static methods, support anonymous enums
This commit is contained in:
parent
e98618b105
commit
f02662d4e0
@ -50,6 +50,7 @@ FunctionRemap(const InterrogateType &itype, const InterrogateFunction &ifunc,
|
||||
_num_default_parameters = num_default_parameters;
|
||||
_type = T_normal;
|
||||
_flags = 0;
|
||||
_args_type = 0;
|
||||
_wrapper_index = 0;
|
||||
|
||||
_return_value_needs_management = false;
|
||||
@ -648,11 +649,11 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
|
||||
}
|
||||
|
||||
if (_parameters.size() == first_param) {
|
||||
_flags |= F_no_args;
|
||||
_args_type = InterfaceMaker::AT_no_args;
|
||||
} else if (_parameters.size() == first_param + 1) {
|
||||
_flags |= F_single_arg;
|
||||
_args_type = InterfaceMaker::AT_single_arg;
|
||||
} else {
|
||||
_flags |= F_varargs;
|
||||
_args_type = InterfaceMaker::AT_varargs;
|
||||
}
|
||||
|
||||
if (_type == T_normal) {
|
||||
@ -670,7 +671,8 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
|
||||
if (_has_this && _parameters.size() > 2) {
|
||||
if (TypeManager::is_integer(_parameters[1]._remap->get_new_type())) {
|
||||
// Its first parameter is an int parameter, presumably an index.
|
||||
_flags |= (F_setitem_int | F_varargs);
|
||||
_flags |= F_setitem_int;
|
||||
_args_type = InterfaceMaker::AT_varargs;
|
||||
}
|
||||
}
|
||||
|
||||
@ -720,16 +722,16 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
|
||||
|
||||
} else if (fname == "operator ()" || fname == "__call__") {
|
||||
// Call operators always take keyword arguments.
|
||||
_flags |= (F_varargs | F_keyword_args);
|
||||
_args_type = InterfaceMaker::AT_keyword_args;
|
||||
|
||||
} else if (fname == "__setattr__" || fname == "__getattr__") {
|
||||
// Just to prevent these from getting keyword arguments.
|
||||
|
||||
} else {
|
||||
if (_flags & F_varargs) {
|
||||
if (_args_type == InterfaceMaker::AT_varargs) {
|
||||
// Every other method can take keyword arguments, if they
|
||||
// take more than one argument.
|
||||
_flags |= F_keyword_args;
|
||||
_args_type = InterfaceMaker::AT_keyword_args;
|
||||
}
|
||||
}
|
||||
|
||||
@ -743,7 +745,7 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
|
||||
|
||||
}
|
||||
// Constructors always take varargs and keyword args.
|
||||
_flags |= (F_varargs | F_keyword_args);
|
||||
_args_type = InterfaceMaker::AT_keyword_args;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -91,10 +91,6 @@ public:
|
||||
F_getbuffer = 0x0200,
|
||||
F_releasebuffer = 0x0400,
|
||||
F_compare_to = 0x0800,
|
||||
F_no_args = 0x1000,
|
||||
F_single_arg = 0x2000,
|
||||
F_varargs = 0x4000,
|
||||
F_keyword_args = 0x8000,
|
||||
};
|
||||
|
||||
typedef vector<Parameter> Parameters;
|
||||
@ -111,6 +107,7 @@ public:
|
||||
int _num_default_parameters;
|
||||
Type _type;
|
||||
int _flags;
|
||||
int _args_type;
|
||||
string _expression;
|
||||
string _function_signature;
|
||||
string _hash;
|
||||
|
@ -57,6 +57,7 @@ Function(const string &name,
|
||||
{
|
||||
_has_this = false;
|
||||
_flags = 0;
|
||||
_args_type = AT_unknown;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -632,13 +633,13 @@ record_function(const InterrogateType &itype, FunctionIndex func_index) {
|
||||
CPPInstance *cppfunc = (*ii).second;
|
||||
CPPFunctionType *ftype = cppfunc->_type->as_function_type();
|
||||
int max_default_parameters = 0;
|
||||
|
||||
|
||||
if (separate_overloading()) {
|
||||
// Count up the number of default parameters this function might
|
||||
// take.
|
||||
CPPParameterList *parameters = ftype->_parameters;
|
||||
CPPParameterList::Parameters::reverse_iterator pi;
|
||||
for (pi = parameters->_parameters.rbegin();
|
||||
for (pi = parameters->_parameters.rbegin();
|
||||
pi != parameters->_parameters.rend();
|
||||
++pi) {
|
||||
CPPInstance *param = (*pi);
|
||||
@ -651,7 +652,7 @@ record_function(const InterrogateType &itype, FunctionIndex func_index) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Now make a different wrapper for each combination of default
|
||||
// parameters. This will happen only if separate_overloading(),
|
||||
// tested above, returned true; otherwise, max_default_parameters
|
||||
@ -672,9 +673,10 @@ record_function(const InterrogateType &itype, FunctionIndex func_index) {
|
||||
}
|
||||
|
||||
func->_flags |= remap->_flags;
|
||||
func->_args_type = (ArgsType)((int)func->_args_type | (int)remap->_args_type);
|
||||
|
||||
// Make a wrapper for the function.
|
||||
FunctionWrapperIndex wrapper_index =
|
||||
FunctionWrapperIndex wrapper_index =
|
||||
remap->make_wrapper_entry(func_index);
|
||||
if (wrapper_index != 0) {
|
||||
InterrogateFunction &mod_ifunc = idb->update_function(func_index);
|
||||
@ -685,13 +687,6 @@ record_function(const InterrogateType &itype, FunctionIndex func_index) {
|
||||
}
|
||||
}
|
||||
|
||||
// If there's a remap taking no args and a remap
|
||||
// taking only a single arg, assume we need varargs.
|
||||
if ((func->_flags & FunctionRemap::F_no_args) &&
|
||||
(func->_flags & FunctionRemap::F_single_arg)) {
|
||||
func->_flags |= FunctionRemap::F_varargs;
|
||||
}
|
||||
|
||||
return func;
|
||||
}
|
||||
|
||||
|
@ -69,6 +69,28 @@ public:
|
||||
static ostream &indent(ostream &out, int indent_level);
|
||||
|
||||
public:
|
||||
// This contains information about the number
|
||||
// of arguments that the wrapping function should take.
|
||||
enum ArgsType {
|
||||
// This is deliberately engineered such that these
|
||||
// values can be OR'ed together to produce another
|
||||
// valid enum value.
|
||||
AT_unknown = 0x00,
|
||||
|
||||
// The method or function takes no arguments.
|
||||
AT_no_args = 0x01,
|
||||
|
||||
// There is only a single argument.
|
||||
AT_single_arg = 0x02,
|
||||
|
||||
// The method takes a variable number of arguments.
|
||||
AT_varargs = 0x03,
|
||||
|
||||
// The method may take keyword arguments, if appropriate
|
||||
// in the scripting language. Implies AT_varargs.
|
||||
AT_keyword_args = 0x07,
|
||||
};
|
||||
|
||||
class Function {
|
||||
public:
|
||||
Function(const string &name,
|
||||
@ -83,6 +105,7 @@ public:
|
||||
Remaps _remaps;
|
||||
bool _has_this;
|
||||
int _flags;
|
||||
ArgsType _args_type;
|
||||
};
|
||||
typedef vector<Function *> Functions;
|
||||
Functions _functions;
|
||||
|
@ -821,7 +821,7 @@ write_functions(ostream &out) {
|
||||
for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
|
||||
Function *func = (*fi);
|
||||
if (!func->_itype.is_global() && is_function_legal(func)) {
|
||||
write_function_for_top(out, NULL, func, "");
|
||||
write_function_for_top(out, NULL, func);
|
||||
}
|
||||
}
|
||||
|
||||
@ -872,29 +872,7 @@ write_class_details(ostream &out, Object *obj) {
|
||||
for (fi = obj->_methods.begin(); fi != obj->_methods.end(); ++fi) {
|
||||
Function *func = (*fi);
|
||||
if (func) {
|
||||
SlottedFunctionDef def;
|
||||
get_slotted_function_def(obj, func, def);
|
||||
|
||||
ostringstream GetThis;
|
||||
GetThis << " " << cClassName << " *local_this = NULL;\n";
|
||||
GetThis << " DTOOL_Call_ExtractThisPointerForType(self, &Dtool_" << ClassName << ", (void **)&local_this);\n";
|
||||
GetThis << " if (local_this == NULL) {\n";
|
||||
if (def._wrapper_type == WT_numeric_operator || def._wrapper_type == WT_ternary_operator) {
|
||||
// WT_numeric_operator means we must return NotImplemented, instead
|
||||
// of raising an exception, if the this pointer doesn't
|
||||
// match. This is for things like __sub__, which Python
|
||||
// likes to call on the wrong-type objects.
|
||||
GetThis << " Py_INCREF(Py_NotImplemented);\n";
|
||||
GetThis << " return Py_NotImplemented;\n";
|
||||
|
||||
} else {
|
||||
// Other functions should raise an exception if the this
|
||||
// pointer isn't set or is the wrong type.
|
||||
GetThis << " PyErr_SetString(PyExc_AttributeError, \"C++ object is not yet constructed, or already destructed.\");\n";
|
||||
GetThis << " return NULL;\n";
|
||||
}
|
||||
GetThis << " }\n";
|
||||
write_function_for_top(out, obj, func, GetThis.str());
|
||||
write_function_for_top(out, obj, func);
|
||||
}
|
||||
}
|
||||
|
||||
@ -915,7 +893,7 @@ write_class_details(ostream &out, Object *obj) {
|
||||
Function *func = (*fi);
|
||||
std::string fname = "int Dtool_Init_" + ClassName + "(PyObject *self, PyObject *args, PyObject *kwds)";
|
||||
|
||||
write_function_for_name(out, obj, func, fname, "", true, coercion_attempted, false, true, true, true);
|
||||
write_function_for_name(out, obj, func, fname, true, coercion_attempted, AT_keyword_args, true);
|
||||
}
|
||||
if (coercion_attempted) {
|
||||
// If a coercion attempt was written into the above constructor,
|
||||
@ -925,7 +903,7 @@ write_class_details(ostream &out, Object *obj) {
|
||||
Function *func = (*fi);
|
||||
std::string fname = "int Dtool_InitNoCoerce_" + ClassName + "(PyObject *self, PyObject *args)";
|
||||
|
||||
write_function_for_name(out, obj, func, fname, "", false, coercion_attempted, false, true, false, true);
|
||||
write_function_for_name(out, obj, func, fname, false, coercion_attempted, AT_varargs, true);
|
||||
}
|
||||
} else {
|
||||
// Otherwise, since the above constructor didn't involve any
|
||||
@ -1143,17 +1121,28 @@ write_module_support(ostream &out, ostream *out_h, InterrogateModuleDef *def) {
|
||||
string name1 = methodNameFromCppName(func, "", false);
|
||||
string name2 = methodNameFromCppName(func, "", true);
|
||||
|
||||
const char *flags;
|
||||
if (func->_flags & FunctionRemap::F_keyword_args) {
|
||||
string flags;
|
||||
switch (func->_args_type) {
|
||||
case AT_keyword_args:
|
||||
flags = "METH_VARARGS | METH_KEYWORDS";
|
||||
} else if (func->_flags & FunctionRemap::F_varargs) {
|
||||
break;
|
||||
|
||||
case AT_varargs:
|
||||
flags = "METH_VARARGS";
|
||||
} else if (func->_flags & FunctionRemap::F_single_arg) {
|
||||
break;
|
||||
|
||||
case AT_single_arg:
|
||||
flags = "METH_O";
|
||||
} else {
|
||||
break;
|
||||
|
||||
default:
|
||||
flags = "METH_NOARGS";
|
||||
break;
|
||||
}
|
||||
|
||||
// Note: we shouldn't add METH_STATIC here, since both METH_STATIC
|
||||
// and METH_CLASS are illegal for module-level functions.
|
||||
|
||||
out << " { \"" << name1 << "\", (PyCFunction) &"
|
||||
<< func->_name << ", " << flags << ", (const char *)" << func->_name << "_comment},\n";
|
||||
if (name1 != name2) {
|
||||
@ -1261,13 +1250,12 @@ write_module_class(ostream &out, Object *obj) {
|
||||
out << "//********************************************************************\n";
|
||||
out << "PyMethodDef Dtool_Methods_" << ClassName << "[] = {\n";
|
||||
|
||||
std::map<int, Function *> static_functions;
|
||||
std::map<Function *, SlottedFunctionDef> slotted_functions;
|
||||
// function Table
|
||||
bool got_copy = false;
|
||||
bool got_deepcopy = false;
|
||||
|
||||
int x = 0;
|
||||
//int x = 0;
|
||||
for (fi = obj->_methods.begin(); fi != obj->_methods.end(); ++fi) {
|
||||
Function *func = (*fi);
|
||||
if (func->_name == "__copy__") {
|
||||
@ -1276,33 +1264,39 @@ write_module_class(ostream &out, Object *obj) {
|
||||
got_deepcopy = true;
|
||||
}
|
||||
|
||||
if (!isFunctionWithThis(func)) {
|
||||
// Save a reference to this static method, so we can add it
|
||||
// directly to the class.
|
||||
static_functions[x] = func;
|
||||
}
|
||||
|
||||
string name1 = methodNameFromCppName(func, export_class_name, false);
|
||||
string name2 = methodNameFromCppName(func, export_class_name, true);
|
||||
|
||||
const char *flags;
|
||||
if (func->_flags & FunctionRemap::F_keyword_args) {
|
||||
string flags;
|
||||
switch (func->_args_type) {
|
||||
case AT_keyword_args:
|
||||
flags = "METH_VARARGS | METH_KEYWORDS";
|
||||
} else if (func->_flags & FunctionRemap::F_varargs) {
|
||||
break;
|
||||
|
||||
case AT_varargs:
|
||||
flags = "METH_VARARGS";
|
||||
} else if (func->_flags & FunctionRemap::F_single_arg) {
|
||||
break;
|
||||
|
||||
case AT_single_arg:
|
||||
flags = "METH_O";
|
||||
} else {
|
||||
break;
|
||||
|
||||
default:
|
||||
flags = "METH_NOARGS";
|
||||
break;
|
||||
}
|
||||
|
||||
if (!func->_has_this) {
|
||||
flags += " | METH_STATIC";
|
||||
}
|
||||
|
||||
out << " { \"" << name1 << "\", (PyCFunction) &"
|
||||
<< func->_name << ", " << flags << ", (char *) " << func->_name << "_comment},\n";
|
||||
++x;
|
||||
//++x;
|
||||
if (name1 != name2) {
|
||||
out << " { \"" << name2 << "\", (PyCFunction) &"
|
||||
<< func->_name << ", " << flags << ", (char *) " << func->_name << "_comment},\n";
|
||||
++x;
|
||||
//++x;
|
||||
}
|
||||
|
||||
SlottedFunctionDef slotted_def;
|
||||
@ -1384,17 +1378,21 @@ write_module_class(ostream &out, Object *obj) {
|
||||
bool func_varargs = true;
|
||||
string call_func;
|
||||
|
||||
if (func->_flags & FunctionRemap::F_keyword_args) {
|
||||
switch (func->_args_type) {
|
||||
case AT_keyword_args:
|
||||
call_func = func->_name + "(self, args, NULL)";
|
||||
break;
|
||||
|
||||
} else if (func->_flags & FunctionRemap::F_varargs) {
|
||||
case AT_varargs:
|
||||
call_func = func->_name + "(self, args)";
|
||||
break;
|
||||
|
||||
} else if (func->_flags & FunctionRemap::F_single_arg) {
|
||||
case AT_single_arg:
|
||||
func_varargs = false;
|
||||
call_func = func->_name + "(self, arg)";
|
||||
break;
|
||||
|
||||
} else {
|
||||
default:
|
||||
func_varargs = false;
|
||||
call_func = func->_name + "(self)";
|
||||
}
|
||||
@ -1536,7 +1534,8 @@ write_module_class(ostream &out, Object *obj) {
|
||||
|
||||
string expected_params;
|
||||
bool coercion_attempted = false;
|
||||
write_function_forset(out, obj, func, remaps, expected_params, 2, false, false, coercion_attempted, false, false, false, false, "index");
|
||||
write_function_forset(out, obj, func, remaps, expected_params, 2, false, false,
|
||||
coercion_attempted, AT_no_args, false, "index");
|
||||
|
||||
out << " return NULL;\n";
|
||||
out << "}\n\n";
|
||||
@ -1578,7 +1577,8 @@ write_module_class(ostream &out, Object *obj) {
|
||||
// very often, it's probably best to disable it for performance.
|
||||
string expected_params;
|
||||
bool coercion_attempted = false;
|
||||
write_function_forset(out, obj, func, remaps, expected_params, 2, false, false, coercion_attempted, true, false, false, true, "index");
|
||||
write_function_forset(out, obj, func, remaps, expected_params, 2, false, false,
|
||||
coercion_attempted, AT_single_arg, true, "index");
|
||||
|
||||
out << " if (!PyErr_Occurred()) {\n";
|
||||
out << " PyErr_SetString(PyExc_TypeError,\n";
|
||||
@ -1998,7 +1998,7 @@ write_module_class(ostream &out, Object *obj) {
|
||||
Function::Remaps::const_iterator ri;
|
||||
for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) {
|
||||
FunctionRemap *remap = (*ri);
|
||||
if (is_remap_legal(remap) && remap->_has_this && (remap->_flags & FunctionRemap::F_single_arg)) {
|
||||
if (is_remap_legal(remap) && remap->_has_this && (remap->_args_type == AT_single_arg)) {
|
||||
remaps.insert(remap);
|
||||
}
|
||||
}
|
||||
@ -2024,7 +2024,8 @@ write_module_class(ostream &out, Object *obj) {
|
||||
|
||||
string expected_params;
|
||||
bool coercion_attempted = false;
|
||||
write_function_forset(out, obj, func, remaps, expected_params, 4, false, true, coercion_attempted, true, false, false, false);
|
||||
write_function_forset(out, obj, func, remaps, expected_params, 4, false, true,
|
||||
coercion_attempted, AT_single_arg, false);
|
||||
|
||||
out << " if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_TypeError)) {\n";
|
||||
out << " PyErr_Clear();\n";
|
||||
@ -2213,7 +2214,14 @@ write_module_class(ostream &out, Object *obj) {
|
||||
int enum_count = nested_obj->_itype.number_of_enum_values();
|
||||
for (int xx = 0; xx < enum_count; xx++) {
|
||||
string name1 = classNameFromCppName(nested_obj->_itype.get_enum_value_name(xx), false);
|
||||
string name2 = classNameFromCppName(nested_obj->_itype.get_enum_value_name(xx), true);
|
||||
string name2;
|
||||
if (nested_obj->_itype.has_true_name()) {
|
||||
name2 = classNameFromCppName(nested_obj->_itype.get_enum_value_name(xx), true);
|
||||
} else {
|
||||
// Don't generate the alternative syntax for anonymous enums, since we added support
|
||||
// for those after we started deprecating the alternative syntax.
|
||||
name2 = name1;
|
||||
}
|
||||
int enum_value = nested_obj->_itype.get_enum_value(xx);
|
||||
out << "#if PY_MAJOR_VERSION >= 3\n";
|
||||
out << " PyDict_SetItemString(Dtool_" << ClassName << ".As_PyTypeObject().tp_dict, \"" << name1 << "\", PyLong_FromLong(" << enum_value << "));\n";
|
||||
@ -2242,25 +2250,6 @@ write_module_class(ostream &out, Object *obj) {
|
||||
// Why make the class a member of itself?
|
||||
//out << " PyDict_SetItemString(Dtool_" <<ClassName << ".As_PyTypeObject().tp_dict,\"" <<export_class_name<< "\",&Dtool_" <<ClassName << ".As_PyObject());\n";
|
||||
|
||||
// static function into dictionary with bogus self..
|
||||
//
|
||||
std::map<int , Function * >::iterator sfi;
|
||||
for (sfi = static_functions.begin(); sfi != static_functions.end(); sfi++) {
|
||||
out << " // Static Method " << methodNameFromCppName(sfi->second, export_class_name, false) << "\n";
|
||||
string name1 = methodNameFromCppName(sfi->second, export_class_name, false);
|
||||
string name2 = methodNameFromCppName(sfi->second, export_class_name, true);
|
||||
out << " PyDict_SetItemString(Dtool_" << ClassName
|
||||
<< ".As_PyTypeObject().tp_dict, \"" << name1
|
||||
<< "\", PyCFunction_New(&Dtool_Methods_" << ClassName << "[" << sfi->first
|
||||
<< "], &Dtool_" << ClassName << ".As_PyObject()));\n";
|
||||
if (name1 != name2) {
|
||||
out << " PyDict_SetItemString(Dtool_" << ClassName
|
||||
<< ".As_PyTypeObject().tp_dict, \"" << name2
|
||||
<< "\", PyCFunction_New(&Dtool_Methods_" << ClassName << "[" << sfi->first
|
||||
<< "], &Dtool_" << ClassName << ".As_PyObject()));\n";
|
||||
}
|
||||
}
|
||||
|
||||
bool is_runtime_typed = IsPandaTypedObject(obj->_itype._cpptype->as_struct_type());
|
||||
if (HasAGetClassTypeFunction(obj->_itype)) {
|
||||
is_runtime_typed = true;
|
||||
@ -2379,43 +2368,37 @@ write_prototype_for_name(ostream &out, InterfaceMaker::Function *func, const std
|
||||
// the indicated C++ function or method.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void InterfaceMakerPythonNative::
|
||||
write_function_for_top(ostream &out, InterfaceMaker::Object *obj, InterfaceMaker::Function *func, const std::string &PreProcess) {
|
||||
write_function_for_top(ostream &out, InterfaceMaker::Object *obj, InterfaceMaker::Function *func) {
|
||||
std::string fname;
|
||||
|
||||
bool single_arg = false;
|
||||
bool have_varargs = false;
|
||||
bool have_kwargs = false;
|
||||
|
||||
if ((func->_flags & FunctionRemap::F_keyword_args) != 0) {
|
||||
// Function takes both an args tuple and a kwargs dictionary.
|
||||
have_kwargs = true;
|
||||
have_varargs = true;
|
||||
} else if ((func->_flags & FunctionRemap::F_varargs) != 0) {
|
||||
// Function takes only an args tuple.
|
||||
have_varargs = true;
|
||||
} else if ((func->_flags & FunctionRemap::F_single_arg) != 0) {
|
||||
// Function takes a single PyObject* argument.
|
||||
single_arg = true;
|
||||
}
|
||||
|
||||
if (func->_ifunc.is_unary_op()) {
|
||||
assert(!single_arg);
|
||||
assert(!have_varargs);
|
||||
assert(!have_kwargs);
|
||||
assert(func->_args_type == AT_no_args);
|
||||
}
|
||||
|
||||
if (have_kwargs) {
|
||||
fname = "static PyObject *" + func->_name + "(PyObject *self, PyObject *args, PyObject *kwds)";
|
||||
} else if (have_varargs) {
|
||||
fname = "static PyObject *" + func->_name + "(PyObject *self, PyObject *args)";
|
||||
} else if (single_arg) {
|
||||
fname = "static PyObject *" + func->_name + "(PyObject *self, PyObject *arg)";
|
||||
} else {
|
||||
fname = "static PyObject *" + func->_name + "(PyObject *self)";
|
||||
fname = "static PyObject *" + func->_name + "(PyObject *";
|
||||
|
||||
// This will be NULL for static funcs, so prevent code from using it.
|
||||
if (func->_has_this) {
|
||||
fname += "self";
|
||||
}
|
||||
|
||||
switch (func->_args_type) {
|
||||
case AT_keyword_args:
|
||||
fname += ", PyObject *args, PyObject *kwds";
|
||||
break;
|
||||
|
||||
case AT_varargs:
|
||||
fname += ", PyObject *args";
|
||||
break;
|
||||
|
||||
case AT_single_arg:
|
||||
fname += ", PyObject *arg";
|
||||
break;
|
||||
}
|
||||
fname += ")";
|
||||
|
||||
bool coercion_attempted = false;
|
||||
write_function_for_name(out, obj, func, fname, PreProcess, true, coercion_attempted, single_arg, have_varargs, have_kwargs, false);
|
||||
write_function_for_name(out, obj, func, fname, true, coercion_attempted, func->_args_type, false);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -2424,10 +2407,10 @@ write_function_for_top(ostream &out, InterfaceMaker::Object *obj, InterfaceMaker
|
||||
// Wrap a complete name override function for Py.....
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void InterfaceMakerPythonNative::
|
||||
write_function_for_name(ostream &out1, InterfaceMaker::Object *obj, InterfaceMaker::Function *func,
|
||||
const std::string &function_name, const std::string &PreProcess,
|
||||
bool coercion_allowed, bool &coercion_attempted, bool single_arg,
|
||||
bool have_varargs, bool have_kwargs, bool return_int) {
|
||||
write_function_for_name(ostream &out1, InterfaceMaker::Object *obj, InterfaceMaker::Function *func,
|
||||
const std::string &function_name,
|
||||
bool coercion_allowed, bool &coercion_attempted,
|
||||
ArgsType args_type, bool return_int) {
|
||||
ostringstream out;
|
||||
|
||||
std::map<int, std::set<FunctionRemap *> > MapSets;
|
||||
@ -2458,8 +2441,33 @@ write_function_for_name(ostream &out1, InterfaceMaker::Object *obj, InterfaceMak
|
||||
out1 << " *******************************************************************/\n";
|
||||
|
||||
out << function_name << " {\n";
|
||||
if (isFunctionWithThis(func)) {
|
||||
out << PreProcess;
|
||||
|
||||
if (func->_has_this) {
|
||||
// Extract pointer from 'self' parameter.
|
||||
std::string ClassName = make_safe_name(obj->_itype.get_scoped_name());
|
||||
std::string cClassName = obj->_itype.get_true_name();
|
||||
|
||||
SlottedFunctionDef def;
|
||||
get_slotted_function_def(obj, func, def);
|
||||
|
||||
out << " " << cClassName << " *local_this = NULL;\n";
|
||||
out << " DTOOL_Call_ExtractThisPointerForType(self, &Dtool_" << ClassName << ", (void **)&local_this);\n";
|
||||
out << " if (local_this == NULL) {\n";
|
||||
if (def._wrapper_type == WT_numeric_operator || def._wrapper_type == WT_ternary_operator) {
|
||||
// WT_numeric_operator means we must return NotImplemented, instead
|
||||
// of raising an exception, if the this pointer doesn't
|
||||
// match. This is for things like __sub__, which Python
|
||||
// likes to call on the wrong-type objects.
|
||||
out << " Py_INCREF(Py_NotImplemented);\n";
|
||||
out << " return Py_NotImplemented;\n";
|
||||
|
||||
} else {
|
||||
// Other functions should raise an exception if the this
|
||||
// pointer isn't set or is the wrong type.
|
||||
out << " PyErr_SetString(PyExc_AttributeError, \"C++ object is not yet constructed, or already destructed.\");\n";
|
||||
out << " return NULL;\n";
|
||||
}
|
||||
out << " }\n";
|
||||
}
|
||||
|
||||
bool is_inplace = isInplaceFunction(func);
|
||||
@ -2477,27 +2485,37 @@ write_function_for_name(ostream &out1, InterfaceMaker::Object *obj, InterfaceMak
|
||||
if (MapSets.size() > 1) {
|
||||
string expected_params;
|
||||
|
||||
if (have_varargs) {
|
||||
switch (args_type) {
|
||||
case AT_keyword_args:
|
||||
indent(out, 2) << "int parameter_count = PyTuple_Size(args);\n";
|
||||
|
||||
if (have_kwargs) {
|
||||
if (args_type == AT_keyword_args) {
|
||||
indent(out, 2) << "if (kwds != NULL && PyDict_Check(kwds)) {\n";
|
||||
indent(out, 2) << " parameter_count += PyDict_Size(kwds);\n";
|
||||
indent(out, 2) << "}\n";
|
||||
}
|
||||
break;
|
||||
|
||||
} else if (single_arg) {
|
||||
case AT_varargs:
|
||||
indent(out, 2) << "int parameter_count = PyTuple_Size(args);\n";
|
||||
break;
|
||||
|
||||
case AT_single_arg:
|
||||
// It shouldń't get here, but we'll handle these cases nonetheless.
|
||||
indent(out, 2) << "const int parameter_count = 1;\n";
|
||||
break;
|
||||
|
||||
} else {
|
||||
default:
|
||||
indent(out, 2) << "const int parameter_count = 0;\n";
|
||||
break;
|
||||
}
|
||||
|
||||
indent(out, 2) << "switch (parameter_count) {\n";
|
||||
for (mii = MapSets.begin(); mii != MapSets.end(); mii ++) {
|
||||
indent(out, 2) << "case " << mii->first << ": {\n";
|
||||
|
||||
write_function_forset(out, obj, func, mii->second, expected_params, 4, is_inplace, coercion_allowed, coercion_attempted, single_arg, have_varargs, have_kwargs, return_int);
|
||||
write_function_forset(out, obj, func, mii->second, expected_params, 4, is_inplace,
|
||||
coercion_allowed, coercion_attempted, args_type, return_int);
|
||||
|
||||
indent(out, 4) << "break;\n";
|
||||
indent(out, 2) << "}\n";
|
||||
@ -2561,7 +2579,8 @@ write_function_for_name(ostream &out1, InterfaceMaker::Object *obj, InterfaceMak
|
||||
} else {
|
||||
string expected_params = "";
|
||||
for (mii = MapSets.begin(); mii != MapSets.end(); mii++) {
|
||||
write_function_forset(out, obj, func, mii->second, expected_params, 2, is_inplace, coercion_allowed, coercion_attempted, single_arg, have_varargs, have_kwargs, return_int);
|
||||
write_function_forset(out, obj, func, mii->second, expected_params, 2, is_inplace,
|
||||
coercion_allowed, coercion_attempted, args_type, return_int);
|
||||
}
|
||||
|
||||
out << " if (!PyErr_Occurred()) {\n";
|
||||
@ -2712,10 +2731,9 @@ write_function_forset(ostream &out, InterfaceMaker::Object *obj,
|
||||
std::set<FunctionRemap *> &remapsin,
|
||||
string &expected_params, int indent_level,
|
||||
bool is_inplace, bool coercion_allowed,
|
||||
bool &coercion_attempted, bool single_arg,
|
||||
bool have_varargs, bool have_kwargs,
|
||||
bool return_int,
|
||||
const string &first_pexpr) {
|
||||
bool &coercion_attempted,
|
||||
ArgsType args_type,
|
||||
bool return_int, const string &first_pexpr) {
|
||||
// Do we accept any parameters that are class objects? If so, we
|
||||
// might need to check for parameter coercion.
|
||||
bool coercion_possible = false;
|
||||
@ -2788,7 +2806,8 @@ write_function_forset(ostream &out, InterfaceMaker::Object *obj,
|
||||
indent(out, indent_level) << "// -2 ";
|
||||
remap->write_orig_prototype(out, 0); out << "\n";
|
||||
|
||||
write_function_instance(out, obj, func, remap, expected_params, indent_level + 2, is_inplace, coercion_possible, coercion_attempted, single_arg, have_varargs, have_kwargs, return_int, first_pexpr);
|
||||
write_function_instance(out, obj, func, remap, expected_params, indent_level + 2, is_inplace,
|
||||
coercion_possible, coercion_attempted, args_type, return_int, first_pexpr);
|
||||
|
||||
indent(out, indent_level + 2) << "PyErr_Clear();\n";
|
||||
indent(out, indent_level) << "}\n\n";
|
||||
@ -2811,7 +2830,8 @@ write_function_forset(ostream &out, InterfaceMaker::Object *obj,
|
||||
<< "// 1-" ;
|
||||
remap->write_orig_prototype(out, 0);
|
||||
out << "\n" ;
|
||||
write_function_instance(out, obj, func, remap, expected_params, indent_level, is_inplace, coercion_possible, coercion_attempted, single_arg, have_varargs, have_kwargs, return_int, first_pexpr);
|
||||
write_function_instance(out, obj, func, remap, expected_params, indent_level, is_inplace,
|
||||
coercion_possible, coercion_attempted, args_type, return_int, first_pexpr);
|
||||
|
||||
if (remap->_has_this && !remap->_const_method) {
|
||||
indent(out, indent_level - 2)
|
||||
@ -2894,8 +2914,7 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj,
|
||||
FunctionRemap *remap, string &expected_params,
|
||||
int indent_level, bool is_inplace,
|
||||
bool coercion_possible, bool &coercion_attempted,
|
||||
bool single_arg, bool have_varargs,
|
||||
bool have_kwargs, bool return_int,
|
||||
ArgsType args_type, bool return_int,
|
||||
const string &first_pexpr) {
|
||||
string format_specifiers;
|
||||
std::string keyword_list;
|
||||
@ -3034,7 +3053,7 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj,
|
||||
} else {
|
||||
indent(out, indent_level) << "char *" << param_name << "_str;\n";
|
||||
indent(out, indent_level) << "Py_ssize_t " << param_name << "_len;\n";
|
||||
if (single_arg) {
|
||||
if (args_type == AT_single_arg) {
|
||||
out << "#if PY_MAJOR_VERSION >= 3\n";
|
||||
indent(out, indent_level)
|
||||
<< param_name << "_str = PyUnicode_AsUTF8AndSize(arg, &"
|
||||
@ -3068,7 +3087,7 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj,
|
||||
only_pyobjects = false;
|
||||
|
||||
} else if (TypeManager::is_bool(type)) {
|
||||
if (single_arg) {
|
||||
if (args_type == AT_single_arg) {
|
||||
param_name = "arg";
|
||||
} else {
|
||||
indent(out, indent_level) << "PyObject *" << param_name << ";\n";
|
||||
@ -3080,7 +3099,7 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj,
|
||||
++num_params;
|
||||
|
||||
} else if (TypeManager::is_unsigned_longlong(type)) {
|
||||
if (single_arg) {
|
||||
if (args_type == AT_single_arg) {
|
||||
param_name = "arg";
|
||||
} else {
|
||||
indent(out, indent_level) << "PyObject *" << param_name << ";\n";
|
||||
@ -3095,7 +3114,7 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj,
|
||||
++num_params;
|
||||
|
||||
} else if (TypeManager::is_longlong(type)) {
|
||||
if (single_arg) {
|
||||
if (args_type == AT_single_arg) {
|
||||
param_name = "arg";
|
||||
} else {
|
||||
indent(out, indent_level) << "PyObject *" << param_name << ";\n";
|
||||
@ -3110,7 +3129,7 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj,
|
||||
++num_params;
|
||||
|
||||
} else if (TypeManager::is_unsigned_integer(type)) {
|
||||
if (single_arg) {
|
||||
if (args_type == AT_single_arg) {
|
||||
param_name = "arg";
|
||||
} else {
|
||||
indent(out, indent_level) << "PyObject *" << param_name << ";\n";
|
||||
@ -3126,7 +3145,7 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj,
|
||||
++num_params;
|
||||
|
||||
} else if (TypeManager::is_integer(type)) {
|
||||
if (single_arg) {
|
||||
if (args_type == AT_single_arg) {
|
||||
pexpr_string = "(" + type->get_local_name(&parser) + ")PyInt_AS_LONG(arg)";
|
||||
extra_param_check += " && PyInt_Check(arg)";
|
||||
} else {
|
||||
@ -3139,7 +3158,7 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj,
|
||||
++num_params;
|
||||
|
||||
} else if (TypeManager::is_double(type)) {
|
||||
if (single_arg) {
|
||||
if (args_type == AT_single_arg) {
|
||||
pexpr_string = "PyFloat_AsDouble(arg)";
|
||||
extra_param_check += " && PyNumber_Check(arg)";
|
||||
} else {
|
||||
@ -3152,7 +3171,7 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj,
|
||||
++num_params;
|
||||
|
||||
} else if (TypeManager::is_float(type)) {
|
||||
if (single_arg) {
|
||||
if (args_type == AT_single_arg) {
|
||||
pexpr_string = "(float) PyFloat_AsDouble(arg)";
|
||||
extra_param_check += " && PyNumber_Check(arg)";
|
||||
} else {
|
||||
@ -3173,7 +3192,7 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj,
|
||||
++num_params;
|
||||
|
||||
} else if (TypeManager::is_pointer_to_PyObject(type)) {
|
||||
if (single_arg) {
|
||||
if (args_type == AT_single_arg) {
|
||||
// This is a single-arg function, so there's no need
|
||||
// to convert anything.
|
||||
param_name = "arg";
|
||||
@ -3191,7 +3210,7 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj,
|
||||
check_exceptions = true;
|
||||
|
||||
} else if (TypeManager::is_pointer_to_Py_buffer(type)) {
|
||||
if (single_arg) {
|
||||
if (args_type == AT_single_arg) {
|
||||
param_name = "arg";
|
||||
} else {
|
||||
indent(out, indent_level) << "PyObject *" << param_name << ";\n";
|
||||
@ -3218,7 +3237,7 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj,
|
||||
expected_params += classNameFromCppName(obj_type->get_simple_name(), false);
|
||||
|
||||
if (!remap->_has_this || pn != 0) {
|
||||
if (single_arg) {
|
||||
if (args_type == AT_single_arg) {
|
||||
param_name = "arg";
|
||||
} else {
|
||||
indent(out, indent_level) << "PyObject *" << param_name << ";\n";
|
||||
@ -3278,7 +3297,7 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj,
|
||||
|
||||
} else {
|
||||
// Ignore a parameter.
|
||||
if (single_arg) {
|
||||
if (args_type == AT_single_arg) {
|
||||
param_name = "arg";
|
||||
} else {
|
||||
indent(out, indent_level) << "PyObject *" << param_name << ";\n";
|
||||
@ -3318,7 +3337,9 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj,
|
||||
std::string format_specifiers1 = format_specifiers + ":" +
|
||||
methodNameFromCppName(func, "", false);
|
||||
|
||||
if (have_kwargs) {
|
||||
switch (args_type) {
|
||||
case AT_keyword_args:
|
||||
// Wrapper takes a varargs tuple and a keyword args dict.
|
||||
indent(out, indent_level)
|
||||
<< "static char *keyword_list[] = {" << keyword_list << "NULL};\n";
|
||||
indent(out, indent_level)
|
||||
@ -3328,8 +3349,10 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj,
|
||||
|
||||
++open_scopes;
|
||||
indent_level += 2;
|
||||
break;
|
||||
|
||||
} else if (have_varargs) {
|
||||
case AT_varargs:
|
||||
// Wrapper takes a varargs tuple.
|
||||
if (only_pyobjects) {
|
||||
// All parameters are PyObject*, so we can use the slightly
|
||||
// more efficient PyArg_UnpackTuple function instead.
|
||||
@ -3347,16 +3370,18 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj,
|
||||
}
|
||||
++open_scopes;
|
||||
indent_level += 2;
|
||||
break;
|
||||
|
||||
} else if (single_arg && !only_pyobjects &&
|
||||
format_specifiers != "" &&
|
||||
format_specifiers != "O") {
|
||||
indent(out, indent_level)
|
||||
<< "if (PyArg_Parse(arg, \"" << format_specifiers << "\""
|
||||
<< parameter_list << ")) {\n";
|
||||
case AT_single_arg:
|
||||
// Wrapper takes a single PyObject* argument.
|
||||
if (!only_pyobjects && format_specifiers != "O") {
|
||||
indent(out, indent_level)
|
||||
<< "if (PyArg_Parse(arg, \"" << format_specifiers << "\""
|
||||
<< parameter_list << ")) {\n";
|
||||
|
||||
++open_scopes;
|
||||
indent_level += 2;
|
||||
++open_scopes;
|
||||
indent_level += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -4155,23 +4180,6 @@ is_function_legal(Function *func) {
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Function : isFunctionWithThis
|
||||
//
|
||||
// If any rempas have a this .. this function has a this..( of self) to python..
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
bool InterfaceMakerPythonNative::
|
||||
isFunctionWithThis(Function *func) {
|
||||
Function::Remaps::const_iterator ri;
|
||||
for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) {
|
||||
FunctionRemap *remap = (*ri);
|
||||
if (remap->_has_this) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// Function : IsRunTimeTyped
|
||||
///////////////////////////////////////////////////////
|
||||
|
@ -27,8 +27,7 @@ class FunctionRemap;
|
||||
// Description : An InterfaceMaker for generating complex Python
|
||||
// function wrappers around C++ code.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class InterfaceMakerPythonNative : public InterfaceMakerPython
|
||||
{
|
||||
class InterfaceMakerPythonNative : public InterfaceMakerPython {
|
||||
public:
|
||||
InterfaceMakerPythonNative(InterrogateModuleDef *def);
|
||||
virtual ~InterfaceMakerPythonNative();
|
||||
@ -92,27 +91,24 @@ private:
|
||||
|
||||
void write_prototype_for_name(ostream &out, Function *func, const std::string &name);
|
||||
void write_prototype_for(ostream &out, Function *func);
|
||||
void write_function_for_top(ostream &out, Object *obj, Function *func, const std::string &PreProcess);
|
||||
void write_function_for_top(ostream &out, Object *obj, Function *func);
|
||||
void write_function_for_name(ostream &out, Object *obj, Function *func,
|
||||
const std::string &name, const std::string &PreProcess,
|
||||
const std::string &name,
|
||||
bool coercion_allowed, bool &coercion_attempted,
|
||||
bool single_arg, bool have_varargs,
|
||||
bool have_kwargs, bool return_int);
|
||||
ArgsType args_type, bool return_int);
|
||||
|
||||
void write_function_forset(ostream &out, Object *obj, Function *func,
|
||||
std::set<FunctionRemap*> &remaps, string &expected_params,
|
||||
int indent_level, bool inplace,
|
||||
bool coercion_allowed, bool &coercion_attempted,
|
||||
bool single_arg, bool have_varargs,
|
||||
bool have_kwargs, bool return_int,
|
||||
ArgsType args_type, bool return_int,
|
||||
const string &first_expr = string());
|
||||
|
||||
void write_function_instance(ostream &out, Object *obj, Function *func,
|
||||
FunctionRemap *remap, string &expected_params,
|
||||
int indent_level, bool is_inplace,
|
||||
bool coercion_allowed, bool &coercion_attempted,
|
||||
bool single_arg, bool have_varargs,
|
||||
bool have_kwargs, bool return_int,
|
||||
ArgsType args_type, bool return_int,
|
||||
const string &first_pexpr = string());
|
||||
|
||||
void pack_return_value(ostream &out, int indent_level, FunctionRemap *remap,
|
||||
|
@ -1863,26 +1863,34 @@ get_type(CPPType *type, bool global) {
|
||||
|
||||
// First, check to see if it's already there.
|
||||
string true_name = type->get_local_name(&parser);
|
||||
TypesByName::const_iterator tni = _types_by_name.find(true_name);
|
||||
if (tni != _types_by_name.end()) {
|
||||
// It's already here, so update the global flag.
|
||||
index = (*tni).second;
|
||||
if (index == 0) {
|
||||
// This is an invalid type; we don't know anything about it.
|
||||
return 0;
|
||||
}
|
||||
|
||||
InterrogateType &itype = InterrogateDatabase::get_ptr()->update_type(index);
|
||||
if (global) {
|
||||
itype._flags |= InterrogateType::F_global;
|
||||
}
|
||||
if (true_name.empty()) {
|
||||
// Whoops, it's an anonymous type. That's okay, because we'll
|
||||
// usually only encounter them once anyway, so let's go ahead and
|
||||
// define it without checking in _types_by_name.
|
||||
|
||||
if ((itype._flags & InterrogateType::F_fully_defined) != 0) {
|
||||
return index;
|
||||
}
|
||||
} else {
|
||||
TypesByName::const_iterator tni = _types_by_name.find(true_name);
|
||||
if (tni != _types_by_name.end()) {
|
||||
// It's already here, so update the global flag.
|
||||
index = (*tni).second;
|
||||
if (index == 0) {
|
||||
// This is an invalid type; we don't know anything about it.
|
||||
return 0;
|
||||
}
|
||||
|
||||
// But wait--it's not fully defined yet! We'll go ahead and
|
||||
// define it now.
|
||||
InterrogateType &itype = InterrogateDatabase::get_ptr()->update_type(index);
|
||||
if (global) {
|
||||
itype._flags |= InterrogateType::F_global;
|
||||
}
|
||||
|
||||
if ((itype._flags & InterrogateType::F_fully_defined) != 0) {
|
||||
return index;
|
||||
}
|
||||
|
||||
// But wait--it's not fully defined yet! We'll go ahead and
|
||||
// define it now.
|
||||
}
|
||||
}
|
||||
|
||||
bool forced = in_forcetype(true_name);
|
||||
@ -1890,7 +1898,9 @@ get_type(CPPType *type, bool global) {
|
||||
if (index == 0) {
|
||||
// It isn't already there, so we have to define it.
|
||||
index = InterrogateDatabase::get_ptr()->get_next_index();
|
||||
_types_by_name[true_name] = index;
|
||||
if (!true_name.empty()) {
|
||||
_types_by_name[true_name] = index;
|
||||
}
|
||||
|
||||
InterrogateType itype;
|
||||
if (global) {
|
||||
@ -1904,7 +1914,7 @@ get_type(CPPType *type, bool global) {
|
||||
InterrogateDatabase::get_ptr()->update_type(index);
|
||||
|
||||
itype._name = get_preferred_name(type);
|
||||
|
||||
|
||||
int num_alt_names = type->get_num_alt_names();
|
||||
if (num_alt_names != 0) {
|
||||
itype._alt_names.clear();
|
||||
@ -1954,23 +1964,19 @@ get_type(CPPType *type, bool global) {
|
||||
}
|
||||
}
|
||||
|
||||
if (forced || !in_ignoretype(true_name))
|
||||
{
|
||||
if (forced || !in_ignoretype(true_name)) {
|
||||
itype._flags |= InterrogateType::F_fully_defined;
|
||||
|
||||
if (type->as_simple_type() != (CPPSimpleType *)NULL)
|
||||
{
|
||||
if (type->as_simple_type() != (CPPSimpleType *)NULL) {
|
||||
define_atomic_type(itype, type->as_simple_type());
|
||||
|
||||
} else if (type->as_pointer_type() != (CPPPointerType *)NULL)
|
||||
{
|
||||
} else if (type->as_pointer_type() != (CPPPointerType *)NULL) {
|
||||
define_wrapped_type(itype, type->as_pointer_type());
|
||||
|
||||
} else if (type->as_const_type() != (CPPConstType *)NULL) {
|
||||
define_wrapped_type(itype, type->as_const_type());
|
||||
|
||||
} else if (type->as_struct_type() != (CPPStructType *)NULL)
|
||||
{
|
||||
} else if (type->as_struct_type() != (CPPStructType *)NULL) {
|
||||
define_struct_type(itype, type->as_struct_type(), index, forced);
|
||||
|
||||
} else if (type->as_enum_type() != (CPPEnumType *)NULL) {
|
||||
@ -1984,7 +1990,9 @@ get_type(CPPType *type, bool global) {
|
||||
|
||||
// Remove the type from the database.
|
||||
InterrogateDatabase::get_ptr()->remove_type(index);
|
||||
_types_by_name[true_name] = 0;
|
||||
if (!true_name.empty()) {
|
||||
_types_by_name[true_name] = 0;
|
||||
}
|
||||
index = 0;
|
||||
}
|
||||
}
|
||||
@ -2229,6 +2237,7 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype,
|
||||
for (di = scope->_declarations.begin();
|
||||
di != scope->_declarations.end();
|
||||
++di) {
|
||||
|
||||
if ((*di)->get_subtype() == CPPDeclaration::ST_instance) {
|
||||
CPPInstance *inst = (*di)->as_instance();
|
||||
if (inst->_type->get_subtype() == CPPDeclaration::ST_function) {
|
||||
@ -2243,15 +2252,12 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype,
|
||||
}
|
||||
}
|
||||
|
||||
} else if ((*di)->get_subtype() == CPPDeclaration::ST_type_declaration)
|
||||
{
|
||||
} else if ((*di)->get_subtype() == CPPDeclaration::ST_type_declaration) {
|
||||
CPPType *type = (*di)->as_type_declaration()->_type;
|
||||
|
||||
if ((*di)->_vis <= min_vis || in_forcetype(type->get_local_name(&parser)))
|
||||
{
|
||||
if ((*di)->_vis <= min_vis || in_forcetype(type->get_local_name(&parser))) {
|
||||
if (type->as_struct_type() != (CPPStructType *)NULL ||
|
||||
type->as_enum_type() != (CPPEnumType *)NULL)
|
||||
{
|
||||
type->as_enum_type() != (CPPEnumType *)NULL) {
|
||||
// Here's a nested class or enum definition.
|
||||
type->_vis = (*di)->_vis;
|
||||
|
||||
@ -2259,13 +2265,20 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype,
|
||||
assert(nested_type != (CPPExtensionType *)NULL);
|
||||
|
||||
// Only try to export named types.
|
||||
if (nested_type->_ident != (CPPIdentifier *)NULL)
|
||||
{
|
||||
if (nested_type->_ident != (CPPIdentifier *)NULL) {
|
||||
TypeIndex nested_index = get_type(nested_type, false);
|
||||
itype._nested_types.push_back(nested_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if ((*di)->get_subtype() == CPPDeclaration::ST_enum) {
|
||||
CPPType *type = (*di)->as_enum_type();
|
||||
|
||||
// An anonymous enum type.
|
||||
if ((*di)->_vis <= min_vis) {
|
||||
TypeIndex nested_index = get_type(type, false);
|
||||
itype._nested_types.push_back(nested_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user