diff options
Diffstat (limited to 'source/gameengine/Expressions')
-rw-r--r-- | source/gameengine/Expressions/Expression.cpp | 4 | ||||
-rw-r--r-- | source/gameengine/Expressions/InputParser.cpp | 5 | ||||
-rw-r--r-- | source/gameengine/Expressions/ListValue.cpp | 13 | ||||
-rw-r--r-- | source/gameengine/Expressions/Makefile | 1 | ||||
-rw-r--r-- | source/gameengine/Expressions/PyObjectPlus.cpp | 16 | ||||
-rw-r--r-- | source/gameengine/Expressions/PyObjectPlus.h | 128 | ||||
-rw-r--r-- | source/gameengine/Expressions/Value.cpp | 183 | ||||
-rw-r--r-- | source/gameengine/Expressions/Value.h | 5 |
8 files changed, 264 insertions, 91 deletions
diff --git a/source/gameengine/Expressions/Expression.cpp b/source/gameengine/Expressions/Expression.cpp index 5c5e1abea34..f16f572c322 100644 --- a/source/gameengine/Expressions/Expression.cpp +++ b/source/gameengine/Expressions/Expression.cpp @@ -22,7 +22,9 @@ ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// - +#ifdef _DEBUG +//int gRefCountExpr; +#endif CExpression::CExpression()// : m_cached_calculate(NULL) { m_refcount = 1; diff --git a/source/gameengine/Expressions/InputParser.cpp b/source/gameengine/Expressions/InputParser.cpp index 24033dd21a2..32a9de32e21 100644 --- a/source/gameengine/Expressions/InputParser.cpp +++ b/source/gameengine/Expressions/InputParser.cpp @@ -631,7 +631,8 @@ void CParser::SetContext(CValue* context) PyObject* CParserPyMake(PyObject* ignored,PyObject* args) { char* txt; - Py_Try(PyArg_ParseTuple(args,"s",&txt)); + if (!PyArg_ParseTuple(args,"s",&txt)) + return NULL; CParser parser; CExpression* expr = parser.ProcessText(txt); CValue* val = expr->Calculate(); @@ -641,7 +642,7 @@ PyObject* CParserPyMake(PyObject* ignored,PyObject* args) static PyMethodDef CParserMethods[] = { - { "calc", CParserPyMake , Py_NEWARGS}, + { "calc", CParserPyMake , METH_VARARGS}, { NULL,NULL} // Sentinel }; diff --git a/source/gameengine/Expressions/ListValue.cpp b/source/gameengine/Expressions/ListValue.cpp index bbf58a8a06e..9ffdbb1223c 100644 --- a/source/gameengine/Expressions/ListValue.cpp +++ b/source/gameengine/Expressions/ListValue.cpp @@ -43,7 +43,7 @@ PyObject* listvalue_buffer_item(PyObject* list,Py_ssize_t index) return ((CListValue*) list)->GetValue(index)->AddRef(); } - Py_Error(PyExc_IndexError, "Python ListIndex out of range"); + PyErr_SetString(PyExc_IndexError, "Python ListIndex out of range"); return NULL; } @@ -130,9 +130,10 @@ listvalue_buffer_concat(PyObject * self, PyObject * other) } } - if (error) - Py_Error(PyExc_SystemError, "Python Error: couldn't add one or more items to a list"); - + if (error) { + PyErr_SetString(PyExc_SystemError, "Python Error: couldn't add one or more items to a list"); + return NULL; + } } else { @@ -155,8 +156,8 @@ listvalue_buffer_concat(PyObject * self, PyObject * other) listval->Add(objval); } else { - Py_Error(PyExc_SystemError, "Python Error: couldn't add item to a list"); - // bad luck + PyErr_SetString(PyExc_SystemError, "Python Error: couldn't add item to a list"); + return NULL; } } } diff --git a/source/gameengine/Expressions/Makefile b/source/gameengine/Expressions/Makefile index e9c02eedcf2..6736149bbcd 100644 --- a/source/gameengine/Expressions/Makefile +++ b/source/gameengine/Expressions/Makefile @@ -36,6 +36,7 @@ include nan_compile.mk CCFLAGS += $(LEVEL_1_CPP_WARNINGS) CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) +CPPFLAGS += -I../../blender/makesdna CPPFLAGS += -I$(NAN_STRING)/include CPPFLAGS += -I$(NAN_MOTO)/include diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/PyObjectPlus.cpp index aabcd6cb71d..1eca527151a 100644 --- a/source/gameengine/Expressions/PyObjectPlus.cpp +++ b/source/gameengine/Expressions/PyObjectPlus.cpp @@ -94,7 +94,7 @@ PyObjectPlus::PyObjectPlus(PyTypeObject *T) // constructor * PyObjectPlus Methods -- Every class, even the abstract one should have a Methods ------------------------------*/ PyMethodDef PyObjectPlus::Methods[] = { - {"isA", (PyCFunction) sPy_isA, Py_NEWARGS}, + {"isA", (PyCFunction) sPy_isA, METH_VARARGS}, {NULL, NULL} /* Sentinel */ }; @@ -119,6 +119,7 @@ PyObject *PyObjectPlus::_getattr(const STR_String& attr) int PyObjectPlus::_delattr(const STR_String& attr) { + PyErr_SetString(PyExc_AttributeError, "attribute cant be deleted"); return 1; } @@ -126,7 +127,8 @@ int PyObjectPlus::_setattr(const STR_String& attr, PyObject *value) { //return PyObject::_setattr(attr,value); //cerr << "Unknown attribute" << endl; - return 1; + PyErr_SetString(PyExc_AttributeError, "attribute cant be set"); + return 1; } /*------------------------------ @@ -134,7 +136,8 @@ int PyObjectPlus::_setattr(const STR_String& attr, PyObject *value) ------------------------------*/ PyObject *PyObjectPlus::_repr(void) { - Py_Error(PyExc_SystemError, "Representation not overridden by object."); + PyErr_SetString(PyExc_SystemError, "Representation not overridden by object."); + return NULL; } /*------------------------------ @@ -164,11 +167,12 @@ bool PyObjectPlus::isA(const char *mytypename) // check typename of each parent PyObject *PyObjectPlus::Py_isA(PyObject *args) // Python wrapper for isA { char *mytypename; - Py_Try(PyArg_ParseTuple(args, "s", &mytypename)); + if (!PyArg_ParseTuple(args, "s", &mytypename)) + return NULL; if(isA(mytypename)) - {Py_INCREF(Py_True); return Py_True;} + Py_RETURN_TRUE; else - {Py_INCREF(Py_False); return Py_False;}; + Py_RETURN_FALSE; } #endif //NO_EXP_PYTHON_EMBEDDING diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h index de89ed9b5c8..3a054454a0b 100644 --- a/source/gameengine/Expressions/PyObjectPlus.h +++ b/source/gameengine/Expressions/PyObjectPlus.h @@ -43,25 +43,39 @@ * Python defines ------------------------------*/ +/* + Py_RETURN_NONE + Python 2.4 macro. + defined here until we switch to 2.4 + also in api2_2x/gen_utils.h +*/ +#ifndef Py_RETURN_NONE +#define Py_RETURN_NONE return Py_BuildValue("O", Py_None) +#endif +#ifndef Py_RETURN_FALSE +#define Py_RETURN_FALSE return PyBool_FromLong(0) +#endif +#ifndef Py_RETURN_TRUE +#define Py_RETURN_TRUE return PyBool_FromLong(1) +#endif + +/* for pre Py 2.5 */ +#if PY_VERSION_HEX < 0x02050000 +typedef int Py_ssize_t; +#define PY_SSIZE_T_MAX INT_MAX +#define PY_SSIZE_T_MIN INT_MIN +#define PY_METHODCHAR char * +#else +/* Py 2.5 and later */ +#define intargfunc ssizeargfunc +#define intintargfunc ssizessizeargfunc +#define PY_METHODCHAR const char * +#endif + // some basic python macros -#define Py_NEWARGS 1 #define Py_Return { Py_INCREF(Py_None); return Py_None;} -static inline PyObject* Py_Success(bool truth) -{ - if (truth) - { - Py_INCREF(Py_True); - return Py_True; - } - Py_INCREF(Py_False); - return Py_False; -} - -#define Py_Error(E, M) {PyErr_SetString(E, M); return NULL;} -#define Py_Try(F) {if (!(F)) return NULL;} -#define Py_Assert(A,E,M) {if (!(A)) {PyErr_SetString(E, M); return NULL;}} -static inline void Py_Fatal(char *M) { +static inline void Py_Fatal(const char *M) { //cout << M << endl; exit(-1); }; @@ -76,18 +90,36 @@ static inline void Py_Fatal(char *M) { virtual PyTypeObject *GetType(void) {return &Type;}; \ virtual PyParentObject *GetParents(void) {return Parents;} + // This defines the _getattr_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, const_cast<char*>(attr.ReadPtr())); \ - if (rvalue == NULL) \ - { \ + PyObject *rvalue = NULL; \ + if (attr=="__methods__") { \ + PyObject *_attr_string = NULL; \ + PyMethodDef *meth = Methods; \ + rvalue = Parent::_getattr(attr); \ + if (rvalue==NULL) { \ + PyErr_Clear(); \ + rvalue = PyList_New(0); \ + } \ + if (meth) { \ + for (; meth->ml_name != NULL; meth++) { \ + _attr_string = PyString_FromString(meth->ml_name); \ + PyList_Append(rvalue, _attr_string); \ + Py_DECREF(_attr_string); \ + } \ + } \ + } else { \ + rvalue = Py_FindMethod(Methods, this, const_cast<char*>(attr.ReadPtr())); \ + if (rvalue == NULL) { \ PyErr_Clear(); \ - return Parent::_getattr(attr); \ + rvalue = Parent::_getattr(attr); \ } \ - else \ - return rvalue + } \ + return rvalue; \ + /** * These macros are helpfull when embedding Python routines. The second @@ -99,27 +131,73 @@ static inline void Py_Fatal(char *M) { return ((class_name*) self)->Py##method_name(self, args, kwds); \ }; \ +#define KX_PYMETHOD_VARARGS(class_name, method_name) \ + PyObject* Py##method_name(PyObject* self, PyObject* args); \ + static PyObject* sPy##method_name( PyObject* self, PyObject* args) { \ + return ((class_name*) self)->Py##method_name(self, args); \ + }; \ + +#define KX_PYMETHOD_NOARGS(class_name, method_name) \ + PyObject* Py##method_name(PyObject* self); \ + static PyObject* sPy##method_name( PyObject* self) { \ + return ((class_name*) self)->Py##method_name(self); \ + }; \ + +#define KX_PYMETHOD_O(class_name, method_name) \ + PyObject* Py##method_name(PyObject* self, PyObject* value); \ + static PyObject* sPy##method_name( PyObject* self, PyObject* value) { \ + return ((class_name*) self)->Py##method_name(self, value); \ + }; \ + #define KX_PYMETHOD_DOC(class_name, method_name) \ PyObject* Py##method_name(PyObject* self, PyObject* args, PyObject* kwds); \ static PyObject* sPy##method_name( PyObject* self, PyObject* args, PyObject* kwds) { \ return ((class_name*) self)->Py##method_name(self, args, kwds); \ }; \ - static char method_name##_doc[]; \ + static const char method_name##_doc[]; \ + +#define KX_PYMETHOD_DOC_VARARGS(class_name, method_name) \ + PyObject* Py##method_name(PyObject* self, PyObject* args); \ + static PyObject* sPy##method_name( PyObject* self, PyObject* args) { \ + return ((class_name*) self)->Py##method_name(self, args); \ + }; \ + static const char method_name##_doc[]; \ + +#define KX_PYMETHOD_DOC_O(class_name, method_name) \ + PyObject* Py##method_name(PyObject* self, PyObject* value); \ + static PyObject* sPy##method_name( PyObject* self, PyObject* value) { \ + return ((class_name*) self)->Py##method_name(self, value); \ + }; \ + static const char method_name##_doc[]; \ + +#define KX_PYMETHOD_DOC_NOARGS(class_name, method_name) \ + PyObject* Py##method_name(PyObject* self); \ + static PyObject* sPy##method_name( PyObject* self) { \ + return ((class_name*) self)->Py##method_name(self); \ + }; \ + static const char method_name##_doc[]; \ + /* The line above should remain empty */ /** * Method table macro (with doc) */ #define KX_PYMETHODTABLE(class_name, method_name) \ - {#method_name , (PyCFunction) class_name::sPy##method_name, METH_VARARGS, class_name::method_name##_doc} + {#method_name , (PyCFunction) class_name::sPy##method_name, METH_VARARGS, (PY_METHODCHAR)class_name::method_name##_doc} + +#define KX_PYMETHODTABLE_NOARG(class_name, method_name) \ + {#method_name , (PyCFunction) class_name::sPy##method_name, METH_NOARGS, (PY_METHODCHAR)class_name::method_name##_doc} /** * Function implementation macro */ #define KX_PYMETHODDEF_DOC(class_name, method_name, doc_string) \ -char class_name::method_name##_doc[] = doc_string; \ +const char class_name::method_name##_doc[] = doc_string; \ PyObject* class_name::Py##method_name(PyObject*, PyObject* args, PyObject*) +#define KX_PYMETHODDEF_DOC_NOARG(class_name, method_name, doc_string) \ +const char class_name::method_name##_doc[] = doc_string; \ +PyObject* class_name::Py##method_name(PyObject*) /*------------------------------ * PyObjectPlus diff --git a/source/gameengine/Expressions/Value.cpp b/source/gameengine/Expressions/Value.cpp index 48898dfc1f5..7296dfbec10 100644 --- a/source/gameengine/Expressions/Value.cpp +++ b/source/gameengine/Expressions/Value.cpp @@ -158,18 +158,38 @@ PyParentObject CValue::Parents[] = { }; PyMethodDef CValue::Methods[] = { -// { "printHello", (PyCFunction) CValue::sPyPrintHello, Py_NEWARGS}, - { "getName", (PyCFunction) CValue::sPyGetName, Py_NEWARGS}, +// { "printHello", (PyCFunction) CValue::sPyPrintHello, METH_VARARGS}, + { "getName", (PyCFunction) CValue::sPyGetName, METH_NOARGS}, {NULL,NULL} //Sentinel }; -PyObject* CValue::PyGetName(PyObject* self,PyObject* args,PyObject* kwds) +PyObject* CValue::PyGetName(PyObject* self) { - PyObject* pyname = PyString_FromString(this->GetName()); - return pyname; + return PyString_FromString(this->GetName()); } +/*#define CVALUE_DEBUG*/ +#ifdef CVALUE_DEBUG +int gRefCount; +struct SmartCValueRef +{ + CValue *m_ref; + int m_count; + SmartCValueRef(CValue *ref) + { + m_ref = ref; + m_count = gRefCount++; + } +}; + +#include <vector> +std::vector<SmartCValueRef> gRefList; +#endif + +#ifdef _DEBUG +//int gRefCountValue; +#endif CValue::CValue(PyTypeObject *T) : PyObjectPlus(T), @@ -186,6 +206,12 @@ effect: constucts a CValue */ { //debug(gRefCountValue++) // debugging +#ifdef _DEBUG + //gRefCountValue++; +#ifdef CVALUE_DEBUG + gRefList.push_back(SmartCValueRef(this)); +#endif +#endif } @@ -199,6 +225,18 @@ effect: deletes the object ClearProperties(); assertd (m_refcount==0); +#ifdef CVALUE_DEBUG + std::vector<SmartCValueRef>::iterator it; + for (it=gRefList.begin(); it!=gRefList.end(); it++) + { + if (it->m_ref == this) + { + *it = gRefList.back(); + gRefList.pop_back(); + break; + } + } +#endif } @@ -293,7 +331,7 @@ void CValue::SetProperty(const STR_String & name,CValue* ioProperty) } // Add property at end of array - (*m_pNamedPropertyArray)[name] = ioProperty;//->Add(ioProperty); + (*m_pNamedPropertyArray)[name] = ioProperty->AddRef();//->Add(ioProperty); } @@ -353,17 +391,40 @@ float CValue::GetPropertyNumber(const STR_String& inName,float defnumber) bool CValue::RemoveProperty(const STR_String & inName) { // Check if there are properties at all which can be removed - if (m_pNamedPropertyArray == NULL) - return false; - - // Scan all properties, as soon as we find one with <inName> -> Remove it -// CValue* val = (*m_pNamedPropertyArray)[inName]; - if (m_pNamedPropertyArray->erase(inName)) return true; + if (m_pNamedPropertyArray) { + CValue* val = GetProperty(inName); + if (NULL != val) + { + val->Release(); + m_pNamedPropertyArray->erase(inName); + return true; + } + } + char err[128]; + if (m_pNamedPropertyArray) + sprintf(err, "attribute \"%s\" dosnt exist", inName.ReadPtr()); + else + sprintf(err, "attribute \"%s\" dosnt exist (no property array)", inName.ReadPtr()); + + PyErr_SetString(PyExc_AttributeError, err); return false; } - +// +// Get Property Names +// +vector<STR_String> CValue::GetPropertyNames() +{ + vector<STR_String> result; + if(!m_pNamedPropertyArray) return result; + for ( std::map<STR_String,CValue*>::iterator it = m_pNamedPropertyArray->begin(); + !(it == m_pNamedPropertyArray->end());it++) + { + result.push_back((*it).first); + } + return result; +} // // Clear all properties @@ -379,7 +440,7 @@ void CValue::ClearProperties() !(it == m_pNamedPropertyArray->end());it++) { CValue* tmpval = (*it).second; - STR_String name = (*it).first; + //STR_String name = (*it).first; tmpval->Release(); } @@ -469,19 +530,15 @@ void CValue::CloneProperties(CValue *replica) for ( std::map<STR_String,CValue*>::iterator it = m_pNamedPropertyArray->begin(); !(it == m_pNamedPropertyArray->end());it++) { - - replica->SetProperty((*it).first,(*it).second->GetReplica()); + CValue *val = (*it).second->GetReplica(); + replica->SetProperty((*it).first,val); + val->Release(); } } } - - - - - double* CValue::GetVector3(bool bGetTransformedVec) { assertd(false); // don;t get vector from me @@ -489,10 +546,6 @@ double* CValue::GetVector3(bool bGetTransformedVec) } - - - - /*--------------------------------------------------------------------------------------------------------------------- Reference Counting ---------------------------------------------------------------------------------------------------------------------*/ @@ -504,6 +557,9 @@ CValue *CValue::AddRef() // Increase global reference count, used to see at the end of the program // if all CValue-derived classes have been dereferenced to 0 //debug(gRefCountValue++); +#ifdef _DEBUG + //gRefCountValue++; +#endif m_refcount++; return this; } @@ -518,7 +574,9 @@ int CValue::Release() // Decrease global reference count, used to see at the end of the program // if all CValue-derived classes have been dereferenced to 0 //debug(gRefCountValue--); - +#ifdef _DEBUG + //gRefCountValue--; +#endif // Decrease local reference count, if it reaches 0 the object should be freed if (--m_refcount > 0) { @@ -546,6 +604,9 @@ void CValue::DisableRefCount() m_refcount--; //debug(gRefCountValue--); +#ifdef _DEBUG + //gRefCountValue--; +#endif m_ValFlags.RefCountDisabled=true; } @@ -590,11 +651,14 @@ CValue* CValue::FindIdentifier(const STR_String& identifiername) } else { result = GetProperty(identifiername); + if (result) + return result->AddRef(); + } + if (!result) + { + // warning here !!! + result = new CErrorValue(identifiername+" not found"); } - if (result) - return result->AddRef(); - // warning here !!! - result = new CErrorValue(identifiername+" not found"); return result; } @@ -604,7 +668,7 @@ CValue* CValue::FindIdentifier(const STR_String& identifiername) static PyMethodDef CValueMethods[] = { - //{ "new", CValue::PyMake , Py_NEWARGS}, + //{ "new", CValue::PyMake , METH_VARARGS}, { NULL,NULL} // Sentinel }; @@ -642,9 +706,7 @@ CValue* CValue::ConvertPythonToValue(PyObject* pyobj) CValue* vallie = NULL; - PyTypeObject* type = pyobj->ob_type; - - if (type == &PyList_Type) + if (PyList_Check(pyobj)) { CListValue* listval = new CListValue(); bool error = false; @@ -674,26 +736,25 @@ CValue* CValue::ConvertPythonToValue(PyObject* pyobj) } } else - if (type == &PyFloat_Type) + if (PyFloat_Check(pyobj)) { - float fl; - PyArg_Parse(pyobj,"f",&fl); - vallie = new CFloatValue(fl); + vallie = new CFloatValue( (float)PyFloat_AsDouble(pyobj) ); } else - if (type==&PyInt_Type) + if (PyInt_Check(pyobj)) { - int innie; - PyArg_Parse(pyobj,"i",&innie); - vallie = new CIntValue(innie); + vallie = new CIntValue( (int)PyInt_AS_LONG(pyobj) ); } else - - if (type==&PyString_Type) + if (PyString_Check(pyobj)) { vallie = new CStringValue(PyString_AsString(pyobj),""); } else - if (type==&CValue::Type || type==&CListValue::Type) + if (pyobj->ob_type==&CValue::Type || pyobj->ob_type==&CListValue::Type) { vallie = ((CValue*) pyobj)->AddRef(); + } else + { + /* return an error value from the caller */ + PyErr_SetString(PyExc_TypeError, "This python value could not be assigned to a game engine property"); } return vallie; @@ -701,7 +762,8 @@ CValue* CValue::ConvertPythonToValue(PyObject* pyobj) int CValue::_delattr(const STR_String& attr) { - RemoveProperty(attr); + if (!RemoveProperty(attr)) /* sets error */ + return 1; return 0; } @@ -717,21 +779,42 @@ int CValue::_setattr(const STR_String& attr,PyObject* pyobj) oldprop->SetValue(vallie); } else { - SetProperty(attr,vallie->AddRef()); + SetProperty(attr,vallie); } vallie->Release(); + } else + { + return 1; /* ConvertPythonToValue sets the error message */ } //PyObjectPlus::_setattr(attr,value); return 0; }; + +PyObject* CValue::ConvertKeysToPython( void ) +{ + PyObject *pylist = PyList_New( 0 ); + PyObject *pystr; + + if (m_pNamedPropertyArray) + { + for ( std::map<STR_String,CValue*>::iterator it = m_pNamedPropertyArray->begin(); + !(it == m_pNamedPropertyArray->end());it++) + { + pystr = PyString_FromString( (*it).first ); + PyList_Append(pylist, pystr); + Py_DECREF( pystr ); + } + } + return pylist; +} + /* PyObject* CValue::PyMake(PyObject* ignored,PyObject* args) { - //Py_Try(PyArg_ParseTuple(args,"s",&name)); - Py_INCREF(Py_None); - return Py_None;//new CValue(); + //if (!PyArg_ParseTuple(args,"s",&name)) return NULL; + Py_RETURN_NONE;//new CValue(); } */ diff --git a/source/gameengine/Expressions/Value.h b/source/gameengine/Expressions/Value.h index ccb9c34749d..74fcdae5756 100644 --- a/source/gameengine/Expressions/Value.h +++ b/source/gameengine/Expressions/Value.h @@ -253,7 +253,9 @@ public: virtual int _delattr(const STR_String& attr); virtual int _setattr(const STR_String& attr,PyObject* value); - KX_PYMETHOD(CValue,GetName); + virtual PyObject* ConvertKeysToPython( void ); + + KX_PYMETHOD_NOARGS(CValue,GetName); #else CValue(); @@ -284,6 +286,7 @@ public: STR_String GetPropertyText(const STR_String & inName,const STR_String& deftext=""); // Get text description of property with name <inName>, returns an empty string if there is no property named <inName> float GetPropertyNumber(const STR_String& inName,float defnumber); virtual bool RemoveProperty(const STR_String & inName); // Remove the property named <inName>, returns true if the property was succesfully removed, false if property was not found or could not be removed + virtual vector<STR_String> GetPropertyNames(); virtual void ClearProperties(); // Clear all properties virtual void SetPropertiesModified(bool inModified); // Set all properties' modified flag to <inModified> |