mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 10:22:45 -04:00
fix performance issues with implicit parameter coercion
This commit is contained in:
parent
82fccf788d
commit
4cd50fa68d
@ -2134,6 +2134,8 @@ write_function_forset(ostream &out, InterfaceMaker::Object *obj,
|
|||||||
<< "PyObject *coerced = NULL;\n";
|
<< "PyObject *coerced = NULL;\n";
|
||||||
indent(out,indent_level)
|
indent(out,indent_level)
|
||||||
<< "PyObject **coerced_ptr = NULL;\n";
|
<< "PyObject **coerced_ptr = NULL;\n";
|
||||||
|
indent(out,indent_level)
|
||||||
|
<< "bool report_errors = false;\n";
|
||||||
indent(out,indent_level)
|
indent(out,indent_level)
|
||||||
<< "while (true) {\n";
|
<< "while (true) {\n";
|
||||||
indent_level += 2;
|
indent_level += 2;
|
||||||
@ -2219,16 +2221,28 @@ write_function_forset(ostream &out, InterfaceMaker::Object *obj,
|
|||||||
if (coercion_possible) {
|
if (coercion_possible) {
|
||||||
// Try again, this time with coercion enabled.
|
// Try again, this time with coercion enabled.
|
||||||
indent(out,indent_level)
|
indent(out,indent_level)
|
||||||
<< "if (coerced_ptr != NULL) {\n";
|
<< "if (coerced_ptr == NULL && !report_errors) {\n";
|
||||||
indent(out,indent_level + 2)
|
indent(out,indent_level + 2)
|
||||||
<< "break;\n";
|
<< "coerced_ptr = &coerced;\n";
|
||||||
|
indent(out,indent_level + 2)
|
||||||
|
<< "continue;\n";
|
||||||
indent(out,indent_level)
|
indent(out,indent_level)
|
||||||
<< "}\n";
|
<< "}\n";
|
||||||
|
|
||||||
|
// No dice. Go back one more time, and this time get the error
|
||||||
|
// message.
|
||||||
indent(out,indent_level)
|
indent(out,indent_level)
|
||||||
<< "PyErr_Clear();\n";
|
<< "if (!report_errors) {\n";
|
||||||
|
indent(out,indent_level + 2)
|
||||||
|
<< "report_errors = true;\n";
|
||||||
|
indent(out,indent_level + 2)
|
||||||
|
<< "continue;\n";
|
||||||
indent(out,indent_level)
|
indent(out,indent_level)
|
||||||
<< "coerced_ptr = &coerced;\n";
|
<< "}\n";
|
||||||
|
|
||||||
|
// We've been through three times. We're done.
|
||||||
|
indent(out,indent_level)
|
||||||
|
<< "break;\n";
|
||||||
|
|
||||||
indent_level -= 2;
|
indent_level -= 2;
|
||||||
indent(out,indent_level)
|
indent(out,indent_level)
|
||||||
@ -2453,9 +2467,9 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj,
|
|||||||
if (coercion_possible && !is_copy_constructor) {
|
if (coercion_possible && !is_copy_constructor) {
|
||||||
// We never attempt to coerce a copy constructor parameter.
|
// We never attempt to coerce a copy constructor parameter.
|
||||||
// That would lead to infinite recursion.
|
// That would lead to infinite recursion.
|
||||||
str << ", coerced_ptr";
|
str << ", coerced_ptr, report_errors";
|
||||||
} else {
|
} else {
|
||||||
str << ", NULL";
|
str << ", NULL, true";
|
||||||
}
|
}
|
||||||
str << ");\n";
|
str << ");\n";
|
||||||
|
|
||||||
|
@ -94,10 +94,24 @@ attempt_coercion(PyObject *self, Dtool_PyTypedObject *classdef,
|
|||||||
// temporary object. Weird.
|
// temporary object. Weird.
|
||||||
Py_DECREF(obj);
|
Py_DECREF(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clear the error returned by the coercion constructor. It's not
|
||||||
|
// the error message we want to report.
|
||||||
|
PyErr_Clear();
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Temporary function to preserve backward compatibility.
|
||||||
|
void *
|
||||||
|
DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef,
|
||||||
|
int param, const string &function_name, bool const_ok,
|
||||||
|
PyObject **coerced) {
|
||||||
|
return DTOOL_Call_GetPointerThisClass(self, classdef,
|
||||||
|
param, function_name, const_ok,
|
||||||
|
coerced, true);
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: DTOOL_Call_GetPointerThisClass
|
// Function: DTOOL_Call_GetPointerThisClass
|
||||||
// Description: Extracts the C++ pointer for an object, given its
|
// Description: Extracts the C++ pointer for an object, given its
|
||||||
@ -140,7 +154,10 @@ attempt_coercion(PyObject *self, Dtool_PyTypedObject *classdef,
|
|||||||
void *
|
void *
|
||||||
DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef,
|
DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef,
|
||||||
int param, const string &function_name, bool const_ok,
|
int param, const string &function_name, bool const_ok,
|
||||||
PyObject **coerced) {
|
PyObject **coerced, bool report_errors) {
|
||||||
|
if (PyErr_Occurred()) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
if (self != NULL) {
|
if (self != NULL) {
|
||||||
if (DtoolCanThisBeAPandaInstance(self)) {
|
if (DtoolCanThisBeAPandaInstance(self)) {
|
||||||
Dtool_PyTypedObject *my_type = ((Dtool_PyInstDef *)self)->_My_Type;
|
Dtool_PyTypedObject *my_type = ((Dtool_PyInstDef *)self)->_My_Type;
|
||||||
@ -150,16 +167,53 @@ DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ostringstream str;
|
if (report_errors) {
|
||||||
str << function_name << "() argument " << param << " may not be const";
|
ostringstream str;
|
||||||
string msg = str.str();
|
str << function_name << "() argument " << param << " may not be const";
|
||||||
PyErr_SetString(PyExc_TypeError, msg.c_str());
|
string msg = str.str();
|
||||||
|
PyErr_SetString(PyExc_TypeError, msg.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
if (report_errors) {
|
||||||
|
ostringstream str;
|
||||||
|
str << function_name << "() argument " << param << " must be ";
|
||||||
|
|
||||||
|
|
||||||
|
PyObject *fname = PyObject_GetAttrString((PyObject *)classdef, "__name__");
|
||||||
|
if (fname != (PyObject *)NULL) {
|
||||||
|
str << PyString_AsString(fname);
|
||||||
|
Py_DECREF(fname);
|
||||||
|
} else {
|
||||||
|
str << classdef->_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *tname = PyObject_GetAttrString((PyObject *)self->ob_type, "__name__");
|
||||||
|
if (tname != (PyObject *)NULL) {
|
||||||
|
str << ", not " << PyString_AsString(tname);
|
||||||
|
Py_DECREF(tname);
|
||||||
|
} else {
|
||||||
|
str << ", not " << my_type->_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
string msg = str.str();
|
||||||
|
PyErr_SetString(PyExc_TypeError, msg.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// The parameter was not a Panda type. Can we coerce it to the
|
||||||
|
// appropriate type, by creating a temporary object?
|
||||||
|
void *result = attempt_coercion(self, classdef, coerced);
|
||||||
|
if (result != NULL) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Coercion failed.
|
||||||
|
if (report_errors) {
|
||||||
ostringstream str;
|
ostringstream str;
|
||||||
str << function_name << "() argument " << param << " must be ";
|
str << function_name << "() argument " << param << " must be ";
|
||||||
|
|
||||||
|
|
||||||
PyObject *fname = PyObject_GetAttrString((PyObject *)classdef, "__name__");
|
PyObject *fname = PyObject_GetAttrString((PyObject *)classdef, "__name__");
|
||||||
if (fname != (PyObject *)NULL) {
|
if (fname != (PyObject *)NULL) {
|
||||||
str << PyString_AsString(fname);
|
str << PyString_AsString(fname);
|
||||||
@ -172,45 +226,16 @@ DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef,
|
|||||||
if (tname != (PyObject *)NULL) {
|
if (tname != (PyObject *)NULL) {
|
||||||
str << ", not " << PyString_AsString(tname);
|
str << ", not " << PyString_AsString(tname);
|
||||||
Py_DECREF(tname);
|
Py_DECREF(tname);
|
||||||
} else {
|
|
||||||
str << ", not " << my_type->_name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string msg = str.str();
|
string msg = str.str();
|
||||||
PyErr_SetString(PyExc_TypeError, msg.c_str());
|
PyErr_SetString(PyExc_TypeError, msg.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
|
||||||
// The parameter was not a Panda type. Can we coerce it to the
|
|
||||||
// appropriate type, by creating a temporary object?
|
|
||||||
void *result = attempt_coercion(self, classdef, coerced);
|
|
||||||
if (result != NULL) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Coercion failed.
|
|
||||||
ostringstream str;
|
|
||||||
str << function_name << "() argument " << param << " must be ";
|
|
||||||
|
|
||||||
PyObject *fname = PyObject_GetAttrString((PyObject *)classdef, "__name__");
|
|
||||||
if (fname != (PyObject *)NULL) {
|
|
||||||
str << PyString_AsString(fname);
|
|
||||||
Py_DECREF(fname);
|
|
||||||
} else {
|
|
||||||
str << classdef->_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyObject *tname = PyObject_GetAttrString((PyObject *)self->ob_type, "__name__");
|
|
||||||
if (tname != (PyObject *)NULL) {
|
|
||||||
str << ", not " << PyString_AsString(tname);
|
|
||||||
Py_DECREF(tname);
|
|
||||||
}
|
|
||||||
|
|
||||||
string msg = str.str();
|
|
||||||
PyErr_SetString(PyExc_TypeError, msg.c_str());
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
PyErr_SetString(PyExc_TypeError, "Self Is Null");
|
if (report_errors) {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "Self Is Null");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -364,6 +364,8 @@ EXPCL_DTOOLCONFIG bool DtoolCanThisBeAPandaInstance(PyObject *self);
|
|||||||
EXPCL_DTOOLCONFIG void DTOOL_Call_ExtractThisPointerForType(PyObject *self, Dtool_PyTypedObject * classdef, void ** answer);
|
EXPCL_DTOOLCONFIG void DTOOL_Call_ExtractThisPointerForType(PyObject *self, Dtool_PyTypedObject * classdef, void ** answer);
|
||||||
|
|
||||||
|
|
||||||
|
EXPCL_DTOOLCONFIG void * DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef, int param, const string &function_name, bool const_ok, PyObject **coerced, bool report_errors);
|
||||||
|
|
||||||
EXPCL_DTOOLCONFIG void * DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef, int param, const string &function_name, bool const_ok, PyObject **coerced);
|
EXPCL_DTOOLCONFIG void * DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef, int param, const string &function_name, bool const_ok, PyObject **coerced);
|
||||||
|
|
||||||
EXPCL_DTOOLCONFIG void * DTOOL_Call_GetPointerThis(PyObject *self);
|
EXPCL_DTOOLCONFIG void * DTOOL_Call_GetPointerThis(PyObject *self);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user