diff options
author | Campbell Barton <ideasman42@gmail.com> | 2009-04-03 18:51:06 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2009-04-03 18:51:06 +0400 |
commit | fd2b1156783d52dbb7c93c53fe008d9e14cbffdd (patch) | |
tree | 3578443cee384e883450b35480244a0c46aaf34b /source/gameengine/Expressions/PyObjectPlus.cpp | |
parent | e30cb79aaa8d9a25b66c57aa08fb79bf591b6be4 (diff) |
Python BGE API
- Initialize python types with PyType_Ready, which adds methods to the type dictionary.
- use Pythons get/setattro (uses a python string for the attribute rather then char*). Using basic C strings seems nice but internally python converts them to python strings and discards them for most functions that accept char arrays.
- Method lookups use the PyTypes dictionary (should be faster then Py_FindMethod)
- Renamed __getattr -> py_base_getattro, _getattr -> py_getattro, __repr -> py_base_repr, py_delattro, py_getattro_self etc.
From here is possible to put all the parent classes methods into each python types dictionary to avoid nested lookups (api has 4 levels of lookups in some places), tested this but its not ready yet.
Simple tests for getting a method within a loop show this to be between 0.5 and 3.2x faster then using Py_FindMethod()
Diffstat (limited to 'source/gameengine/Expressions/PyObjectPlus.cpp')
-rw-r--r-- | source/gameengine/Expressions/PyObjectPlus.cpp | 54 |
1 files changed, 31 insertions, 23 deletions
diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/PyObjectPlus.cpp index 417388be464..ed6932b414a 100644 --- a/source/gameengine/Expressions/PyObjectPlus.cpp +++ b/source/gameengine/Expressions/PyObjectPlus.cpp @@ -55,19 +55,22 @@ ------------------------------*/ PyTypeObject PyObjectPlus::Type = { - PyObject_HEAD_INIT(&PyType_Type) + PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "PyObjectPlus", /*tp_name*/ sizeof(PyObjectPlus), /*tp_basicsize*/ 0, /*tp_itemsize*/ /* methods */ - PyDestructor, /*tp_dealloc*/ - 0, /*tp_print*/ - __getattr, /*tp_getattr*/ - __setattr, /*tp_setattr*/ - 0, /*tp_compare*/ - __repr, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + PyDestructor, + 0, + 0, + 0, + 0, + py_base_repr, + 0,0,0,0,0,0, + py_base_getattro, + py_base_setattro, + 0,0,0,0,0,0,0,0,0, Methods }; @@ -103,37 +106,41 @@ PyParentObject PyObjectPlus::Parents[] = {&PyObjectPlus::Type, NULL}; /*------------------------------ * PyObjectPlus attributes -- attributes ------------------------------*/ -PyObject *PyObjectPlus::_getattr(const char *attr) +PyObject *PyObjectPlus::py_getattro(PyObject* attr) { - if (!strcmp(attr, "__doc__") && GetType()->tp_doc) - return PyString_FromString(GetType()->tp_doc); - + PyObject *descr = PyDict_GetItem(Type.tp_dict, attr); \ + if (descr == NULL) { + PyErr_SetString(PyExc_AttributeError, "attribute not found"); + return NULL; + } else { + return PyCFunction_New(((PyMethodDescrObject *)descr)->d_method, (PyObject *)this); \ + } //if (streq(attr, "type")) // return Py_BuildValue("s", (*(GetParents()))->tp_name); - - return Py_FindMethod(Methods, this, attr); } -int PyObjectPlus::_delattr(const char *attr) +int PyObjectPlus::py_delattro(PyObject* attr) { PyErr_SetString(PyExc_AttributeError, "attribute cant be deleted"); return 1; } -int PyObjectPlus::_setattr(const char *attr, PyObject *value) +int PyObjectPlus::py_setattro(PyObject *attr, PyObject* value) { - //return PyObject::_setattr(attr,value); + //return PyObject::py_setattro(attr,value); //cerr << "Unknown attribute" << endl; PyErr_SetString(PyExc_AttributeError, "attribute cant be set"); return 1; } -PyObject *PyObjectPlus::_getattr_self(const PyAttributeDef attrlist[], void *self, const char *attr) +PyObject *PyObjectPlus::py_getattro_self(const PyAttributeDef attrlist[], void *self, PyObject *attr) { + char *attr_str= PyString_AsString(attr); + const PyAttributeDef *attrdef; for (attrdef=attrlist; attrdef->m_name != NULL; attrdef++) { - if (!strcmp(attr, attrdef->m_name)) + if (!strcmp(attr_str, attrdef->m_name)) { if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_DUMMY) { @@ -242,16 +249,17 @@ PyObject *PyObjectPlus::_getattr_self(const PyAttributeDef attrlist[], void *sel return NULL; } -int PyObjectPlus::_setattr_self(const PyAttributeDef attrlist[], void *self, const char *attr, PyObject *value) +int PyObjectPlus::py_setattro_self(const PyAttributeDef attrlist[], void *self, PyObject *attr, PyObject *value) { const PyAttributeDef *attrdef; void *undoBuffer = NULL; void *sourceBuffer = NULL; size_t bufferSize = 0; + char *attr_str= PyString_AsString(attr); for (attrdef=attrlist; attrdef->m_name != NULL; attrdef++) { - if (!strcmp(attr, attrdef->m_name)) + if (!strcmp(attr_str, attrdef->m_name)) { if (attrdef->m_access == KX_PYATTRIBUTE_RO || attrdef->m_type == KX_PYATTRIBUTE_TYPE_DUMMY) @@ -684,7 +692,7 @@ int PyObjectPlus::_setattr_self(const PyAttributeDef attrlist[], void *self, con /*------------------------------ * PyObjectPlus repr -- representations ------------------------------*/ -PyObject *PyObjectPlus::_repr(void) +PyObject *PyObjectPlus::py_repr(void) { PyErr_SetString(PyExc_SystemError, "Representation not overridden by object."); return NULL; @@ -726,7 +734,7 @@ PyObject *PyObjectPlus::Py_isA(PyObject *value) // Python wrapper for isA Py_RETURN_FALSE; } -/* Utility function called by the macro _getattr_up() +/* Utility function called by the macro py_getattro_up() * for getting ob.__dict__() values from our PyObject * this is used by python for doing dir() on an object, so its good * if we return a list of attributes and methods. |