PageRenderTime 30ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 1ms

/PyVariable.cpp

https://github.com/bengioe/PyVariable
C++ | 459 lines | 361 code | 61 blank | 37 comment | 55 complexity | 3a979cd58746bc72d1c6a6c36d260950 MD5 | raw file
  1. #include "PyVariable.h"
  2. #include "PyException.h"
  3. PyObject* _pyvar_call_void_pv(PyObject* func,PyObject* args,PyObject* kw){
  4. PyCFunction meth = PyCFunction_GET_FUNCTION(func);
  5. void (*fpFunc)(PyVariable) = (void (*)(PyVariable))meth;
  6. PyVariable pvargs = args;
  7. fpFunc(pvargs);
  8. return Py_None;
  9. }
  10. PyObject* _pyvar_call_pv_pv(PyObject* func,PyObject* args,PyObject* kw){
  11. PyCFunction meth = PyCFunction_GET_FUNCTION(func);
  12. PyVariable (*fpFunc)(PyVariable) = (PyVariable (*)(PyVariable))meth;
  13. PyVariable pvargs = args;
  14. PyVariable result = fpFunc(pvargs);
  15. return result.get();
  16. }
  17. void _pyvar_dealloc_func(PyObject* fp){
  18. // nothing to free for us
  19. }
  20. static PyTypeObject _pyvar_functype_void_pv = {
  21. PyObject_HEAD_INIT(NULL)
  22. 0, /*ob_size*/
  23. "Cfunc(void(*)(PyVariable))", /*tp_name*/
  24. sizeof(PyObject), /*tp_basicsize*/
  25. 0, /*tp_itemsize*/
  26. _pyvar_dealloc_func, /*tp_dealloc*/
  27. /*tp_print,tp_getattr,tp_setattr,tp_compare,tp_repr,
  28. tp_as_number,tp_as_sequence,tp_as_mapping,tp_hash*/
  29. 0,0,0,0,0,0,0,0,0,
  30. _pyvar_call_void_pv, /*tp_call*/
  31. /*tp_str,tp_getattro,tp_setattro,tp_as_buffer*/
  32. 0,0,0,0,
  33. Py_TPFLAGS_DEFAULT, /*tp_flags*/
  34. "PyVariable function (void (*)(PyV&))",/* tp_doc */
  35. };
  36. static PyTypeObject _pyvar_functype_pv_pv = {
  37. PyObject_HEAD_INIT(NULL)
  38. 0, /*ob_size*/
  39. "Cfunc(PyVariable(*)(PyVariable))", /*tp_name*/
  40. sizeof(PyObject), /*tp_basicsize*/
  41. 0, /*tp_itemsize*/
  42. _pyvar_dealloc_func, /*tp_dealloc*/
  43. /*tp_print,tp_getattr,tp_setattr,tp_compare,tp_repr,
  44. tp_as_number,tp_as_sequence,tp_as_mapping,tp_hash*/
  45. 0,0,0,0,0,0,0,0,0,
  46. _pyvar_call_pv_pv, /*tp_call*/
  47. /*tp_str,tp_getattro,tp_setattro,tp_as_buffer*/
  48. 0,0,0,0,
  49. Py_TPFLAGS_DEFAULT, /*tp_flags*/
  50. "PyVariable function (PyV (*)(PyV))",/* tp_doc */
  51. };
  52. PyVariable::PyVariable() {
  53. m_obj = NULL;
  54. m_flag = 42;
  55. }
  56. PyVariable::PyVariable(const PyVariable& o){
  57. m_obj = o.m_obj;
  58. m_flag = o.m_flag;
  59. Py_XINCREF(m_obj);
  60. }
  61. PyVariable::PyVariable(PyObject* obj, bool isBorrowedRef) {
  62. /* Borrowed References are when we get a PyObject* we do not "own", that is,
  63. * we are not responsible to "free" it, or to decref it.
  64. * One can either use a flag or just increase the reference count, and then
  65. * automatically decref any PyObject in a PyVariable. The second is what is
  66. * done here.
  67. */
  68. if (isBorrowedRef){
  69. Py_XINCREF(obj);
  70. }
  71. m_obj = obj;
  72. m_flag = 42;
  73. }
  74. PyVariable::PyVariable(const char* s) {
  75. m_obj = PyString_FromString(s);
  76. m_flag = 42;
  77. }
  78. PyVariable::PyVariable(std::string s) {
  79. m_obj = PyString_FromString(s.c_str());
  80. m_flag = 42;
  81. }
  82. PyVariable::PyVariable(int i) {
  83. m_obj = PyInt_FromLong(i);
  84. m_flag = 42;
  85. }
  86. PyVariable::PyVariable(long i) {
  87. m_obj = PyInt_FromLong(i);
  88. m_flag = 42;
  89. }
  90. PyVariable::PyVariable(double d) {
  91. m_obj = PyFloat_FromDouble(d);
  92. m_flag = 42;
  93. }
  94. PyVariable::PyVariable(PyObject* (*fpFunc)(PyObject*,PyObject*)){
  95. //this is bad and will cause a memory leak because there won't be
  96. //any track of methd, so it can't be freed...
  97. PyMethodDef* methd = new PyMethodDef();
  98. methd->ml_name = "pyvar_func";
  99. methd->ml_meth = fpFunc;
  100. methd->ml_flags= METH_VARARGS;
  101. methd->ml_doc = NULL;
  102. PyObject* name = PyString_FromString(methd->ml_name);
  103. m_obj = PyCFunction_NewEx(methd,NULL,name);
  104. Py_DECREF(name);
  105. m_flag = 42;
  106. }
  107. PyVariable::PyVariable(void (*fpFunc)(PyVariable)){
  108. PyMethodDef* methd = new PyMethodDef();
  109. methd->ml_name = "pyvar_func";
  110. methd->ml_meth = (PyObject* (*)(PyObject*,PyObject*))fpFunc;
  111. methd->ml_flags= METH_VARARGS;
  112. methd->ml_doc = NULL;
  113. PyObject* name = PyString_FromString(methd->ml_name);
  114. m_obj = PyCFunction_NewEx(methd,NULL,name);
  115. Py_DECREF(name);
  116. // give our own function object type
  117. m_obj->ob_type = &_pyvar_functype_void_pv;
  118. m_flag = 42;
  119. }
  120. PyVariable::PyVariable(PyVariable (*fpFunc)(PyVariable)){
  121. PyMethodDef* methd = new PyMethodDef();
  122. methd->ml_name = "pyvar_func";
  123. methd->ml_meth = (PyObject* (*)(PyObject*,PyObject*))fpFunc;
  124. methd->ml_flags= METH_VARARGS;
  125. methd->ml_doc = NULL;
  126. PyObject* name = PyString_FromString(methd->ml_name);
  127. m_obj = PyCFunction_NewEx(methd,NULL,name);
  128. Py_DECREF(name);
  129. // give our own function object type
  130. m_obj->ob_type = &_pyvar_functype_pv_pv;
  131. m_flag = 42;
  132. }
  133. PyVariable::~PyVariable() {
  134. if (m_obj != NULL) {
  135. if (PyInt_Check(m_obj)) {
  136. /* "The current implementation keeps an array of integer objects for all
  137. * integers between -5 and 256, when you create an int in that range
  138. * you actually just get back a reference to the existing object.
  139. * So it should be possible to change the value of 1.
  140. * I suspect the behaviour of Python in this case is undefined."*/
  141. int i = c_int();
  142. if (i < -5 || i > 256) {
  143. Py_DECREF(m_obj);
  144. }
  145. }else{
  146. Py_XDECREF(m_obj);
  147. }
  148. }
  149. for (std::list<void*>::iterator it = m_tofree.begin(); it != m_tofree.end(); ++it) {
  150. //printf("freeing stuff from %p %s\n",this,*it);
  151. free(*it);
  152. }
  153. }
  154. PyObject* PyVariable::get() {
  155. if (m_obj == NULL) {
  156. throw PyException("PyVariable::get", "the PyVariable is empty");
  157. }
  158. return m_obj;
  159. }
  160. bool PyVariable::isEmpty() {
  161. return m_obj == NULL;
  162. }
  163. bool PyVariable::isNone(){
  164. return m_obj == Py_None;
  165. }
  166. PyVariable PyVariable::setitem(PyVariable k,PyVariable val) {
  167. if (PyDict_Check(m_obj)){
  168. PyDict_SetItem(m_obj,k.get(),val.get());
  169. } else{
  170. throw PyException("PyVariable::setitem","Object is not a dictionnary");
  171. }
  172. return *this;
  173. }
  174. PyVariable PyVariable::getattr(std::string attr){
  175. PyVariable ret_value;
  176. PyObject* o = PyObject_GetAttrString(m_obj, attr.c_str());
  177. if (o == NULL) {
  178. throw PyException("PyVariable::getattr", "No such attribute "+attr+" in object.");
  179. }
  180. return PyVariable(o);
  181. }
  182. /**
  183. * @return the string value of this PyVariable using PyObject_Str
  184. */
  185. const char* PyVariable::c_str() {
  186. if (m_obj != NULL) {
  187. PyObject* s = PyObject_Str(m_obj);
  188. // "The pointer refers to the internal buffer of string, not a copy."
  189. char* ret = PyString_AsString(s);
  190. size_t len = strlen(ret);
  191. char* local = (char*)malloc(len+1);
  192. memcpy(local,ret,len);
  193. local[len]=0;
  194. Py_DECREF(s);
  195. //printf("alloc %p %d %s\n",local,len,local);
  196. m_tofree.push_back((void*)local);
  197. //printf("tofree %p\n",this);
  198. return local;
  199. } else {
  200. return "(null)";
  201. }
  202. }
  203. /**
  204. * @return the string value of this PyVariable using PyObject_Str
  205. */
  206. std::string PyVariable::str() {
  207. if (m_obj != NULL) {
  208. PyObject* s = PyObject_Str(m_obj);
  209. std::string local(PyString_AsString(s),PyString_Size(s));
  210. Py_DECREF(s);
  211. return local;
  212. } else {
  213. return "(null)";
  214. }
  215. }
  216. int PyVariable::c_int() {
  217. return PyInt_AsLong(m_obj);
  218. }
  219. PyVariable PyVariable::append(PyVariable e, int nrepeat){
  220. if (PyList_Check(m_obj)){
  221. for (int i=0;i<nrepeat;i++){
  222. PyList_Append(m_obj,e.get());
  223. }
  224. }else{
  225. throw PyException("PyVariable::append","Object is not a list. Cannot append.");
  226. }
  227. return *this;
  228. }
  229. PyVariable PyVariable::operator+(PyVariable other) {
  230. PyObject* o = other.get();
  231. PyObject* result = PyNumber_Add(m_obj, o);
  232. return PyVariable(result);
  233. }
  234. PyVariable PyVariable::operator-(PyVariable other) {
  235. PyObject* o = other.get();
  236. PyObject* result = PyNumber_Subtract(m_obj, o);
  237. return PyVariable(result);
  238. }
  239. PyVariable PyVariable::operator/(PyVariable other) {
  240. PyObject* o = other.get();
  241. PyObject* result = PyNumber_Divide(m_obj, o);
  242. return PyVariable(result);
  243. }
  244. PyVariable PyVariable::operator*(PyVariable other) {
  245. PyObject* o = other.get();
  246. PyObject* result = PyNumber_Multiply(m_obj, o);
  247. return PyVariable(result);
  248. }
  249. void PyVariable::operator=(PyVariable other) {
  250. if (m_obj!=NULL){Py_XDECREF(m_obj);}
  251. m_obj = other.get();
  252. m_flag = other.m_flag;
  253. Py_XINCREF(m_obj);
  254. }
  255. void PyVariable::operator=(long other) {
  256. Py_XDECREF(m_obj);
  257. m_obj = PyInt_FromLong(other);
  258. }
  259. void PyVariable::operator=(const char* other) {
  260. Py_XDECREF(m_obj);
  261. m_obj = PyString_FromString(other);
  262. }
  263. PyVariable PyVariable::operator[](int index) {
  264. PyObject* pyindex = PyInt_FromLong(index);
  265. PyVariable ret_value;
  266. if (PySequence_Check(m_obj)) {
  267. if (PySequence_Length(m_obj) > index) {
  268. ret_value = PyVariable(PySequence_GetItem(m_obj, index));
  269. } else {
  270. throw PyException("PyVariable::operator[]", "Index out of range");
  271. }
  272. } else if (PyDict_Check(m_obj)) {
  273. if (PyDict_Contains(m_obj, pyindex)) {
  274. ret_value = PyVariable(PyDict_GetItem(m_obj, pyindex));
  275. } else {
  276. throw PyException("PyVariable::operator[]", "Dict has no such key");
  277. }
  278. } else {
  279. throw PyException("PyVariable::operator[]", "Not a sequence or a dict");
  280. }
  281. Py_DECREF(pyindex);
  282. return ret_value;
  283. }
  284. PyVariable PyVariable::operator[](std::string key) {
  285. PyObject* pyindex = PyString_FromString(key.c_str());
  286. PyVariable ret_value;
  287. if (PyDict_Check(m_obj)) {
  288. if (PyDict_Contains(m_obj, pyindex)) {
  289. ret_value = PyVariable(PyDict_GetItem(m_obj, pyindex),true);
  290. } else {
  291. throw PyException("PyVariable::operator[]", "Dict has no such key: "+key);
  292. }
  293. } else {
  294. PyObject* o = PyObject_GetAttr(m_obj, pyindex);
  295. if (o == NULL) {
  296. o = PyObject_GetItem(m_obj,pyindex);
  297. if (o == NULL){
  298. throw PyException("PyVariable::operator[]", "Object not a dict, and no such attribute "+key+" in object.");
  299. }
  300. }
  301. ret_value = PyVariable(o,true);
  302. }
  303. Py_DECREF(pyindex);
  304. return ret_value;
  305. }
  306. PyVariable PyVariable::operator[](const char* key){
  307. std::string k(key);
  308. return (*this)[k];
  309. }
  310. PyVariable PyVariable::operator[](PyVariable index) {
  311. PyObject* pyindex = index.get();
  312. PyVariable ret_value;
  313. if (PySequence_Check(m_obj)) {
  314. ret_value = PyVariable(PySequence_GetItem(m_obj, index.c_int()),true);
  315. } else if (PyDict_Check(m_obj)) {
  316. if (PyDict_Contains(m_obj, pyindex)) {
  317. ret_value = PyVariable(PyDict_GetItem(m_obj, pyindex),true);
  318. } else {
  319. throw PyException("PyVariable::operator[]", "Dict has no such key");
  320. }
  321. } else {
  322. throw PyException("PyVariable::operator[]", "Not a sequence or a dict");
  323. }
  324. return ret_value;
  325. }
  326. PyVariable PyVariable::operator()(PyVariable arg1,
  327. PyVariable arg2,
  328. PyVariable arg3){
  329. int len = 1;
  330. if (arg2.get()!=Py_None){++len;}
  331. if (arg3.get()!=Py_None){++len;}
  332. PyObject* args = PyTuple_Pack(len,arg1.get(),arg2.get(),arg3.get());
  333. PyObject* o = PyObject_Call(this->get(),args,NULL);
  334. if (o == NULL){
  335. throw PyException("PyVariable::operator()","Error during function call");
  336. }
  337. Py_XDECREF(args);
  338. return PyVariable(o);
  339. }
  340. PyVariable PyVariable::operator()(){
  341. PyObject* o = PyObject_Call(this->get(),PyTuple_New(0),NULL);
  342. if (o == NULL){
  343. throw PyException("PyVariable::operator()","Error during function call");
  344. }
  345. return PyVariable(o);
  346. }
  347. /////////////////////
  348. // static stuff
  349. PyVariable PyVariable::dict() {
  350. return PyDict_New();
  351. }
  352. PyVariable PyVariable::list() {
  353. return PyList_New(0);
  354. }
  355. PyVariable PyVariable::new_int() {
  356. return PyVariable(PyInt_FromLong(0));
  357. }
  358. PyVariable PyVariable::new_str() {
  359. return PyVariable(PyString_FromString(""));
  360. }
  361. PyVariable PyVariable::new_tuple() {
  362. return PyVariable(PyTuple_New(0));
  363. }
  364. PyVariable PyVariable::exec(std::string str) {
  365. return PyVariable(PyRun_String(str.c_str(),Py_eval_input,PyEval_GetBuiltins(),0));
  366. }
  367. PyVariable PyVariable::exec(const char* str,const char* format,...) {
  368. PyVariable locals = PyVariable::dict();
  369. PyVariable elems = format;
  370. elems = elems["split"](",");
  371. int num = elems["__len__"]();
  372. va_list arguments;
  373. va_start ( arguments, num );
  374. for ( int x = 0; x < num; x++ ){
  375. PyVariable* arg = va_arg ( arguments, PyVariable* );
  376. // increase ref because PyDict_SetItem doesn't, so when
  377. // `locals` is freed, it decrefs it's arguments because they are supposed
  378. // to be borrowed references
  379. Py_XINCREF(arg->get());
  380. locals.setitem(elems[x],arg->get());
  381. }
  382. va_end ( arguments );
  383. return PyVariable(PyRun_String(str,Py_eval_input,PyEval_GetBuiltins(),locals.get()));
  384. }
  385. PyVariable PyVariable::import(std::string module_name){
  386. PyObject* o = PyImport_ImportModule(module_name.c_str());
  387. if (o==NULL){
  388. throw PyException("PyVariable::import","Importing module "+module_name+" failed.");
  389. }
  390. return PyVariable(o);
  391. }
  392. PyVariable PyVariable::reload(PyVariable module){
  393. PyObject* o = PyImport_ReloadModule(module.get());
  394. if (o==NULL){
  395. throw PyException("PyVariable::import","Reloading module failed.");
  396. }
  397. return PyVariable(o);
  398. }