Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2009-04-03 18:51:06 +0400
committerCampbell Barton <ideasman42@gmail.com>2009-04-03 18:51:06 +0400
commitfd2b1156783d52dbb7c93c53fe008d9e14cbffdd (patch)
tree3578443cee384e883450b35480244a0c46aaf34b /source/gameengine/Expressions
parente30cb79aaa8d9a25b66c57aa08fb79bf591b6be4 (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')
-rw-r--r--source/gameengine/Expressions/ListValue.cpp17
-rw-r--r--source/gameengine/Expressions/ListValue.h2
-rw-r--r--source/gameengine/Expressions/PyObjectPlus.cpp54
-rw-r--r--source/gameengine/Expressions/PyObjectPlus.h50
-rw-r--r--source/gameengine/Expressions/Value.cpp36
-rw-r--r--source/gameengine/Expressions/Value.h8
6 files changed, 96 insertions, 71 deletions
diff --git a/source/gameengine/Expressions/ListValue.cpp b/source/gameengine/Expressions/ListValue.cpp
index aa84cab0266..15eb8835b79 100644
--- a/source/gameengine/Expressions/ListValue.cpp
+++ b/source/gameengine/Expressions/ListValue.cpp
@@ -193,7 +193,7 @@ static PyMappingMethods instance_as_mapping = {
PyTypeObject CListValue::Type = {
- PyObject_HEAD_INIT(&PyType_Type)
+ PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"CListValue", /*tp_name*/
sizeof(CListValue), /*tp_basicsize*/
@@ -201,16 +201,19 @@ PyTypeObject CListValue::Type = {
/* methods */
PyDestructor, /*tp_dealloc*/
0, /*tp_print*/
- __getattr, /*tp_getattr*/
- __setattr, /*tp_setattr*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
0, /*tp_compare*/
- __repr, /*tp_repr*/
+ py_base_repr, /*tp_repr*/
0, /*tp_as_number*/
&listvalue_as_sequence, /*tp_as_sequence*/
&instance_as_mapping, /*tp_as_mapping*/
0, /*tp_hash*/
0, /*tp_call */
- 0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,
+ py_base_getattro,
+ py_base_setattro,
+ 0,0,0,0,0,0,0,0,0,
Methods
};
@@ -238,8 +241,8 @@ PyAttributeDef CListValue::Attributes[] = {
{ NULL } //Sentinel
};
-PyObject* CListValue::_getattr(const char *attr) {
- _getattr_up(CValue);
+PyObject* CListValue::py_getattro(PyObject* attr) {
+ py_getattro_up(CValue);
}
diff --git a/source/gameengine/Expressions/ListValue.h b/source/gameengine/Expressions/ListValue.h
index 104e3e63283..f936298a8c4 100644
--- a/source/gameengine/Expressions/ListValue.h
+++ b/source/gameengine/Expressions/ListValue.h
@@ -59,7 +59,7 @@ public:
bool CheckEqual(CValue* first,CValue* second);
- virtual PyObject* _getattr(const char *attr);
+ virtual PyObject* py_getattro(PyObject* attr);
KX_PYMETHOD_O(CListValue,append);
KX_PYMETHOD_NOARGS(CListValue,reverse);
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.
diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h
index 345eb8c9c3f..77963c092eb 100644
--- a/source/gameengine/Expressions/PyObjectPlus.h
+++ b/source/gameengine/Expressions/PyObjectPlus.h
@@ -72,6 +72,8 @@ typedef int Py_ssize_t;
#define PY_METHODCHAR const char *
#endif
+#include "descrobject.h"
+
static inline void Py_Fatal(const char *M) {
fprintf(stderr, "%s\n", M);
exit(-1);
@@ -90,21 +92,27 @@ static inline void Py_Fatal(const char *M) {
- // This defines the _getattr_up macro
+ // This defines the py_getattro_up macro
// which allows attribute and method calls
// to be properly passed up the hierarchy.
-#define _getattr_up(Parent) \
- PyObject *rvalue = Py_FindMethod(Methods, this, attr); \
+
+#define py_getattro_up(Parent) \
+ PyObject *rvalue; \
+ PyObject *descr = PyDict_GetItem(Type.tp_dict, attr); \
\
- if (rvalue == NULL) { \
+ if (descr == NULL) { \
PyErr_Clear(); \
- rvalue = Parent::_getattr(attr); \
+ rvalue = Parent::py_getattro(attr); \
+ } else { \
+ rvalue= PyCFunction_New(((PyMethodDescrObject *)descr)->d_method, (PyObject *)this); \
} \
- if (strcmp(attr, "__dict__")==0) {\
+ \
+ if (strcmp(PyString_AsString(attr), "__dict__")==0) {\
rvalue = _getattr_dict(rvalue, Methods, Attributes); \
} \
return rvalue; \
+
/**
* These macros are helpfull when embedding Python routines. The second
* macro is one that also requires a documentation string
@@ -361,29 +369,29 @@ public:
// Py_DECREF(this);
// }; // decref method
- virtual PyObject *_getattr(const char *attr); // _getattr method
- static PyObject *__getattr(PyObject * PyObj, char *attr) // This should be the entry in Type.
+ virtual PyObject *py_getattro(PyObject *attr); // py_getattro method
+ static PyObject *py_base_getattro(PyObject * PyObj, PyObject *attr) // This should be the entry in Type.
{
- return ((PyObjectPlus*) PyObj)->_getattr(attr);
+ return ((PyObjectPlus*) PyObj)->py_getattro(attr);
}
- static PyObject *_getattr_self(const PyAttributeDef attrlist[], void *self, const char *attr);
- static int _setattr_self(const PyAttributeDef attrlist[], void *self, const char *attr, PyObject *value);
+ static PyObject *py_getattro_self(const PyAttributeDef attrlist[], void *self, PyObject *attr);
+ static int py_setattro_self(const PyAttributeDef attrlist[], void *self, PyObject *attr, PyObject *value);
- virtual int _delattr(const char *attr);
- virtual int _setattr(const char *attr, PyObject *value); // _setattr method
- static int __setattr(PyObject *PyObj, // This should be the entry in Type.
- char *attr,
+ virtual int py_delattro(PyObject *attr);
+ virtual int py_setattro(PyObject *attr, PyObject *value); // py_setattro method
+ static int py_base_setattro(PyObject *PyObj, // This should be the entry in Type.
+ PyObject *attr,
PyObject *value)
{
- if (!value)
- return ((PyObjectPlus*) PyObj)->_delattr(attr);
- return ((PyObjectPlus*) PyObj)->_setattr(attr, value);
+ if (value==NULL)
+ return ((PyObjectPlus*) PyObj)->py_delattro(attr);
+ return ((PyObjectPlus*) PyObj)->py_setattro(attr, value);
}
- virtual PyObject *_repr(void); // _repr method
- static PyObject *__repr(PyObject *PyObj) // This should be the entry in Type.
+ virtual PyObject *py_repr(void); // py_repr method
+ static PyObject *py_base_repr(PyObject *PyObj) // This should be the entry in Type.
{
- return ((PyObjectPlus*) PyObj)->_repr();
+ return ((PyObjectPlus*) PyObj)->py_repr();
}
// isA methods
diff --git a/source/gameengine/Expressions/Value.cpp b/source/gameengine/Expressions/Value.cpp
index 36509763454..8b910b9038b 100644
--- a/source/gameengine/Expressions/Value.cpp
+++ b/source/gameengine/Expressions/Value.cpp
@@ -139,19 +139,22 @@ static PyNumberMethods cvalue_as_number = {
PyTypeObject CValue::Type = {
- PyObject_HEAD_INIT(&PyType_Type)
+ PyObject_HEAD_INIT(NULL)
0,
"CValue",
sizeof(CValue),
0,
PyDestructor,
0,
- __getattr,
- __setattr,
+ 0,
+ 0,
&MyPyCompare,
- __repr,
+ py_base_repr,
&cvalue_as_number,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
+ 0,0,0,0,0,0,0,0,0,
Methods
};
@@ -695,9 +698,10 @@ PyAttributeDef CValue::Attributes[] = {
};
-PyObject* CValue::_getattr(const char *attr)
+PyObject* CValue::py_getattro(PyObject *attr)
{
- CValue* resultattr = GetProperty(attr);
+ char *attr_str= PyString_AsString(attr);
+ CValue* resultattr = GetProperty(attr_str);
if (resultattr)
{
PyObject* pyconvert = resultattr->ConvertValueToPython();
@@ -707,7 +711,7 @@ PyObject* CValue::_getattr(const char *attr)
else
return resultattr; // also check if it's already in pythoninterpreter!
}
- _getattr_up(PyObjectPlus);
+ py_getattro_up(PyObjectPlus);
}
CValue* CValue::ConvertPythonToValue(PyObject* pyobj)
@@ -769,26 +773,28 @@ CValue* CValue::ConvertPythonToValue(PyObject* pyobj)
}
-int CValue::_delattr(const char *attr)
+int CValue::py_delattro(PyObject *attr)
{
- if (RemoveProperty(STR_String(attr)))
+ char *attr_str= PyString_AsString(attr);
+ if (RemoveProperty(STR_String(attr_str)))
return 0;
- PyErr_Format(PyExc_AttributeError, "attribute \"%s\" dosnt exist", attr);
+ PyErr_Format(PyExc_AttributeError, "attribute \"%s\" dosnt exist", attr_str);
return 1;
}
-int CValue::_setattr(const char *attr, PyObject* pyobj)
+int CValue::py_setattro(PyObject *attr, PyObject* pyobj)
{
CValue* vallie = ConvertPythonToValue(pyobj);
if (vallie)
{
- CValue* oldprop = GetProperty(attr);
+ char *attr_str= PyString_AsString(attr);
+ CValue* oldprop = GetProperty(attr_str);
if (oldprop)
oldprop->SetValue(vallie);
else
- SetProperty(attr, vallie);
+ SetProperty(attr_str, vallie);
vallie->Release();
} else
@@ -796,7 +802,7 @@ int CValue::_setattr(const char *attr, PyObject* pyobj)
return 1; /* ConvertPythonToValue sets the error message */
}
- //PyObjectPlus::_setattr(attr,value);
+ //PyObjectPlus::py_setattro(attr,value);
return 0;
};
diff --git a/source/gameengine/Expressions/Value.h b/source/gameengine/Expressions/Value.h
index 4678ab1f0c2..7a2816a9778 100644
--- a/source/gameengine/Expressions/Value.h
+++ b/source/gameengine/Expressions/Value.h
@@ -217,14 +217,14 @@ public:
CValue(PyTypeObject *T = &Type);
//static PyObject* PyMake(PyObject*,PyObject*);
- virtual PyObject *_repr(void)
+ virtual PyObject *py_repr(void)
{
return Py_BuildValue("s",(const char*)GetText());
}
- virtual PyObject* _getattr(const char *attr);
+ virtual PyObject* py_getattro(PyObject *attr);
void SpecialRelease()
{
@@ -251,8 +251,8 @@ public:
virtual CValue* ConvertPythonToValue(PyObject* pyobj);
- virtual int _delattr(const char *attr);
- virtual int _setattr(const char *attr, PyObject* value);
+ virtual int py_delattro(PyObject *attr);
+ virtual int py_setattro(PyObject *attr, PyObject* value);
virtual PyObject* ConvertKeysToPython( void );