C/C++ API

Anything that doesn't fit elsewhere.
stephanmg
Posts: 68
Joined: Tue Jul 03, 2012 4:40 am

C/C++ API

Post by stephanmg »

Dear NEURON Users,

i know that there exists the possibility to control NEURON via Python Code. (import neuron)

I would ask for a C/C++ API because i want to execute a NEURON Simulation in my C++ Application.

All the best,
Stephan
hines
Site Admin
Posts: 1682
Joined: Wed May 18, 2005 3:32 pm

Re: C/C++ API

Post by hines »

There is not yet a formal API for NEURON but one can use the nrn/src/nrnpython cpp files for examples of how
python uses NEURON functions and data. Python loads NEURON as an extension and gets it initialized via
inithoc.cpp
After that you can execute any hoc statement (e.g. load_file) with hoc_valid_stmt(stmt, 0) as done by
nrnexec in nrnpy_hoc.cpp. The beginning of the file lists many NEURON functions used to retrieve information.
Section, Mechanism, Range Variable interaction is handled in nrnpy_nrn.cpp.
Also, many useful functions are listed in nrn/src/ivoc/oc2iv.h and nrn/src/nrniv/nrnoc2iv.h
stephanmg
Posts: 68
Joined: Tue Jul 03, 2012 4:40 am

Re: C/C++ API

Post by stephanmg »

Hi there Hines,

i've build NEURON with PYTHON support, therefore using:

import neuron
...
additional python NEURON code.


I'm using Python's functionality for embedding it into it with the high level Python API into C++: http://docs.python.org/extending/embedding.html

Example is:

extern "C" {
#include <Python.h>
}
Py_Initialize();
PyRun_SimpleString("from neuron import h\n");
Py_Finalize();



But this fails with:
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/home/stephan/local/lib/python2.7/site-packages/neuron/__init__.py", line 81, in <module>
import neuron.hoc
ImportError: /home/stephan/neuron/nrn/x86_64/lib/libnrnpython.so.0: undefined symbol: PyExc_ImportError
Error in sys.excepthook:
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/apport_python_hook.py", line 64, in apport_excepthook
from apport.fileutils import likely_packaged, get_recent_crashes
File "/usr/lib/python2.7/dist-packages/apport/__init__.py", line 1, in <module>
from apport.report import Report
File "/usr/lib/python2.7/dist-packages/apport/report.py", line 16, in <module>
from xml.parsers.expat import ExpatError
File "/usr/lib/python2.7/xml/parsers/expat.py", line 4, in <module>
from pyexpat import *
ImportError: /usr/lib/python2.7/lib-dynload/pyexpat.so: undefined symbol: _Py_ZeroStruct

Original exception was:
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/home/stephan/local/lib/python2.7/site-packages/neuron/__init__.py", line 81, in <module>
import neuron.hoc
ImportError: /home/stephan/neuron/nrn/x86_64/lib/libnrnpython.so.0: undefined symbol: PyExc_ImportError
terminate called without an active exception
Aborted (core dumped)



Please note: invoking the Python interpreter in a Bash shell, and import neuron module works.

Let me know if you can suggest anything.

All the best,
Stephan
hines
Site Admin
Posts: 1682
Joined: Wed May 18, 2005 3:32 pm

Re: C/C++ API

Post by hines »

I'd start by leaving out the import neuron line and instead compare
import sys
sys.path

It may be that launching python sets up a bit more environment than what you are getting with Py_Initialize.
stephanmg
Posts: 68
Joined: Tue Jul 03, 2012 4:40 am

Re: C/C++ API

Post by stephanmg »

Thank you again.

Is there a possibility to use only C/C++ code to control NEURON from within an C/C++ application? (I don't want to bother with Python)

All the best,
Stephan
hines
Site Admin
Posts: 1682
Joined: Wed May 18, 2005 3:32 pm

Re: C/C++ API

Post by hines »

Yes. My best hint is the above 05 Jul 2012 post. You can dynamically load or link your executable against the installed libnrniv.so just like a launch of
python loads nrniv as a module using src/nrnpython/inithoc.cpp . The first test is to execute a hoc statement from your c++ program.
stephanmg
Posts: 68
Joined: Tue Jul 03, 2012 4:40 am

Re: C/C++ API

Post by stephanmg »

Ah okay,

just to be sure if I'm doing things correct:

I've built NEURON without IV and have those .so files. Now I need to include in analogy to your example, NEURON in my own C++ application, then building and linking against the NEURON libs.

Am I right?

All the best and sorry for bothering you again,
Stephan
stephanmg
Posts: 68
Joined: Tue Jul 03, 2012 4:40 am

Re: C/C++ API

Post by stephanmg »

Thank you very much. I figured it out. It's still failing while linking because linking order matters... i'm currently figuring out the correct linkage order:

g++ -L nrn-7.3/x86_64/lib/ example.c -lnrnoc -livoc -loc -livos -lnrniv -lmeschach -lscopmath -lsparse13 -lneuron_gnu -lnrnmpi -lmemacs -lsundials
nrn-7.3/x86_64/lib//liboc.so: undefined reference to `rl_deprep_terminal'
nrn-7.3/x86_64/lib//liboc.so: undefined reference to `rl_event_hook'
nrn-7.3/x86_64/lib//liboc.so: undefined reference to `readline'
nrn-7.3/x86_64/lib//libnrnoc.so: undefined reference to `modl_reg'
nrn-7.3/x86_64/lib//liboc.so: undefined reference to `add_history'


some suggestions? :)

All the best,
Stephan
hines
Site Admin
Posts: 1682
Joined: Wed May 18, 2005 3:32 pm

Re: C/C++ API

Post by hines »

I created a static version configured using
../nrn/configure --prefix=`pwd` --without-x --disable-shared --enable-static linux_nrnmech=no
and then nrnivmodl gives a link line of
libtool: link: g++ -g -O2 -pthread -o special /home/hines/neuron/nrnstatic/x86_64/lib/nrnmain.o /home/hines/neuron/nrnstatic/x86_64/lib/ivocmain.o /home/hines/neuron/nrnstatic/x86_64/lib/nvkludge.o temp.o mod_func.o -L/home/hines/neuron/nrnstatic/x86_64/lib /home/hines/neuron/nrnstatic/x86_64/lib/libnrnoc.a /home/hines/neuron/nrnstatic/x86_64/lib/libnrniv.a /home/hines/neuron/nrnstatic/x86_64/lib/libivoc.a /home/hines/neuron/nrnstatic/x86_64/lib/liboc.a /home/hines/neuron/nrnstatic/x86_64/lib/libneuron_gnu.a /home/hines/neuron/nrnstatic/x86_64/lib/libscopmath.a /home/hines/neuron/nrnstatic/x86_64/lib/libsparse13.a /home/hines/neuron/nrnstatic/x86_64/lib/libsundials.a /home/hines/neuron/nrnstatic/x86_64/lib/libnrnmpi.a /home/hines/neuron/nrnstatic/x86_64/lib/libmemacs.a /home/hines/neuron/nrnstatic/x86_64/lib/libmeschach.a /home/hines/neuron/nrnstatic/x86_64/lib/libivos.a /home/hines/neuron/nrnstatic/x86_64/lib/libreadline.a -lncurses -lm -ldl -pthread

from that I infer
-lnrnoc -lnrniv -livoc -loc-lneuron_gnu -lscopmath -lsparse13 -lsundials -lnrnmpi -lmemacs -lmeschach -livos -lreadline -lncurses -lm
might work.
hines
Site Admin
Posts: 1682
Joined: Wed May 18, 2005 3:32 pm

Re: C/C++ API

Post by hines »

forgot to mention that
ivocmain.o nvkludge.o
may be needed to ensure some names in the libraries get linked (perhaps because used in later libraries)
stephanmg
Posts: 68
Joined: Tue Jul 03, 2012 4:40 am

Re: C/C++ API

Post by stephanmg »

Using this linkage i arrive at that error, mh:

nrn-7.3/x86_64/lib//libnrnoc.so: undefined reference to `modl_reg'

I will try to figure out this, i will update my post if I could figure out for other people.


My example code is (also i defined nil to be NULL since nil is otherwise undefined somehow):

Code: Select all

#define nil NULL
#include "nrn-7.3/src/ivoc/oc2iv.h"
int main(int argc, char** argv) {
   int i = 10;
   bool test = hoc_is_double_arg(i);
   return 1;
}
My compile line is:

Code: Select all

 g++ -L nrn-7.3/x86_64/lib/ example.cpp nrn-7.3/x86_64/lib/nvkludge.o nrn-7.3/x86_64/lib/ivocmain.o -lnrnoc -lnrniv -livoc -loc -lneuron_gnu -lscopmath -lsparse13 -lsundials -lnrnmpi -lmemacs -lmeschach -livos -lreadline -lncurses -lm -locxt
And I build NEURON with that line:

Code: Select all

./configure --prefix=`pwd` --without-iv; make; make install
Maybe you see where I fail.

Addentum: I added nrn-7.3/x86_64/src/oc/modlreg.o and now it compiles, but when running:

./a.out: error while loading shared libraries: libnrnoc.so.0: cannot open shared object file: No such file or directory

I guess I need to change my LD_LIBRARY_PATH variable?

=> Changed it, but now it results in an Segmentation Fault. Is this to be expected in my (buggy?) example code? And is adding modlreg.o from src folder correct?


Best regards,
Stephan
hines
Site Admin
Posts: 1682
Joined: Wed May 18, 2005 3:32 pm

Re: C/C++ API

Post by hines »

Code: Select all

bool test = hoc_is_double_arg(i);
is out of context since it assumes the interpreter has called your main function. It looks at the argument the interpreter put on its stack.
But the interpreter was never started. You would need to follow the initialization process used in nrniv/nrnmain.cpp which calls
ivocmain in ivoc/ivocmain.cpp
stephanmg
Posts: 68
Joined: Tue Jul 03, 2012 4:40 am

Re: C/C++ API

Post by stephanmg »

hines wrote:

Code: Select all

bool test = hoc_is_double_arg(i);
is out of context since it assumes the interpreter has called your main function. It looks at the argument the interpreter put on its stack.
But the interpreter was never started. You would need to follow the initialization process used in nrniv/nrnmain.cpp which calls
ivocmain in ivoc/ivocmain.cpp
Thank you again hines! :)
I must have been over-reading this. Sorry.

All the best,
Stephan
stephanmg
Posts: 68
Joined: Tue Jul 03, 2012 4:40 am

Re: C/C++ API

Post by stephanmg »

Update:

I managed to compile the code below (which executes valid hoc statements as expected now, yeah!).
I compiled it with the line:

Code: Select all

 g++  -L nrn-7.3/x86_64/lib/ nrn-7.3/src/oc/modlreg.o  example.cpp nrn-7.3/x86_64/lib/nvkludge.o -lnrnoc -lnrniv -livoc -loc -lneuron_gnu -lscopmath -lsparse13 -lsundials -lnrnmpi -lmemacs -lmeschach -livos -lreadline -lncurses -lm -locxt
And ran it by:

Code: Select all

LD_LIBRARY_PATH=nrn-7.3/x86_64/lib/ ./a.out 
Outputting:
NEURON -- Release 7.3 (849:5be3d097b917) 2013-04-11
Duke, Yale, and the BlueBrain Project -- Copyright 1984-2013
See http://www.neuron.yale.edu/neuron/credits

Executing hoc statement (t = 0) succeded? Yes.
In case of someone finds this useful, i reported it.

Code: Select all

// define nil (how to circumvent that define?)
#define nil NULL
// necessary includes
#include "nrn-7.3/src/ivoc/oc2iv.h"
#include "nrn-7.3/src/ivoc/ivocmain.cpp"
#include "nrn-7.3/src/ivoc/ocjump.cpp"

// extern C functions
extern bool hoc_valid_stmt(const char* stmt, Object* ob);
extern int ivocmain(int, char**, char**);

// oc environment
static char* env[] = {0};

// main
int main(int argc, char** argv) {
   const int init = 0;
   ivocmain(init, argv, env);
   const char* stmt = "t = 0";
   const bool ret = hoc_valid_stmt(stmt, 0);
   std::cout << "Executing hoc statement (" << stmt << ") succeded? " << (ret ? "Yes." : "No.") << std::endl;
   return 1;
}
Nevertheless I need to ask two minor questions:

1) How can i retrieve for example the membrane potential or the value of a variable through execution of hoc_valid_stmt? In fact I need to access a variable defined by a hoc expression like my_val = v(i).
2) How can i get rid of the #define nil NULL - which i guess is quite non-optimal?



I struggled a while for compiling and linking an C++ app with NEURON, as for that i will provide in future (as a post in this forum) a CMakeLists.txt file for custom projects using the hoc interpreter, as I'm going to do for now manually... maybe someone will find this useful (if something like a CMakeLists already exists I'm sorry I did not find it in the www).

All the best,
Stephan
hines
Site Admin
Posts: 1682
Joined: Wed May 18, 2005 3:32 pm

Re: C/C++ API

Post by hines »

extern double hoc_ac_
is known to the interpreter. So you can execute
hoc_valid_stmt("hoc_ac_ = expr...", 0);
and then look at hoc_ac_

I think
#define nil NULL
is fine.
Post Reply