NEURON
nrnpy_p2h.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 
3 #include <stdio.h>
4 #include <InterViews/resource.h>
5 #include <nrnoc2iv.h>
6 #include <classreg.h>
7 #include <nrnpython.h>
8 #include <hoccontext.h>
9 #include "nrnpy_utils.h"
10 
11 #include "parse.hpp"
12 extern void hoc_nopop();
13 extern void hoc_pop_defer();
14 extern Object* hoc_new_object(Symbol*, void*);
15 extern int hoc_stack_type();
16 extern char** hoc_strpop();
17 extern Object** hoc_objpop();
18 extern Object* hoc_pop_object();
19 extern void hoc_tobj_unref(Object**);
20 extern int hoc_ipop();
21 PyObject* nrnpy_hoc2pyobject(Object*);
22 PyObject* hocobj_call_arg(int);
23 Object* nrnpy_pyobject_in_obj(PyObject*);
24 int nrnpy_ho_eq_po(Object*, PyObject*);
25 char* nrnpyerr_str();
26 extern void* (*nrnpy_save_thread)();
27 extern void (*nrnpy_restore_thread)(void*);
28 static void* save_thread() { return PyEval_SaveThread(); }
29 static void restore_thread(void* g) {PyEval_RestoreThread((PyThreadState*)g); }
30 extern Symbol* nrnpy_pyobj_sym_;
32 extern void (*nrnpy_hpoasgn)(Object*, int);
33 extern double (*nrnpy_praxis_efun)(Object*, Object*);
34 extern int (*nrnpy_hoccommand_exec)(Object*);
35 extern int (*nrnpy_hoccommand_exec_strret)(Object*, char*, int);
36 extern void (*nrnpy_cmdtool)(Object*, int, double, double, int);
37 extern double (*nrnpy_func_call)(Object*, int, int*);
38 extern Object* (*nrnpy_callable_with_args)(Object*, int);
39 extern double (*nrnpy_guigetval)(Object*);
40 extern void (*nrnpy_guisetval)(Object*, double);
41 extern int (*nrnpy_guigetstr)(Object*, char**);
42 extern char* (*nrnpy_po2pickle)(Object*, size_t* size);
43 extern Object* (*nrnpy_pickle2po)(char*, size_t size);
44 extern char* (*nrnpy_callpicklef)(char*, size_t size, int narg,
45  size_t* retsize);
46 extern int (*nrnpy_pysame)(Object*, Object*); // contain same Python object
47 extern Object* (*nrnpympi_alltoall_type)(int, int);
48 typedef struct {
49  PyObject_HEAD Section* sec_;
50  char* name_;
51  PyObject* cell_;
52 } NPySecObj;
55 extern "C" void nrnpython_reg_real();
56 PyObject* nrnpy_ho2po(Object*);
57 void nrnpy_decref_defer(PyObject*);
58 PyObject* nrnpy_pyCallObject(PyObject*, PyObject*);
59 
60 Object* nrnpy_po2ho(PyObject*);
61 static void py2n_component(Object*, Symbol*, int, int);
62 static void hpoasgn(Object*, int);
63 static double praxis_efun(Object*, Object*);
64 static int hoccommand_exec(Object*);
65 static int hoccommand_exec_strret(Object*, char*, int);
66 static void grphcmdtool(Object*, int, double, double, int);
67 static double func_call(Object*, int, int*);
68 static Object* callable_with_args(Object*, int);
69 static double guigetval(Object*);
70 static void guisetval(Object*, double);
71 static int guigetstr(Object*, char**);
72 static char* po2pickle(Object*, size_t* size);
73 static Object* pickle2po(char*, size_t size);
74 static char* call_picklef(char*, size_t size, int narg, size_t* retsize);
75 static Object* py_alltoall_type(int, int);
76 static int pysame(Object*, Object*);
77 static PyObject* main_module;
78 static PyObject* main_namespace;
79 static hoc_List* dlist;
80 #if NRNPYTHON_DYNAMICLOAD
81 extern int nrnpy_site_problem;
82 extern int* nrnpy_site_problem_p;
83 #endif
84 
85 class Py2Nrn {
86  public:
87  Py2Nrn();
88  virtual ~Py2Nrn();
89  int type_; // 0 toplevel
90  PyObject* po_;
91 };
92 
93 static void* p_cons(Object*) {
94  Py2Nrn* p = new Py2Nrn();
95  return p;
96 }
97 
98 static void p_destruct(void* v) { delete (Py2Nrn*)v; }
99 
101 
102 static void call_python_with_section(Object* pyact, Section* sec) {
103  PyObject* po = ((Py2Nrn*)pyact->u.this_pointer)->po_;
104  PyObject* r;
105  PyLockGIL lock;
106 
107  PyObject* args = PyTuple_Pack(1, (PyObject*) newpysechelp(sec));
108  r = nrnpy_pyCallObject(po, args);
109  Py_XDECREF(args);
110  Py_XDECREF(r);
111  if (!r) {
112  char* mes = nrnpyerr_str();
113  if (mes) {
114  Fprintf(stderr, "%s\n", mes);
115  free(mes);
116  lock.release();
117  hoc_execerror("Call of Python Callable failed", NULL);
118  }
119  if (PyErr_Occurred()) {
120  PyErr_Print();
121  }
122  }
123 }
124 
125 extern void* (*nrnpy_opaque_obj2pyobj_p_)(Object*);
126 static void* opaque_obj2pyobj(Object* ho) {
127  assert(ho && ho->ctemplate->sym == nrnpy_pyobj_sym_);
128  PyObject* po =((Py2Nrn*)ho->u.this_pointer)->po_;
129  assert(po);
130  return po;
131 }
132 
133 extern "C" void nrnpython_reg_real() {
134  //printf("nrnpython_reg_real()\n");
135  class2oc("PythonObject", p_cons, p_destruct, p_members, NULL, NULL, NULL);
136  Symbol* s = hoc_lookup("PythonObject");
137  assert(s);
138  nrnpy_pyobj_sym_ = s;
159  dlist = hoc_l_newlist();
160 #if NRNPYTHON_DYNAMICLOAD
161  nrnpy_site_problem_p = &nrnpy_site_problem;
162 #endif
163 }
164 
165 
167  po_ = NULL;
168  type_ = 0;
169  // printf("Py2Nrn() %p\n", this);
170 }
172  PyLockGIL lock;
173  Py_XDECREF(po_);
174  // printf("~Py2Nrn() %p\n", this);
175 }
176 
177 int nrnpy_ho_eq_po(Object* ho, PyObject* po) {
178  if (ho->ctemplate->sym == nrnpy_pyobj_sym_) {
179  return ((Py2Nrn*)ho->u.this_pointer)->po_ == po;
180  }
181  return 0;
182 }
183 
184 int pysame(Object* o1, Object* o2) {
185  if (o2->ctemplate->sym == nrnpy_pyobj_sym_) {
186  return nrnpy_ho_eq_po(o1, ((Py2Nrn*)o2->u.this_pointer)->po_);
187  }
188  return 0;
189 }
190 
191 PyObject* nrnpy_hoc2pyobject(Object* ho) {
192  PyObject* po = ((Py2Nrn*)ho->u.this_pointer)->po_;
193  if (!po) {
194  if (!main_module) {
195  main_module = PyImport_AddModule("__main__");
196  main_namespace = PyModule_GetDict(main_module);
197  Py_INCREF(main_module);
198  Py_INCREF(main_namespace);
199  }
200  po = main_module;
201  }
202  return po;
203 }
204 
206  Py2Nrn* pn = new Py2Nrn();
207  pn->po_ = po;
208  Py_INCREF(po);
209  pn->type_ = 1;
210  Object* on = hoc_new_object(nrnpy_pyobj_sym_, (void*)pn);
211  hoc_obj_ref(on);
212  return on;
213 }
214 
215 PyObject* nrnpy_pyCallObject(PyObject* callable, PyObject* args) {
216  // When hoc calls a PythonObject method, then in case python
217  // calls something back in hoc, the hoc interpreter must be
218  // at the top level
219  HocTopContextSet PyObject* p = PyObject_CallObject(callable, args);
220 #if 0
221 printf("PyObject_CallObject callable\n");
222 PyObject_Print(callable, stdout, 0);
223 printf("\nargs\n");
224 PyObject_Print(args, stdout, 0);
225 printf("\nreturn %p\n", p);
226 #endif
228  // It would be nice to handle the error here, ending with a hoc_execerror
229  // for any Exception (note, that does not include SystemExit). However
230  // since many, but not all, of the callers need to clean up and
231  // release the GIL, errors get handled by the caller or higher up.
232  // The almost generic idiom is:
233  /**
234  if (!p) {
235  char* mes = nrnpyerr_str();
236  if (mes) {
237  Fprintf(stderr, "%s\n", mes);
238  free(mes);
239  hoc_execerror("Call of Python Callable failed", NULL);
240  }
241  if (PyErr_Occurred()) {
242  PyErr_Print(); // Python process will exit with the error code specified by the SystemExit instance.
243  }
244  }
245  **/
246  return p;
247 }
248 
249 void py2n_component(Object* ob, Symbol* sym, int nindex, int isfunc) {
250 #if 0
251  if (isfunc) {
252  printf("py2n_component %s.%s(%d)\n", hoc_object_name(ob), sym->name, nindex);
253  }else{
254  printf("py2n_component %s.%s[%d]\n", hoc_object_name(ob), sym->name, nindex);
255  }
256 #endif
257  int i;
258  Py2Nrn* pn = (Py2Nrn*)ob->u.this_pointer;
259  PyObject* head = pn->po_;
260  PyObject* tail;
261  PyLockGIL lock;
262  if (pn->type_ == 0) { // top level
263  if (!main_module) {
264  main_module = PyImport_AddModule("__main__");
265  main_namespace = PyModule_GetDict(main_module);
266  Py_INCREF(main_module);
267  Py_INCREF(main_namespace);
268  }
269  tail =
270  PyRun_String(sym->name, Py_eval_input, main_namespace, main_namespace);
271  } else {
272  Py_INCREF(head);
273  if (strcmp(sym->name, "_") == 0) {
274  tail = head;
275  Py_INCREF(tail);
276  } else {
277  tail = PyObject_GetAttrString(head, sym->name);
278  }
279  }
280  if (!tail) {
281  PyErr_Print();
282  lock.release();
283  hoc_execerror("No attribute:", sym->name);
284  }
285  PyObject* args = 0;
286  Object* on;
287  PyObject* result = 0;
288  if (isfunc) {
289  args = PyTuple_New(nindex);
290  for (i = 0; i < nindex; ++i) {
291  PyObject* arg = nrnpy_hoc_pop();
292  // PyObject_Print(arg, stdout, 0);
293  // printf(" %d arg %d\n", arg->ob_refcnt, i);
294  if (PyTuple_SetItem(args, nindex - 1 - i, arg)) {
295  assert(0);
296  }
297  }
298  // printf("PyObject_CallObject %s %p\n", sym->name, tail);
299  result = nrnpy_pyCallObject(tail, args);
300  Py_DECREF(args);
301  // PyObject_Print(result, stdout, 0);
302  // printf(" result of call\n");
303  if (!result) {
304  char* mes = nrnpyerr_str();
305  Py_XDECREF(tail);
306  Py_XDECREF(head);
307  if (mes) {
308  Fprintf(stderr, "%s\n", mes);
309  free(mes);
310  lock.release();
311  hoc_execerror("PyObject method call failed:", sym->name);
312  }
313  if (PyErr_Occurred()) {
314  PyErr_Print();
315  }
316  return;
317  }
318  } else if (nindex) {
319  PyObject* arg;
320  if (hoc_stack_type() == NUMBER) {
321  arg = Py_BuildValue("l", (long)hoc_xpop());
322  } else {
323  arg = nrnpy_hoc_pop();
324  }
325  result = PyObject_GetItem(tail, arg);
326  if (!result) {
327  PyErr_Print();
328  lock.release();
329  hoc_execerror("Python get item failed:", hoc_object_name(ob));
330  }
331  } else {
332  result = tail;
333  Py_INCREF(result);
334  }
335  // printf("py2n_component %s %d %s result refcount=%d\n", hoc_object_name(ob),
336  // ob->refcount, sym->name, result->ob_refcnt);
337  // if numeric, string, or python HocObject return those
338  if (nrnpy_numbercheck(result)) {
339  hoc_pop_defer();
340  PyObject* pn = PyNumber_Float(result);
341  hoc_pushx(PyFloat_AsDouble(pn));
342  Py_XDECREF(pn);
343  Py_XDECREF(result);
344  } else if (is_python_string(result)) {
345  char** ts = hoc_temp_charptr();
346  Py2NRNString str(result, true);
347  *ts = str.c_str();
348  hoc_pop_defer();
349  hoc_pushstr(ts);
350  // how can we defer the result unref til the string is popped
351  nrnpy_decref_defer(result);
352  } else {
353  // PyObject_Print(result, stdout, 0);
354  on = nrnpy_po2ho(result);
355  hoc_pop_defer();
356  hoc_push_object(on);
357  if (on) {
358  on->refcount--;
359  }
360  Py_XDECREF(result);
361  }
362  Py_XDECREF(head);
363  Py_DECREF(tail);
364 }
365 
366 static void hpoasgn(Object* o, int type) {
367  int err = 0;
368  int nindex;
369  Symbol* sym;
370  PyObject* poleft;
371  PyObject* poright;
372  if (type == NUMBER) {
373  poright = PyFloat_FromDouble(hoc_xpop());
374  } else if (type == STRING) {
375  poright = Py_BuildValue("s", *hoc_strpop());
376  } else if (type == OBJECTVAR || type == OBJECTTMP) {
377  Object** po2 = hoc_objpop();
378  poright = nrnpy_ho2po(*po2);
379  hoc_tobj_unref(po2);
380  } else {
381  hoc_execerror("Cannot assign that type to PythonObject", (char*)0);
382  }
383  Object* stack_value = hoc_pop_object();
384  assert(o == stack_value);
385  poleft = nrnpy_hoc2pyobject(o);
386  sym = hoc_spop();
387  nindex = hoc_ipop();
388  // printf("hpoasgn %s %s %d\n", hoc_object_name(o), sym->name, nindex);
389  if (nindex == 0) {
390  err = PyObject_SetAttrString(poleft, sym->name, poright);
391  } else if (nindex == 1) {
392  PyObject* key = PyLong_FromDouble(hoc_xpop());
393  PyObject* a = PyObject_GetAttrString(poleft, sym->name);
394  if (a) {
395  err = PyObject_SetItem(a, key, poright);
396  Py_DECREF(a);
397  }else{
398  err = -1;
399  }
400  Py_DECREF(key);
401  } else {
402  char buf[512];
403  sprintf(buf, "%s.%s[][]...=...:", hoc_object_name(o), sym->name);
405  buf,
406  "HOC cannot handle PythonObject assignment with more than one index.");
407  }
408  Py_DECREF(poright);
409  if (err) {
410  PyErr_Print();
411  hoc_execerror("Assignment to PythonObject failed", NULL);
412  }
413 }
414 
415 void nrnpy_decref_defer(PyObject* po) {
416  if (po) {
417 #if 0
418  PyObject* ps = PyObject_Str(po);
419  printf("defer %s\n", PyString_AsString(ps));
420  Py_DECREF(ps);
421 #endif
422  hoc_l_lappendvoid(dlist, (void*)po);
423  }
424 }
425 
426 static PyObject* hoccommand_exec_help1(PyObject* po) {
427  PyObject* r;
428  // PyObject_Print(po, stdout, 0);
429  // printf("\n");
430  if (PyTuple_Check(po)) {
431  PyObject* args = PyTuple_GetItem(po, 1);
432  if (!PyTuple_Check(args)) {
433  args = PyTuple_Pack(1, args);
434  }else{
435  Py_INCREF(args);
436  }
437  // PyObject_Print(PyTuple_GetItem(po, 0), stdout, 0);
438  // printf("\n");
439  // PyObject_Print(args, stdout, 0);
440  // printf("\n");
441  // printf("threadstate %p\n", PyThreadState_GET());
442  r = nrnpy_pyCallObject(PyTuple_GetItem(po, 0), args);
443  Py_DECREF(args);
444  } else {
445  PyObject* args = PyTuple_New(0);
446  r = nrnpy_pyCallObject(po, args);
447  Py_DECREF(args);
448  }
449  return r;
450 }
451 
452 static PyObject* hoccommand_exec_help(Object* ho) {
453  PyObject* po = ((Py2Nrn*)ho->u.this_pointer)->po_;
454  // printf("%s\n", hoc_object_name(ho));
455  return hoccommand_exec_help1(po);
456 }
457 
458 static double praxis_efun(Object* ho, Object* v) {
459  PyLockGIL lock;
460 
461  PyObject* pc = nrnpy_ho2po(ho);
462  PyObject* pv = nrnpy_ho2po(v);
463  PyObject* po = Py_BuildValue("(OO)", pc, pv);
464  Py_XDECREF(pc);
465  Py_XDECREF(pv);
466  PyObject* r = hoccommand_exec_help1(po);
467  Py_XDECREF(po);
468  if (!r) {
469  char* mes = nrnpyerr_str();
470  if (mes) {
471  Fprintf(stderr, "%s\n", mes);
472  free(mes);
473  lock.release();
474  hoc_execerror("Call of Python Callable failed in praxis_efun", NULL);
475  }
476  if (PyErr_Occurred()) {
477  PyErr_Print();
478  }
479  return 1e9; // SystemExit?
480  }
481  PyObject* pn = PyNumber_Float(r);
482  double x = PyFloat_AsDouble(pn);
483  Py_XDECREF(pn);
484  Py_XDECREF(r);
485  return x;
486 }
487 
488 static int hoccommand_exec(Object* ho) {
489  PyLockGIL lock;
490 
491  PyObject* r = hoccommand_exec_help(ho);
492  if (r == NULL) {
493  char* mes = nrnpyerr_str();
494  if (mes) {
495  Fprintf(stderr, "%s\n", mes);
496  free(mes);
497  lock.release();
498  hoc_execerror("Python Callback failed", 0);
499  }
500  if (PyErr_Occurred()) {
501  PyErr_Print();
502  }
503  }
504  Py_XDECREF(r);
505  return (r != NULL);
506 }
507 
508 static int hoccommand_exec_strret(Object* ho, char* buf, int size) {
509  PyLockGIL lock;
510 
511  PyObject* r = hoccommand_exec_help(ho);
512  if (r) {
513  PyObject* pn = PyObject_Str(r);
514  Py2NRNString str(pn);
515  Py_XDECREF(pn);
516  strncpy(buf, str.c_str(), size);
517  buf[size - 1] = '\0';
518  Py_XDECREF(r);
519  } else {
520  char* mes = nrnpyerr_str();
521  if (mes) {
522  Fprintf(stderr, "%s\n", mes);
523  free(mes);
524  lock.release();
525  hoc_execerror("Python Callback failed", 0);
526  }
527  if (PyErr_Occurred()) {
528  PyErr_Print();
529  }
530  }
531  return (r != NULL);
532 }
533 
534 static void grphcmdtool(Object* ho, int type, double x, double y, int key) {
535  PyObject* po = ((Py2Nrn*)ho->u.this_pointer)->po_;
536  PyObject* r;
537  PyLockGIL lock;
538 
539  PyObject* args = PyTuple_Pack(4, PyInt_FromLong(type), PyFloat_FromDouble(x),
540  PyFloat_FromDouble(y), PyInt_FromLong(key));
541  r = nrnpy_pyCallObject(po, args);
542  Py_XDECREF(args);
543  Py_XDECREF(r);
544  if (!r) {
545  char* mes = nrnpyerr_str();
546  if (mes) {
547  Fprintf(stderr, "%s\n", mes);
548  free(mes);
549  lock.release();
550  hoc_execerror("Python Callback failed", 0);
551  }
552  if (PyErr_Occurred()) {
553  PyErr_Print();
554  }
555  }
556 }
557 
559  PyObject* po = ((Py2Nrn*)ho->u.this_pointer)->po_;
560  PyLockGIL lock;
561 
562  PyObject* args = PyTuple_New((Py_ssize_t)narg);
563  if (args == NULL) {
564  lock.release();
565  hoc_execerror("PyTuple_New failed", 0);
566  }
567  for (int i = 0; i < narg; ++i) {
568  PyObject* item = nrnpy_hoc_pop();
569  if (item == NULL) {
570  Py_XDECREF(args);
571  lock.release();
572  hoc_execerror("nrnpy_hoc_pop failed", 0);
573  }
574  if (PyTuple_SetItem(args, (Py_ssize_t)(narg - i - 1), item) != 0) {
575  Py_XDECREF(args);
576  lock.release();
577  hoc_execerror("PyTuple_SetItem failed", 0);
578  }
579  }
580 
581  PyObject* r = PyTuple_New(2);
582  PyTuple_SetItem(r, 1, args);
583  Py_INCREF(po); // when r is destroyed, do not want po refcnt to go to 0
584  PyTuple_SetItem(r, 0, po);
585 
586  Object* hr = nrnpy_po2ho(r);
587  Py_XDECREF(r);
588 
589  return hr;
590 }
591 
592 static double func_call(Object* ho, int narg, int* err) {
593  PyObject* po = ((Py2Nrn*)ho->u.this_pointer)->po_;
594  PyObject* r;
595  PyLockGIL lock;
596 
597  PyObject* args = PyTuple_New((Py_ssize_t)narg);
598  if (args == NULL) {
599  lock.release();
600  hoc_execerror("PyTuple_New failed", 0);
601  }
602  for (int i = 0; i < narg; ++i) {
603  PyObject* item = nrnpy_hoc_pop();
604  if (item == NULL) {
605  Py_XDECREF(args);
606  lock.release();
607  hoc_execerror("nrnpy_hoc_pop failed", 0);
608  }
609  if (PyTuple_SetItem(args, (Py_ssize_t)(narg - i - 1), item) != 0) {
610  Py_XDECREF(args);
611  lock.release();
612  hoc_execerror("PyTuple_SetItem failed", 0);
613  }
614  }
615 
616  r = nrnpy_pyCallObject(po, args);
617  Py_XDECREF(args);
618  double rval = 0.0;
619  if (r == NULL) {
620  if (!err || *err) {
621  char* mes = nrnpyerr_str();
622  if (mes) {
623  Fprintf(stderr, "%s\n", mes);
624  free(mes);
625  }
626  if (PyErr_Occurred()) {
627  PyErr_Print();
628  }
629  }else{
630  PyErr_Clear();
631  }
632  if (!err || *err) {
633  lock.release();
634  hoc_execerror("func_call failed", NULL);
635  }
636  if (err) { *err = 1; }
637  }else{
638  if (nrnpy_numbercheck(r)) {
639  PyObject* pn = PyNumber_Float(r);
640  rval = PyFloat_AsDouble(pn);
641  Py_XDECREF(pn);
642  }
643  Py_XDECREF(r);
644  if (err) { *err = 0; } // success
645  }
646  return rval;
647 }
648 
649 static double guigetval(Object* ho) {
650  PyObject* po = ((Py2Nrn*)ho->u.this_pointer)->po_;
651  PyLockGIL lock;
652  PyObject* r = NULL;
653  PyObject* p = PyTuple_GetItem(po, 0);
654  if (PySequence_Check(p) || PyMapping_Check(p)) {
655  r = PyObject_GetItem(p, PyTuple_GetItem(po, 1));
656  }else{
657  r = PyObject_GetAttr(p, PyTuple_GetItem(po, 1));
658  }
659  PyObject* pn = PyNumber_Float(r);
660  double x = PyFloat_AsDouble(pn);
661  Py_XDECREF(pn);
662  return x;
663 }
664 
665 static void guisetval(Object* ho, double x) {
666  PyObject* po = ((Py2Nrn*)ho->u.this_pointer)->po_;
667  PyLockGIL lock;
668  PyObject* pn = PyFloat_FromDouble(x);
669  PyObject* p = PyTuple_GetItem(po, 0);
670  if (PySequence_Check(p) || PyMapping_Check(p)) {
671  PyObject_SetItem(p, PyTuple_GetItem(po, 1), pn);
672  }else{
673  PyObject_SetAttr(p, PyTuple_GetItem(po, 1), pn);
674  }
675  Py_XDECREF(pn);
676 }
677 
678 static int guigetstr(Object* ho, char** cpp) {
679  PyObject* po = ((Py2Nrn*)ho->u.this_pointer)->po_;
680  PyLockGIL lock;
681 
682  PyObject* r = PyObject_GetAttr(PyTuple_GetItem(po, 0),
683  PyTuple_GetItem(po, 1));
684  PyObject* pn = PyObject_Str(r);
685  Py2NRNString name(pn);
686  Py_DECREF(pn);
687  char* cp = name.c_str();
688  if (*cpp && strcmp(*cpp, cp) == 0) {
689  return 0;
690  }
691  if (*cpp) {
692  delete[] * cpp;
693  }
694  *cpp = new char[strlen(cp) + 1];
695  strcpy(*cpp, cp);
696  return 1;
697 }
698 
699 static PyObject* loads;
700 static PyObject* dumps;
701 
702 static void setpickle() {
703  PyObject* pickle;
704  if (!dumps) {
705  pickle = PyImport_ImportModule("pickle");
706  if (pickle) {
707  Py_INCREF(pickle);
708  dumps = PyObject_GetAttrString(pickle, "dumps");
709  loads = PyObject_GetAttrString(pickle, "loads");
710  if (dumps) {
711  Py_INCREF(dumps);
712  Py_INCREF(loads);
713  }
714  }
715  if (!dumps || !loads) {
716  hoc_execerror("Neither Python cPickle nor pickle are available", 0);
717  }
718  }
719 }
720 
721 // note that *size includes the null terminating character if it exists
722 static char* pickle(PyObject* p, size_t* size) {
723  PyObject* arg = PyTuple_Pack(1, p);
724  PyObject* r = nrnpy_pyCallObject(dumps, arg);
725  Py_XDECREF(arg);
726  if (!r && PyErr_Occurred()) {
727  PyErr_Print();
728  }
729  assert(r);
730  assert(PyBytes_Check(r));
731  *size = PyBytes_Size(r);
732  char* buf1 = PyBytes_AsString(r);
733  char* buf = new char[*size];
734  for (size_t i = 0; i < *size; ++i) {
735  buf[i] = buf1[i];
736  }
737  Py_XDECREF(r);
738  return buf;
739 }
740 
741 static char* po2pickle(Object* ho, size_t* size) {
742  setpickle();
743  if (ho && ho->ctemplate->sym == nrnpy_pyobj_sym_) {
744  PyObject* po = nrnpy_hoc2pyobject(ho);
745  char* buf = pickle(po, size);
746  return buf;
747  } else {
748  return 0;
749  }
750 }
751 
752 static PyObject* unpickle(char* s, size_t size) {
753  PyObject* ps = PyBytes_FromStringAndSize(s, size);
754  PyObject* arg = PyTuple_Pack(1, ps);
755  PyObject* po = nrnpy_pyCallObject(loads, arg);
756  assert(po);
757  Py_XDECREF(arg);
758  Py_XDECREF(ps);
759  return po;
760 }
761 
762 static Object* pickle2po(char* s, size_t size) {
763  setpickle();
764  PyObject* po = unpickle(s, size);
765  Object* ho = nrnpy_pyobject_in_obj(po);
766  Py_XDECREF(po);
767  return ho;
768 }
769 
770 /** Full python traceback error message returned as string.
771  * Caller should free the return value if not NULL
772 **/
773 char* nrnpyerr_str() {
774  if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_Exception)) {
775  PyObject *ptype, *pvalue, *ptraceback;
776  PyErr_Fetch(&ptype, &pvalue, &ptraceback);
777  PyErr_NormalizeException(&ptype, &pvalue, &ptraceback);
778  // try for full backtrace
779  PyObject* module_name = NULL;
780  PyObject* pyth_module = NULL;
781  PyObject* pyth_func = NULL;
782  PyObject* py_str = NULL;
783  char* cmes = NULL;
784 
785  // Since traceback.format_exception returns list of strings, wrap
786  // in neuron.format_exception that returns a string.
787  if (!ptraceback) {
788  ptraceback = Py_None;
789  Py_INCREF(ptraceback);
790  }
791  module_name = PyString_FromString("neuron");
792  if (module_name) {
793  pyth_module = PyImport_Import(module_name);
794  }
795  if (pyth_module) {
796  pyth_func = PyObject_GetAttrString(pyth_module, "format_exception");
797  if (pyth_func) {
798  py_str = PyObject_CallFunctionObjArgs(pyth_func, ptype, pvalue, ptraceback, NULL);
799  }
800  }
801  if (py_str) {
802  Py2NRNString mes(py_str);
803  if (mes.err()) {
804  Fprintf(stderr, "nrnperr_str: Py2NRNString failed\n");
805  } else {
806  cmes = strdup(mes.c_str());
807  if (!cmes) {
808  Fprintf(stderr, "nrnpyerr_str: strdup failed\n");
809  }
810  }
811  }
812 
813  if (!py_str) {
814  PyErr_Print();
815  Fprintf(stderr, "nrnpyerr_str failed\n");
816  }
817 
818  Py_XDECREF(module_name);
819  Py_XDECREF(pyth_func);
820  Py_XDECREF(pyth_module);
821  Py_XDECREF(ptype);
822  Py_XDECREF(pvalue);
823  Py_XDECREF(ptraceback);
824  Py_XDECREF(py_str);
825 
826  return cmes;
827  }
828  return NULL;
829 }
830 
831 char* call_picklef(char* fname, size_t size, int narg, size_t* retsize) {
832  // fname is a pickled callable, narg is the number of args on the
833  // hoc stack with types double, char*, hoc Vector, and PythonObject
834  // callable return must be pickleable.
835  PyObject* args = 0;
836  PyObject* result = 0;
837  PyObject* callable;
838 
839  setpickle();
840  PyObject* ps = PyBytes_FromStringAndSize(fname, size);
841  args = PyTuple_Pack(1, ps);
842  callable = nrnpy_pyCallObject(loads, args);
843  assert(callable);
844  Py_XDECREF(args);
845  Py_XDECREF(ps);
846 
847  args = PyTuple_New(narg);
848  for (int i = 0; i < narg; ++i) {
849  PyObject* arg = nrnpy_hoc_pop();
850  if (PyTuple_SetItem(args, narg - 1 - i, arg)) {
851  assert(0);
852  }
853  // Py_XDECREF(arg);
854  }
855  result = nrnpy_pyCallObject(callable, args);
856  Py_DECREF(callable);
857  Py_DECREF(args);
858  if (!result) {
859  char* mes = nrnpyerr_str();
860  if (mes) {
861  Fprintf(stderr, "%s\n", mes);
862  free(mes);
863  hoc_execerror("PyObject method call failed:", NULL);
864  }
865  if (PyErr_Occurred()) {
866  PyErr_Print();
867  }
868  }
869  char* rs = pickle(result, retsize);
870  Py_XDECREF(result);
871  return rs;
872 }
873 
874 #include "nrnmpi.h"
875 
876 int* mk_displ(int* cnts) {
877  int* displ = new int[nrnmpi_numprocs + 1];
878  displ[0] = 0;
879  for (int i = 0; i < nrnmpi_numprocs; ++i) {
880  displ[i + 1] = displ[i] + cnts[i];
881  }
882  return displ;
883 }
884 
885 static PyObject* char2pylist(char* buf, int np, int* cnt, int* displ) {
886  PyObject* plist = PyList_New(np);
887  assert(plist != NULL);
888  for (int i = 0; i < np; ++i) {
889  if (cnt[i] == 0) {
890  Py_INCREF(Py_None); // 'Fatal Python error: deallocating None' eventually
891  PyList_SetItem(plist, i, Py_None);
892  } else {
893  PyObject* p = unpickle(buf + displ[i], cnt[i]);
894  PyList_SetItem(plist, i, p);
895  }
896  }
897  return plist;
898 }
899 
900 #if NRNMPI
901 static PyObject* py_allgather(PyObject* psrc){
902  int np = nrnmpi_numprocs;
903  size_t sz;
904  char* sbuf = pickle(psrc, &sz);
905  // what are the counts from each rank
906  int* rcnt = new int[np];
907  rcnt[nrnmpi_myid] = int(sz);
908  nrnmpi_int_allgather_inplace(rcnt, 1);
909  int* rdispl = mk_displ(rcnt);
910  char* rbuf = new char[rdispl[np]];
911 
912  nrnmpi_char_allgatherv(sbuf, rbuf, rcnt, rdispl);
913  delete [] sbuf;
914 
915  PyObject* pdest = char2pylist(rbuf, np, rcnt, rdispl);
916  delete [] rbuf;
917  delete [] rcnt;
918  delete [] rdispl;
919  return pdest;
920 }
921 
922 static PyObject* py_gather(PyObject* psrc, int root){
923  int np = nrnmpi_numprocs;
924  size_t sz;
925  char* sbuf = pickle(psrc, &sz);
926  // what are the counts from each rank
927  int scnt = int(sz);
928  int* rcnt = NULL;
929  if (root == nrnmpi_myid) {
930  rcnt = new int[np];
931  }
932  nrnmpi_int_gather(&scnt, rcnt, 1, root);
933  int* rdispl = NULL;
934  char* rbuf = NULL;
935  if (root == nrnmpi_myid) {
936  rdispl = mk_displ(rcnt);
937  rbuf = new char[rdispl[np]];
938  }
939 
940  nrnmpi_char_gatherv(sbuf, scnt, rbuf, rcnt, rdispl, root);
941  delete [] sbuf;
942 
943  PyObject* pdest = Py_None;
944  if (root == nrnmpi_myid) {
945  pdest = char2pylist(rbuf, np, rcnt, rdispl);
946  delete [] rbuf;
947  delete [] rcnt;
948  delete [] rdispl;
949  }else{
950  Py_INCREF(pdest);
951  }
952  return pdest;
953 }
954 
955 static PyObject* py_broadcast(PyObject* psrc, int root){
956  // Note: root returns reffed psrc.
957  char* buf = NULL;
958  int cnt = 0;
959  if (root == nrnmpi_myid) {
960  size_t sz;
961  buf = pickle(psrc, &sz);
962  cnt = int(sz);
963  }
964  nrnmpi_int_broadcast(&cnt, 1, root);
965  if (root != nrnmpi_myid) {
966  buf = new char[cnt];
967  }
968  nrnmpi_char_broadcast(buf, cnt, root);
969  PyObject* pdest = psrc;
970  if (root != nrnmpi_myid) {
971  pdest = unpickle(buf, size_t(cnt));
972  }else{
973  Py_INCREF(pdest);
974  }
975  delete [] buf;
976  return pdest;
977 }
978 #endif
979 
980 //type 1-alltoall, 2-allgather, 3-gather, 4-broadcast, 5-scatter
981 // size for 3, 4, 5 refer to rootrank.
982 Object* py_alltoall_type(int size, int type) {
983  int np = nrnmpi_numprocs; // of subworld communicator
984  PyObject* psrc = NULL;
985  PyObject* pdest = NULL;
986 
987  if (type == 1 || type == 5) { // alltoall, scatter
988  Object* o = *hoc_objgetarg(1);
989  if (type == 1 || nrnmpi_myid == size) {// if scatter only root must be a list
990  psrc = nrnpy_hoc2pyobject(o);
991  if (!PyList_Check(psrc)) {
992  hoc_execerror("Argument must be a Python list", 0);
993  }
994  if (PyList_Size(psrc) != np) {
995  if (type == 1) {
996  hoc_execerror("py_alltoall list size must be nhost", 0);
997  }else{
998  hoc_execerror("py_scatter list size must be nhost", 0);
999  }
1000  }
1001  }
1002  if (np == 1) {
1003  if (type == 1) {
1004  return o;
1005  }else{ // return psrc[0]
1006  pdest = PyList_GetItem(psrc, 0);
1007  Py_INCREF(pdest);
1008  Object* ho = nrnpy_po2ho(pdest);
1009  if (ho) {
1010  --ho->refcount;
1011  }
1012  Py_XDECREF(pdest);
1013  return ho;
1014  }
1015  }
1016  }else{
1017  // Get the raw PyObject* arg. So things like None, int, bool are preserved.
1018  psrc = hocobj_call_arg(0);
1019  Py_INCREF(psrc);
1020 
1021  if (np == 1) {
1022  if (type == 4) { // broadcast is just the PyObject
1023  pdest = psrc;
1024  }else{ // allgather and gather must wrap psrc in list
1025  pdest = PyList_New(1);
1026  PyList_SetItem(pdest, 0, psrc);
1027  }
1028  Object* ho = nrnpy_po2ho(pdest);
1029  if (ho) {
1030  --ho->refcount;
1031  }
1032  Py_XDECREF(pdest);
1033  return ho;
1034  }
1035  }
1036 
1037 #if NRNMPI
1038  setpickle();
1039  int root;
1040 
1041  if (type == 2) {
1042  pdest = py_allgather(psrc);
1043  Py_DECREF(psrc);
1044  }else if (type != 1 && type != 5) {
1045  root = size;
1046  if (root < 0 || root >= np) {
1047  hoc_execerror("root rank must be >= 0 and < nhost", 0);
1048  }
1049  if (type == 3) {
1050  pdest = py_gather(psrc, root);
1051  }else if (type == 4) {
1052  pdest = py_broadcast(psrc, root);
1053  }
1054  Py_DECREF(psrc);
1055  }else{
1056 
1057  if (type == 5) { // scatter
1058  root = size;
1059  size = 0; // calculate dest size (cannot be -1 so cannot return it)
1060  }
1061 
1062  char* s = NULL;
1063  int* scnt = NULL;
1064  int* sdispl = NULL;
1065  char* r = NULL;
1066  int* rcnt = NULL;
1067  int* rdispl = NULL;
1068 
1069  // setup source buffer for transfer s, scnt, sdispl
1070  // for alltoall, each rank handled identically
1071  // for scatter, root handled as list all, other ranks handled as None
1072  if (type == 1 || nrnmpi_myid == root) { // psrc is list of nhost items
1073 
1074  scnt = new int[np];
1075  for (int i = 0; i < np; ++i) {
1076  scnt[i] = 0;
1077  }
1078 
1079  PyObject* iterator = PyObject_GetIter(psrc);
1080  PyObject* p;
1081 
1082  size_t bufsz = 100000; // 100k buffer to start with
1083  if (size > 0) { // or else the positive number specified
1084  bufsz = size;
1085  }
1086  if (size >= 0) { // otherwise count only
1087  s = new char[bufsz];
1088  }
1089  size_t curpos = 0;
1090  for (size_t i = 0; (p = PyIter_Next(iterator)) != NULL; ++i) {
1091  if (p == Py_None) {
1092  scnt[i] = 0;
1093  Py_DECREF(p);
1094  continue;
1095  }
1096  size_t sz;
1097  char* b = pickle(p, &sz);
1098  if (size >= 0) {
1099  if (curpos + sz >= bufsz) {
1100  bufsz = bufsz * 2 + sz;
1101  char* s2 = new char[bufsz];
1102  for (size_t i = 0; i < curpos; ++i) {
1103  s2[i] = s[i];
1104  }
1105  delete[] s;
1106  s = s2;
1107  }
1108  for (size_t j = 0; j < sz; ++j) {
1109  s[curpos + j] = b[j];
1110  }
1111  }
1112  curpos += sz;
1113  scnt[i] = sz;
1114  delete[] b;
1115  Py_DECREF(p);
1116  }
1117  Py_DECREF(iterator);
1118 
1119  // scatter equivalent to alltoall NONE list for not root ranks.
1120  }else if (type == 5 && nrnmpi_myid != root){
1121  // nothing to setup, s, scnt, sdispl already NULL
1122  }
1123 
1124  // destinations need to know receive counts. Then transfer data.
1125  if (type == 1) { // alltoall
1126 
1127  // what are destination counts
1128  int* ones = new int[np];
1129  for (int i = 0; i < np; ++i) {
1130  ones[i] = 1;
1131  }
1132  sdispl = mk_displ(ones);
1133  rcnt = new int[np];
1134  nrnmpi_int_alltoallv(scnt, ones, sdispl, rcnt, ones, sdispl);
1135  delete[] ones;
1136  delete[] sdispl;
1137 
1138  // exchange
1139  sdispl = mk_displ(scnt);
1140  rdispl = mk_displ(rcnt);
1141  char* r = 0;
1142  if (size < 0) {
1143  pdest = PyTuple_New(2);
1144  PyTuple_SetItem(pdest, 0, Py_BuildValue("l", (long)sdispl[np]));
1145  PyTuple_SetItem(pdest, 1, Py_BuildValue("l", (long)rdispl[np]));
1146  delete[] scnt;
1147  delete[] sdispl;
1148  delete[] rcnt;
1149  delete[] rdispl;
1150  } else {
1151  r = new char[rdispl[np] + 1]; //force > 0 for all None case
1152  nrnmpi_char_alltoallv(s, scnt, sdispl, r, rcnt, rdispl);
1153  delete[] s;
1154  delete[] scnt;
1155  delete[] sdispl;
1156 
1157  pdest = char2pylist(r, np, rcnt, rdispl);
1158 
1159  delete[] r;
1160  delete[] rcnt;
1161  delete[] rdispl;
1162  }
1163 
1164  }else{ // scatter
1165 
1166  // destination counts
1167  rcnt = new int[1];
1168  nrnmpi_int_scatter(scnt, rcnt, 1, root);
1169  r = new char[rcnt[0] + 1]; // rcnt[0] can be 0
1170 
1171  // exchange
1172  if (nrnmpi_myid == root) {sdispl = mk_displ(scnt);}
1173  nrnmpi_char_scatterv(s, scnt, sdispl, r, rcnt[0], root);
1174  if (s) delete[] s;
1175  if (scnt) delete[] scnt;
1176  if (sdispl) delete[] sdispl;
1177 
1178  if (rcnt[0]) {
1179  pdest = unpickle(r, size_t(rcnt[0]));
1180  }else{
1181  pdest = Py_None;
1182  Py_INCREF(pdest);
1183  }
1184 
1185  delete[] r;
1186  delete[] rcnt;
1187  assert (rdispl == NULL);
1188 
1189  }
1190 
1191  }
1192  Object* ho = nrnpy_po2ho(pdest);
1193  Py_XDECREF(pdest);
1194  if (ho) {
1195  --ho->refcount;
1196  }
1197  return ho;
1198 #else
1199  assert(0);
1200  return NULL;
1201 #endif
1202 }
static void setpickle()
Definition: nrnpy_p2h.cpp:702
o
Definition: seclist.cpp:180
void(* nrnpy_cmdtool)(Object *, int, double, double, int)
Definition: objcmd.cpp:19
static int hoccommand_exec(Object *)
Definition: nrnpy_p2h.cpp:488
void hoc_nopop()
void(* nrnpy_py2n_component)(Object *, Symbol *, int, int)
PyObject * nrnpy_hoc_pop()
Definition: nrnpy_hoc.cpp:551
int(* nrnpy_guigetstr)(Object *, char **)
Definition: xmenu.cpp:9
#define HocContextRestore
Definition: hoccontext.h:17
static PyObject * unpickle(char *s, size_t size)
Definition: nrnpy_p2h.cpp:752
hoc_List * hoc_l_newlist()
int hoc_ipop()
#define assert(ex)
Definition: hocassrt.h:26
static int hoccommand_exec_strret(Object *, char *, int)
Definition: nrnpy_p2h.cpp:508
static PyObject * hoccommand_exec_help1(PyObject *po)
Definition: nrnpy_p2h.cpp:426
short type
Definition: cabvars.h:10
int * mk_displ(int *cnts)
Definition: nrnpy_p2h.cpp:876
static void * p_cons(Object *)
Definition: nrnpy_p2h.cpp:93
static hoc_List * dlist
Definition: nrnpy_p2h.cpp:79
char * c_str() const
Definition: nrnpy_utils.h:42
if(status)
static Object * pickle2po(char *, size_t size)
Definition: nrnpy_p2h.cpp:762
static PyObject * main_module
Definition: nrnpy_p2h.cpp:77
#define g
Definition: passive0.cpp:23
static int guigetstr(Object *, char **)
Definition: nrnpy_p2h.cpp:678
void(* nrnpy_hpoasgn)(Object *, int)
Object *(* nrnpy_pickle2po)(char *, size_t size)
Definition: ocbbs.cpp:36
Symbol * hoc_lookup(const char *)
void(* nrnpy_restore_thread)(void *)
Definition: ivoc.cpp:44
PyObject * nrnpy_pyCallObject(PyObject *, PyObject *)
Definition: nrnpy_p2h.cpp:215
void
static void p_destruct(void *v)
Definition: nrnpy_p2h.cpp:98
void * this_pointer
Definition: hocdec.h:231
char * hoc_object_name(Object *ob)
Definition: hoc_oop.cpp:84
size_t p
static PyObject * main_namespace
Definition: nrnpy_p2h.cpp:78
static void py2n_component(Object *, Symbol *, int, int)
Definition: nrnpy_p2h.cpp:249
int(* nrnpy_hoccommand_exec_strret)(Object *, char *, int)
Definition: objcmd.cpp:18
static void nrnmpi_char_broadcast(char *, int, int)
Definition: ocbbs.cpp:61
char * name
Definition: model.h:72
Object *(* nrnpy_callable_with_args)(Object *, int)
Definition: nrnmenu.cpp:46
static int narg()
Definition: ivocvect.cpp:135
static char * pickle(PyObject *p, size_t *size)
Definition: nrnpy_p2h.cpp:722
#define Fprintf
Definition: model.h:249
#define v
Definition: md1redef.h:4
static Object ** py_broadcast(void *)
Definition: ocbbs.cpp:433
static void hpoasgn(Object *, int)
Definition: nrnpy_p2h.cpp:366
#define lock
static int pysame(Object *, Object *)
Definition: nrnpy_p2h.cpp:184
void(* nrnpy_call_python_with_section)(Object *, Section *)
Definition: secbrows.cpp:20
Object * hoc_pop_object()
Definition: code.cpp:860
sprintf(buf," if (secondorder) {\ " int _i;\" " for(_i=0;_i< %d;++_i) {\" " _p[_slist%d[_i]]+=dt *_p[_dlist%d[_i]];\" " }}\", numeqn, listnum, listnum)
void nrnpy_decref_defer(PyObject *)
Definition: nrnpy_p2h.cpp:415
#define PyInt_FromLong
Definition: nrnpython.h:29
int(* nrnpy_pysame)(Object *, Object *)
Definition: cvodeobj.cpp:529
static void guisetval(Object *, double)
Definition: nrnpy_p2h.cpp:665
Object * nrnpy_po2ho(PyObject *)
Definition: nrnpy_hoc.cpp:524
PyObject * hocobj_call_arg(int)
Definition: nrnpy_hoc.cpp:707
int refcount
Definition: hocdec.h:227
double(* nrnpy_func_call)(Object *, int, int *)
Definition: objcmd.cpp:20
static void * save_thread()
Definition: nrnpy_p2h.cpp:28
void hoc_tobj_unref(Object **)
Definition: code.cpp:219
static PyObject * loads
Definition: nrnpy_p2h.cpp:699
#define root
Definition: rbtqueue.cpp:53
Symbol * hoc_spop(void)
int nrnmpi_numprocs
static char * call_picklef(char *, size_t size, int narg, size_t *retsize)
Definition: nrnpy_p2h.cpp:831
_CONST char * s
Definition: system.cpp:74
Member_func p_members[]
Definition: nrnpy_p2h.cpp:100
char * nrnpyerr_str()
Full python traceback error message returned as string.
Definition: nrnpy_p2h.cpp:773
static void nrnmpi_int_broadcast(int *, int, int)
Definition: ocbbs.cpp:60
void class2oc(const char *, void *(*cons)(Object *), void(*destruct)(void *), Member_func *, int(*checkpoint)(void **), Member_ret_obj_func *, Member_ret_str_func *)
Definition: hoc_oop.cpp:1581
static void call_python_with_section(Object *pyact, Section *sec)
Definition: nrnpy_p2h.cpp:102
static Object * py_alltoall_type(int, int)
Definition: nrnpy_p2h.cpp:982
hoc_Item * hoc_l_lappendvoid(hoc_List *, void *)
Object ** hoc_objpop()
Definition: code.cpp:849
#define printf
Definition: mwprefix.h:26
static PyObject * hoccommand_exec_help(Object *ho)
Definition: nrnpy_p2h.cpp:452
int nrnpy_numbercheck(PyObject *po)
Definition: nrnpy_hoc.cpp:478
int nrnpy_ho_eq_po(Object *, PyObject *)
Definition: nrnpy_p2h.cpp:177
int
Definition: nrnmusic.cpp:71
static Object ** py_allgather(void *)
Definition: ocbbs.cpp:425
static const char * fname(const char *name)
Definition: nrnbbs.cpp:108
#define STRING
Definition: bbslsrv.cpp:9
double hoc_xpop(void)
double(* nrnpy_praxis_efun)(Object *, Object *)
Definition: hocprax.cpp:80
void hoc_execerror(const char *, const char *)
Definition: hoc.cpp:741
int * nrnpy_site_problem_p
Definition: nrnpy.cpp:23
#define cnt
Definition: spt2queue.cpp:19
char ** hoc_strpop()
Definition: code.cpp:868
#define key
Definition: spt2queue.cpp:20
static void nrnmpi_int_alltoallv(int *s, int *scnt, int *sdispl, int *r, int *rcnt, int *rdispl)
size_t j
void release()
Definition: nrnpy_utils.h:112
bool is_python_string(PyObject *python_string)
Definition: nrnpy_utils.h:7
Definition: model.h:57
PyObject * nrnpy_hoc2pyobject(Object *)
Definition: nrnpy_p2h.cpp:191
void hoc_push_object(Object *d)
Definition: code.cpp:657
static Object ** py_gather(void *)
Definition: ocbbs.cpp:429
Object * hoc_new_object(Symbol *, void *)
Definition: hoc_oop.cpp:465
char *(* nrnpy_callpicklef)(char *, size_t size, int narg, size_t *retsize)
Definition: ocbbs.cpp:37
static void * opaque_obj2pyobj(Object *ho)
Definition: nrnpy_p2h.cpp:126
char * name
Definition: init.cpp:16
int type_
Definition: nrnpy_p2h.cpp:89
int hoc_stack_type()
Definition: code.cpp:637
static double func_call(Object *, int, int *)
Definition: nrnpy_p2h.cpp:592
void hoc_obj_ref(Object *obj)
Definition: hoc_oop.cpp:1980
static PyObject * char2pylist(char *buf, int np, int *cnt, int *displ)
Definition: nrnpy_p2h.cpp:885
Inst * pc
Definition: code.cpp:138
void hoc_pushx(double)
PyObject * nrnpy_ho2po(Object *)
Definition: nrnpy_hoc.cpp:503
static void restore_thread(void *g)
Definition: nrnpy_p2h.cpp:29
static char * po2pickle(Object *, size_t *size)
Definition: nrnpy_p2h.cpp:741
static double guigetval(Object *)
Definition: nrnpy_p2h.cpp:649
#define PyString_FromString
Definition: nrnpython.h:24
Symbol * nrnpy_pyobj_sym_
int nrnmpi_myid
double(* nrnpy_guigetval)(Object *)
Definition: xmenu.cpp:7
Definition: hocdec.h:226
bool err() const
Definition: nrnpy_utils.h:43
void(* nrnpy_guisetval)(Object *, double)
Definition: xmenu.cpp:8
void nrnpython_reg_real()
Definition: nrnpy_p2h.cpp:133
#define i
Definition: md1redef.h:12
static Object * callable_with_args(Object *, int)
Definition: nrnpy_p2h.cpp:558
PyObject * po_
Definition: nrnpy_p2h.cpp:90
NPySecObj * newpysechelp(Section *sec)
Definition: nrnpy_nrn.cpp:871
sec
Definition: solve.cpp:885
#define arg
Definition: redef.h:28
char buf[512]
Definition: init.cpp:13
char *(* nrnpy_po2pickle)(Object *, size_t *size)
Definition: ocbbs.cpp:35
void hoc_pushstr(char **d)
Definition: code.cpp:665
Object *(* nrnpympi_alltoall_type)(int, int)
Definition: ocbbs.cpp:38
static PyObject * dumps
Definition: nrnpy_p2h.cpp:700
int(* nrnpy_hoccommand_exec)(Object *)
Definition: objcmd.cpp:17
virtual ~Py2Nrn()
Definition: nrnpy_p2h.cpp:171
#define HocTopContextSet
Definition: hoccontext.h:10
union Object::@54 u
static Symbol * pv[4]
Definition: partial.cpp:80
char ** hoc_temp_charptr(void)
Definition: code.cpp:625
void *(* nrnpy_save_thread)()
Definition: ivoc.cpp:43
Object ** hoc_objgetarg(int)
Definition: code.cpp:1568
return NULL
Definition: cabcode.cpp:461
static double praxis_efun(Object *, Object *)
Definition: nrnpy_p2h.cpp:458
void hoc_pop_defer()
Definition: code.cpp:250
void *(* nrnpy_opaque_obj2pyobj_p_)(Object *)
static void grphcmdtool(Object *, int, double, double, int)
Definition: nrnpy_p2h.cpp:534
Object * nrnpy_pyobject_in_obj(PyObject *)
Definition: nrnpy_p2h.cpp:205
#define OBJECTTMP
Definition: hocdec.h:101