00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "PreCompiled.h"
00025
00026 #ifndef _PreComp_
00027 # include <sstream>
00028 # include <stdlib.h>
00029 #endif
00030
00031 #include "PyObjectBase.h"
00032 #include "Console.h"
00033
00034 using namespace Base;
00035
00036
00037 PyObjectBase::PyObjectBase(void* p,PyTypeObject *T)
00038 : _pcTwinPointer(p), parent(0), attribute(0)
00039 {
00040 this->ob_type = T;
00041 _Py_NewReference(this);
00042 #ifdef FC_LOGPYOBJECTS
00043 Base::Console().Log("PyO+: %s (%p)\n",T->tp_name, this);
00044 #endif
00045 StatusBits.set(0);
00046 }
00047
00049 PyObjectBase::~PyObjectBase()
00050 {
00051 #ifdef FC_LOGPYOBJECTS
00052 Base::Console().Log("PyO-: %s (%p)\n",this->ob_type->tp_name, this);
00053 #endif
00054 if (this->parent)
00055 this->parent->DecRef();
00056 if (this->attribute)
00057 free(this->attribute);
00058 }
00059
00060
00061
00062
00063
00073 PyTypeObject PyObjectBase::Type = {
00074 PyObject_HEAD_INIT(&PyType_Type)
00075 0,
00076 "PyObjectBase",
00077 sizeof(PyObjectBase),
00078 0,
00079
00080 PyDestructor,
00081 0,
00082 __getattr,
00083 __setattr,
00084 0,
00085 __repr,
00086 0,
00087 0,
00088 0,
00089 0,
00090 0,
00091 0,
00092 0,
00093 0,
00094
00095 0,
00096
00097 Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_CLASS,
00098 "The most base class for Python binding",
00099 0,
00100 0,
00101 0,
00102 0,
00103 0,
00104 0,
00105 0,
00106 0,
00107 0,
00108 0,
00109 0,
00110 0,
00111 0,
00112 0,
00113 0,
00114 0,
00115 0,
00116 0,
00117 0,
00118 0,
00119 0,
00120 0,
00121 0,
00122 0,
00123 0
00124 };
00125
00126
00127
00128
00129 PyMethodDef PyObjectBase::Methods[] = {
00130 {NULL, NULL, 0, NULL}
00131 };
00132
00133
00134
00135
00136 PyParentObject PyObjectBase::Parents[] = {&PyObjectBase::Type, NULL};
00137
00138 PyObject* PyObjectBase::__getattr(PyObject * obj, char *attr)
00139 {
00140
00141 PyObjectBase* pyObj = static_cast<PyObjectBase*>(obj);
00142 if (!pyObj->isValid()){
00143 PyErr_Format(PyExc_ReferenceError, "Cannot access attribute '%s' of deleted object", attr);
00144 return NULL;
00145 }
00146
00147 PyObject* value = pyObj->_getattr(attr);
00148 #if 1
00149 if (value && PyObject_TypeCheck(value, &(PyObjectBase::Type))) {
00150 if (!static_cast<PyObjectBase*>(value)->isConst())
00151 static_cast<PyObjectBase*>(value)->setAttributeOf(attr, pyObj);
00152 }
00153 #endif
00154 return value;
00155 }
00156
00157 int PyObjectBase::__setattr(PyObject *obj, char *attr, PyObject *value)
00158 {
00159
00160
00161 if ( value==0 ) {
00162 PyErr_Format(PyExc_AttributeError, "Cannot delete attribute: '%s'", attr);
00163 return -1;
00164 }
00165 else if (!static_cast<PyObjectBase*>(obj)->isValid()){
00166 PyErr_Format(PyExc_ReferenceError, "Cannot access attribute '%s' of deleted object", attr);
00167 return -1;
00168 }
00169
00170 int ret = static_cast<PyObjectBase*>(obj)->_setattr(attr, value);
00171 #if 1
00172 if (ret == 0) {
00173 static_cast<PyObjectBase*>(obj)->startNotify();
00174 }
00175 #endif
00176 return ret;
00177 }
00178
00179
00180
00181
00182 PyObject *PyObjectBase::_getattr(char *attr)
00183 {
00184 if (streq(attr, "__class__")) {
00185
00186
00187 Py_INCREF(this->ob_type);
00188 return (PyObject *)(this->ob_type);
00189 }
00190 else if (streq(attr, "__members__")) {
00191
00192 return NULL;
00193 }
00194 else if (streq(attr,"__dict__")) {
00195
00196 PyTypeObject *tp = this->ob_type;
00197 Py_XINCREF(tp->tp_dict);
00198 return tp->tp_dict;
00199 }
00200 else if (streq(attr,"softspace")) {
00201
00202 return NULL;
00203 }
00204 else {
00205
00206 PyObject *w, *res;
00207 w = PyString_InternFromString(attr);
00208 if (w != NULL) {
00209 res = PyObject_GenericGetAttr(this, w);
00210 Py_XDECREF(w);
00211 return res;
00212 } else {
00213
00214 PyTypeObject *tp = this->ob_type;
00215 PyErr_Format(PyExc_AttributeError, "%.50s instance has no attribute '%.400s'", tp->tp_name, attr);
00216 return NULL;
00217 }
00218 }
00219 }
00220
00221 int PyObjectBase::_setattr(char *attr, PyObject *value)
00222 {
00223 if (streq(attr,"softspace"))
00224 return -1;
00225 PyObject *w;
00226
00227 w = PyString_InternFromString(attr);
00228 if (w != NULL) {
00229
00230 int res = PyObject_GenericSetAttr(this, w, value);
00231 Py_DECREF(w);
00232 return res;
00233 } else {
00234
00235 PyTypeObject *tp = this->ob_type;
00236 PyErr_Format(PyExc_AttributeError, "%.50s instance has no attribute '%.400s'", tp->tp_name, attr);
00237 return -1;
00238 }
00239 }
00240
00241
00242
00243
00244 PyObject *PyObjectBase::_repr(void)
00245 {
00246 std::stringstream a;
00247 a << "<base object at " << _pcTwinPointer << ">";
00248 # ifdef FCDebug
00249 Console().Log("PyObjectBase::_repr() not overwritten representation!");
00250 # endif
00251 return Py_BuildValue("s", a.str().c_str());
00252 }
00253
00254 void PyObjectBase::setAttributeOf(const char* attr, const PyObjectBase* par)
00255 {
00256 if (this->parent != par) {
00257 Py_XDECREF(this->parent);
00258 this->parent = const_cast<PyObjectBase*>(par);
00259 Py_XINCREF(this->parent);
00260 }
00261
00262 if (this->attribute) {
00263 if (strcmp(this->attribute, attr) != 0) {
00264 free(this->attribute);
00265 #if defined (__GNUC__)
00266 this->attribute = strdup(attr);
00267 #else
00268 this->attribute = _strdup(attr);
00269 #endif
00270 }
00271 }
00272 else {
00273 #if defined (__GNUC__)
00274 this->attribute = strdup(attr);
00275 #else
00276 this->attribute = _strdup(attr);
00277 #endif
00278 }
00279 }
00280
00281 void PyObjectBase::startNotify()
00282 {
00283 if (this->attribute && this->parent) {
00284 __setattr(this->parent, this->attribute, this);
00285 if (PyErr_Occurred())
00286 PyErr_Clear();
00287 }
00288 }