Adapting MOD files for C++ with |neuron_with_cpp_mechanisms|
Attention!
This guide only applies if you have MOD files with VERBATIM blocks that fail to compile with |neuron_with_cpp_mechanisms| but work with older versions of NEURON. If this is not your case, you can skip this guide.
In older versions of NEURON, MOD files containing NMODL code were translated into C code before being compiled and executed by NEURON. Starting with |neuron_with_cpp_mechanisms|, NMODL code is translated into C++ code instead.
In most cases, this does not present any issues, as simple C code is typically
valid C++, and no changes are required.
However, C and C++ are not the same language, and there are cases in which MOD
files containing VERBATIM
blocks need to be modified in order to build with
|neuron_with_cpp_mechanisms|.
Before you start, you should decide if you need your MOD files to be compatible simultaneously with |neuron_with_cpp_mechanisms| and older versions, or if you can safely stop supporting older versions. Supporting both is generally possible, but it may be more cumbersome than committing to using C++ features. Considering NEURON has maintained strong backward compatibility and its internal numerical methods haven't changed with migration to C++, it is likely to be sufficient to adapt MOD files to C++ only and use |neuron_with_cpp_mechanisms|. If you do decide to preserve compatibility across versions, the preprocessor macros described in :ref:`verbatim` may prove useful.
Note
If you have a model that stopped compiling when you upgraded to or beyond |neuron_with_cpp_mechanisms|, the first thing that you should check is whether the relevant MOD files have already been updated in ModelDB or in the GitHub repository of that model. You can check the repository name with the model accession number under https://github.com/ModelDBRepository. An updated version may already be available!
The following models were updated in ModelDB in preparation for |neuron_with_cpp_mechanisms| and may serve as useful references. You can see updated MOD files in the Changed Mod Files column. You can just apply the changes to your MOD files, or you can use the updated MOD files directly from the GitHub repository.
ModelDB Id | Model Name | GitHub Repository | Pull Request | Changed Mod Files |
---|---|---|---|---|
2487 | Olfactory Mitral Cell (Davison et al 2000) | ModelDBRepository/2487 | pull/1 | cadecay.mod |
2730 | Olfactory Bulb Network (Davison et al 2003) | ModelDBRepository/2730 | pull/1 | cadecay.mod |
2733 | Olfactory Mitral Cell (Bhalla, Bower 1993) | ModelDBRepository/2733 | pull/1 | cadecay.mod |
3658 | Glutamate diffusion ...lar glomerulus (Saftenku 2005) | ModelDBRepository/3658 | pull/1 | glubbfbm.mod glubes2.mod glubes23.mod glubes3.mod glubes4.mod glubes5.mod glubes6.mod glures23.mod |
7399 | Feedforward heteroas...with HH dynamics (Lytton 1998) | ModelDBRepository/7399 | pull/1 | matrix.mod snsarr.inc vecst.mod |
7400 | Hippocampus temporo-...gram shift model (Lytton 1999) | ModelDBRepository/7400 | pull/1 | matrix.mod vecst.mod |
8284 | Febrile seizure-indu...ations to Ih (Chen et al 2001) | ModelDBRepository/8284 | pull/1 | hyperde1.mod hyperde2.mod hyperde3.mod hyperso.mod ichan.mod |
9889 | Thalamic quiescence ...e seizures (Lytton et al 1997) | ModelDBRepository/9889 | pull/1 | rand.mod |
12631 | Computer model of cl...n thalamic slice (Lytton 1997) | ModelDBRepository/12631 | pull/2 | rand.mod |
26997 | Gamma oscillations i... networks (Wang, Buzsaki 1996) | ModelDBRepository/26997 | pull/1 | vecst.mod |
35358 | CA3 pyramidal cell: ...ub model (Pinsky, Rinzel 1994) | ModelDBRepository/35358 | pull/2 | matrix.mod vecst.mod |
37819 | Thalamocortical augm...response (Bazhenov et al 1998) | ModelDBRepository/37819 | pull/1 | matrix.mod pointer.inc ppsav.inc vecst.mod |
51781 | Dentate gyrus networ...model (Santhakumar et al 2005) | ModelDBRepository/51781 | pull/1 | hyperde3.mod ichan2.mod |
52034 | Cortical network mod...leptogenesis (Bush et al 1999) | ModelDBRepository/52034 | pull/1 | holt_rnd.mod precall.mod snsarr.inc |
64229 | Parallel network sim...h NEURON (Migliore et al 2006) | ModelDBRepository/64229 | pull/1 | parbulbNet/cadecay.mod |
64296 | Dynamical model of o...al cell (Rubin, Cleland 2006) | ModelDBRepository/64296 | pull/1 | cadecay.mod |
87585 | Sodium channel mutat...eizures + (Barela et al. 2006) | ModelDBRepository/87585 | pull/1 | ichanR859C1.mod ichanWT2005.mod |
93321 | Activity dependent c...euron model (Liu et al. 1998) | ModelDBRepository/93321 | pull/1 | cadecay.mod |
97868 | NEURON interfaces to...gorithm (Neymotin et al. 2008) | ModelDBRepository/97868 | pull/2 | MySQL.mod spud.mod vecst.mod |
97874 | Neural Query System ...NEURON Simulator (Lytton 2006) | ModelDBRepository/97874 | pull/2 | NQS/vecst.mod modeldb/vecst.mod |
97917 | Cell splitting in ne...ng scaling (Hines et al. 2008) | ModelDBRepository/97917 | pull/2 | nrntraub/mod/rand.mod nrntraub/mod/ri.mod pardentategyrus/hyperde3.mod pardentategyrus/ichan2.mod |
105507 | Tonic-clonic transit...tion (Lytton and Omurtag 2007) | ModelDBRepository/105507 | pull/2 | intf_.mod misc.mod stats.mod vecst.mod |
106891 | JitCon: Just in time... networks (Lytton et al. 2008) | ModelDBRepository/106891 | pull/3 | jitcon.mod misc.h misc.mod stats.mod vecst.mod |
113732 | MEG of Somatosensory Neocortex (Jones et al. 2007) | ModelDBRepository/113732 | pull/1 | precall.mod presyn.inc |
116094 | Lateral dendrodendit...ctory Bulb (David et al. 2008) | ModelDBRepository/116094 | pull/1 | LongDendrite/cadecay.mod ShortDendrite/cadecay.mod |
116830 | Broadening of activi...tructures (Lytton et al. 2008) | ModelDBRepository/116830 | pull/1 | intf.mod misc.mod stats.mod vecst.mod |
116838 | The virtual slice setup (Lytton et al. 2008) | ModelDBRepository/116838 | pull/1 | intf_.mod misc.h misc.mod stats.mod vecst.mod |
116862 | Thalamic interneuron...rtment model (Zhu et al. 1999) | ModelDBRepository/116862 | pull/1 | clampex.mod misc.h vecst.mod |
123815 | Encoding and retriev...rcuit (Cutsuridis et al. 2009) | ModelDBRepository/123815 | pull/1 | burststim2.mod ichan2.mod regn_stim.mod |
136095 | Synaptic information...columns (Neymotin et al. 2010) | ModelDBRepository/136095 | pull/1 | clampex.mod field.mod infot.mod intf_.mod intfsw.mod misc.h misc.mod netrand.inc pregencv.mod stats.mod updown.mod vecst.mod |
136310 | Modeling local field...otentials (Bedard et al. 2004) | ModelDBRepository/136310 | pull/1 | ImpedanceFM.mod |
137845 | Spike exchange metho...rcomputer (Hines et al., 2011) | ModelDBRepository/137845 | pull/1 | invlfire.mod |
138379 | Emergence of physiol...lations (Neymotin et al. 2011) | ModelDBRepository/138379 | pull/1 | intf6_.mod misc.h misc.mod stats.mod vecst.mod |
139421 | Ketamine disrupts th...pocampus (Neymotin et al 2011) | ModelDBRepository/139421 | pull/1 | misc.h misc.mod stats.mod vecst.mod wrap.mod |
140881 | Computational Surgery (Lytton et al. 2011) | ModelDBRepository/140881 | pull/1 | intf6_.mod misc.h misc.mod stats.mod vecst.mod |
141505 | Prosthetic electrost...ortical simulation (Kerr 2012) | ModelDBRepository/141505 | pull/1 | infot.mod intf6_.mod intfsw.mod misc.h misc.mod staley.mod stats.mod vecst.mod |
144538 | Reinforcement learni...ement (Chadderdon et al. 2012) | ModelDBRepository/144538 | pull/1 | infot.mod intf6_.mod intfsw.mod misc.h misc.mod stats.mod updown.mod vecst.mod |
144549 | Hopfield and Brody m...d, Brody 2000) (NEURON+python) | ModelDBRepository/144549 | pull/1 | misc.h misc.mod stats.mod vecst.mod |
144586 | Boolean network-base...sis network (Mai and Liu 2009) | ModelDBRepository/144586 | pull/1 | bnet.mod misc.h misc.mod stats.mod vecst.mod |
146949 | Motor cortex microci...pping (Chadderdon et al. 2014) | ModelDBRepository/146949 | pull/1 | infot.mod intf6.mod intfsw.mod matrix.mod misc.h misc.mod staley.mod stats.mod vecst.mod |
149000 | Using Strahler`s ana...c models (Marasco et al, 2013) | ModelDBRepository/149000 | pull/1 | pj.mod |
149739 | A two-layer biophysi...dulation (Li and Cleland 2013) | ModelDBRepository/149739 | pull/1 | cadecay.mod cadecay2.mod |
150240 | A Model Circuit of T...vergence (Behuret et al. 2013) | ModelDBRepository/150240 | pull/1 | RandomGenerator.mod |
150245 | Sensorimotor cortex ...eaching (Neymotin et al. 2013) | ModelDBRepository/150245 | pull/1 | infot.mod intf6_.mod misc.h misc.mod stats.mod vecst.mod |
150551 | Calcium waves and mG...rons (Ashhad & Narayanan 2013) | ModelDBRepository/150551 | pull/1 | Calamp.mod |
150556 | Single compartment D...MPA (Biddell and Johnson 2013) | ModelDBRepository/150556 | pull/1 | KBNetStim.mod |
150691 | Model of arrhythmias...twork (Casaleggio et al. 2014) | ModelDBRepository/150691 | pull/1 | Readme halfgapm1.mod halfgapspk.mod |
151126 | Effects of increasin... network (Bianchi et al. 2014) | ModelDBRepository/151126 | pull/1 | burststim2.mod ichan2.mod regn_stim.mod |
151282 | Ih tunes oscillation...3 model (Neymotin et al. 2013) | ModelDBRepository/151282 | pull/1 | misc.h misc.mod stats.mod vecst.mod |
153280 | Parvalbumin-positive...amidal cells (Lee et al. 2014) | ModelDBRepository/153280 | pull/1 | ch_Kdrfast.mod mynetstim.mod repeatconn.mod |
154732 | Spine head calcium i...ell model (Graham et al. 2014) | ModelDBRepository/154732 | pull/1 | burststim2.mod |
155568 | Dentate gyrus network model (Tejada et al 2014) | ModelDBRepository/155568 | pull/1 | hyperde3.mod ichan2.mod |
155601 | Basket cell extrasyn...tions (Proddutur et al., 2013) | ModelDBRepository/155601 | pull/1 | hyperde3.mod ichan2.mod |
155602 | Status epilepticus a...c inhibition (Yu J et al 2013) | ModelDBRepository/155602 | pull/1 | hyperde3.mod ichan2.mod |
156780 | Microcircuits of L5 ...midal cells (Hay & Segev 2015) | ModelDBRepository/156780 | pull/1 | ProbAMPANMDA2.mod ProbUDFsyn2.mod |
157157 | CA1 pyramidal neuron...cles (Saudargiene et al. 2015) | ModelDBRepository/157157 | pull/1 | burststim2.mod regn_stim.mod |
168874 | Neuronal dendrite ca...e model (Neymotin et al, 2015) | ModelDBRepository/168874 | pull/4 | misc.h misc.mod stats.mod vecst.mod |
181967 | Long time windows fr...op (Cutsuridis & Poirazi 2015) | ModelDBRepository/181967 | pull/1 | burststim.mod hyperde3.mod ichan2.mod regn_stim.mod |
182129 | Computational modeli...signaling (Lupascu et al 2020) | ModelDBRepository/182129 | pull/1 | ProbGABAAB_EMS_GEPH_g.mod |
183300 | Mitral cell activity...ory bulb NN (Short et al 2016) | ModelDBRepository/183300 | pull/1 | cadecay.mod cadecay2.mod thetastim.mod vecstim.mod |
185355 | Dentate gyrus networ...g in epilepsy (Yim et al 2015) | ModelDBRepository/185355 | pull/2 | HCN.mod ichan2.mod netstim125.mod netstimbox.mod |
185858 | Ca+/HCN channel-depe...eocortex (Neymotin et al 2016) | ModelDBRepository/185858 | pull/1 | misc.h misc.mod vecst.mod |
186768 | CA3 Network Model of...Activity (Sanjay et. al, 2015) | ModelDBRepository/186768 | pull/1 | misc.h misc.mod stats.mod vecst.mod wrap.mod |
187604 | Hippocampal CA1 NN w...ork clamp (Bezaire et al 2016) | ModelDBRepository/187604 | pull/2 | fastconn.mod mynetstim.mod repeatconn.mod sgate.mod |
189154 | Multitarget pharmaco...ia in M1 (Neymotin et al 2016) | ModelDBRepository/189154 | pull/1 | misc.h misc.mod stats.mod vecst.mod |
194897 | Motor system model w...l arm (Dura-Bernal et al 2017) | ModelDBRepository/194897 | pull/2 | izhi2007.mod nsloc.mod vecevent.mod |
195615 | Computer models of c...ynamics (Neymotin et al. 2017) | ModelDBRepository/195615 | pull/1 | misc.h misc.mod vecst.mod |
223031 | Interneuron Specific...l (Guet-McCreight et al, 2016) | ModelDBRepository/223031 | pull/1 | S1/ingauss.mod S2/ingauss.mod SD/ingauss.mod SDprox1/ingauss.mod SDprox2/ingauss.mod |
225080 | CA1 pyr cell: Inhibi...ssion (Grienberger et al 2017) | ModelDBRepository/225080 | pull/1 | pr.mod vecevent.mod |
231427 | Shaping NMDA spikes ...on on L5PC (Doron et al. 2017) | ModelDBRepository/231427 | pull/2 | ProbAMPA.mod ProbUDFsyn2_lark.mod |
232097 | 2D model of olfactor...llations (Li and Cleland 2017) | ModelDBRepository/232097 | pull/1 | cadecay.mod cadecay2.mod |
239177 | Phase response theor...(Tikidji-Hamburyan et al 2019) | ModelDBRepository/239177 | pull/1 | PIR-Inetwork/innp.mod PIR-Inetwork/vecevent.mod |
241165 | Biophysically realis...imulation (Aberra et al. 2018) | ModelDBRepository/241165 | pull/1 | mechanisms/ProbAMPANMDA_EMS.mod mechanisms/ProbGABAAB_EMS.mod |
241240 | Role of afferent-hai...regularity (Holmes et al 2017) | ModelDBRepository/241240 | pull/1 | afhcsyn_i0.mod hc1.mod random.mod ribbon1.mod |
244262 | Deconstruction of co...ic DBS (Kumaravelu et al 2018) | ModelDBRepository/244262 | pull/1 | rand.mod ri.mod |
244848 | Active dendrites sha...urons (Basak & Narayanan 2018) | ModelDBRepository/244848 | pull/2 | apamp.mod |
247968 | Gamma genesis in the...ral amygdala (Feng et al 2019) | ModelDBRepository/247968 | pull/1 | Gfluct_new_exc.mod Gfluct_new_inh.mod vecevent.mod |
249463 | Layer V pyramidal ce...cs (Mäki-Marttunen et al 2019) | ModelDBRepository/249463 | pull/1 | almog/ProbAMPANMDA2.mod almog/ProbUDFsyn2.mod hay/ProbAMPANMDA2.mod hay/ProbUDFsyn2.mod |
256388 | The APP in C-termina...n firing (Pousinha et al 2019) | ModelDBRepository/256388 | pull/1 | burststim2.mod ichan2.mod regn_stim.mod |
259366 | Cycle skipping in IN...dji-Hamburyan & Canavier 2020) | ModelDBRepository/259366 | pull/1 | innp.mod |
This section aims to list some patterns that the NEURON developers have found in pre-|neuron_with_cpp_mechanisms| models that need to be modified to be valid C++.
C++ has stricter rules governing pointer type conversions than C. For example
double* x = (void*)0; // valid C, invalid C++
double* x = nullptr; // valid C++, invalid C
double* x = (double*)0; // valid C and C++ (C-style casts discouraged in C++)
Similarly, in C one can pass a void*
argument to a function that expects a
double*
. In C++ this is forbidden.
The same issue may manifest itself in code such as
double* x = malloc(7 * sizeof(double)); // valid C, invalid C++
double* x = new double[7]; // valid C++, invalid C
double* x = (double*)malloc(7 * sizeof(double)); // valid C and C++ (C-style casts discouraged in C++)
If you choose to move from using C malloc
and free
to using C++ new
and delete
then remember that you cannot mix and match new
with free
and so on.
Note
Explicit memory management with new
and delete
is discouraged in C++
(R.11: Avoid calling new and delete explicitly).
If you do not need to support older versions of NEURON, you may be able to
use standard library containers such as std::vector<T>
.
In C, the function declaration
void some_function();
is a non-prototype function declaration: it declares
that some_function
exists, but it does not specify the number of arguments
that it takes, or their types.
In C++, the same code declares that some_function
takes zero arguments (the
C equivalent of this is void some_function(void)
).
If such a declaration occurs in a top-level VERBATIM
block then it is
likely to be harmless: it will add a zero-parameter overload of the function,
which will never be called.
It will, however, cause a problem if the declaration is included inside
an NMODL construct
PROCEDURE procedure() {
VERBATIM
void some_method_taking_an_int(); // problematic in C++
some_method_taking_an_int(42);
ENDVERBATIM
}
because in this case the local declaration hides the real declaration, which is something like
void some_method_taking_an_int(int);
in a NEURON header that is included when the translated MOD file is compiled. In this case, the problematic local declaration can simply be removed.
In older MOD files and versions of NEURON, API methods were often accessed by declaring them in the MOD file and not by including a correct declaration from NEURON itself. In NEURON 8.2+, more declarations are implicitly included when MOD files are compiled. This can lead to problems if the declaration in the MOD file did not specify the correct argument and return types.
Rand* nrn_random_arg(int); // correct declaration from NEURON header, only in new NEURON
/* ... */
void* nrn_random_arg(int); // incorrect declaration in MOD file, clashes with previous line
The fix here is simply to remove the incorrect declaration from the MOD file.
If the argument types are incorrect, the situation is slightly more nuanced. This is because C++ supports overloading functions by argument type, but not by return type.
void sink(Thing*); // correct declaration from NEURON header, only in new NEURON
/* ... */
void sink(void*); // incorrect declaration in MOD file, adds an overload, not a compilation error
/* ... */
void* void_ptr;
sink(void_ptr); // probably used to work, now causes a linker error
Thing* thing_ptr;
sink(thing_ptr); // works with both old and new NEURON
Here the incorrect declaration sink(void*)
declares a second overload of
the sink
function, which is not defined anywhere.
With |neuron_with_cpp_mechanisms| the sink(void_ptr)
line will select the
void*
second overload, based on the argument type, and this will fail during
linking because this overload is not defined (only sink(Thing*)
has a
definition).
In contrast, sink(thing_ptr)
will select the correct overload in
|neuron_with_cpp_mechanisms|, and it also works in older NEURON versions
because Thing*
can be implicitly converted to void*
.
The fix here is, again, to remove the incorrect declaration from the MOD file.
See also the section below, :ref:`deprecated-overloads-taking-void`, for cases
where NEURON does provide a (deprecated) definition of the void*
overload.
C supports (until C23) a legacy ("K&R") syntax for function declarations. This is not valid C++.
There is no advantage to the legacy syntax. If you have legacy definitions such as
void foo(a, b) int a, b; { /* ... */ }
then simply replace them with
void foo(int a, int b) { /* ... */ }
which is valid in both C and C++.
As noted above (:ref:`local-non-prototype-function-declaration`), declarations such as
VERBATIM
extern void vector_resize();
ENDVERBATIM
at the global scope in MOD files declare C++ function overloads that take no
parameters.
If such declarations appear at the global scope then they do not hide the
correct declarations, so this can be harmless, but it is not necessary.
In |neuron_with_cpp_mechanisms| the full declarations of the NEURON API methods
that can be used in MOD files are implicitly included via the mech_api.h
header, so this explicit declaration of a zero-parameter overload is not needed
and can safely be removed.
As noted above (:ref:`function-decls-with-incorrect-types`), |neuron_with_cpp_mechanisms| provides extra overloads for some API methods that aim to smooth the transition from C to C++. These overloads are provided for widely used methods, and where overloading on return type would not be required.
An example is the vector_capacity
function, which in
|neuron_with_cpp_mechanisms| has two overloads
int vector_capacity(IvocVect*);
[[deprecated("non-void* overloads are preferred")]] int vector_capacity(void*);
The second one simply casts its argument to IvocVect*
and calls the first
one.
The [[deprecated]]
attribute means that MOD files that use the second
overload emit compilation warnings when they are compiled using nrnivmodl
.
If your MOD files produce these deprecation warnings, make sure that the
relevant method (vector_capacity
in this example) is being called with an
argument of the correct type (IvocVect*
), and not a type that is implicitly
converted to void*
.
Various changes have also been done in the API of NEURON functions related to random number generators.
First, in |neuron_with_cpp_mechanisms| parameters passed to the functions need to be
of the correct type as it was already mentioned in :ref:`function-decls-with-incorrect-types`.
The most usual consequence of that is that NEURON random API functions that were taking as
an argument a void*
now need to called with a Rand*
. An example of the changes needed
to fix this issue is given in 182129.
Another related change is with scop_rand()
function that is usually used for defining a
URAND
FUNCTION
in mod files to return a number based on a uniform distribution from 0 to 1.
This function now takes no argument anymore. An example of this change can also be found in
182129.
Finally, the preferred random number generator is Random123
. You can find more information
about that in :meth:`Random.Random123` and :ref:`Randomness in NEURON models`. An example of the
usage of Random123
can be seen in netstim.mod
and its corresponding test.`
Another important aspect of Random123
is that it's supported in CoreNEURON as well. For more
information about this see :ref:`Random Number Generators: Random123 vs MCellRan4`.