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