|
| 1 | +// NOTE: this assumes neuronapi.h is on your CPLUS_INCLUDE_PATH |
| 2 | +// Exercises nrn_symbol_dataptr on a NOTUSER runtime scalar (created by HOC |
| 3 | +// `x = 42`). Its value is stored in the top-level object-data array, not at |
| 4 | +// sym->u.pval, so before the fix the returned pointer was an offset cast to a |
| 5 | +// pointer and dereferencing it was undefined. The pointer must now alias the |
| 6 | +// same storage HOC reads and writes. |
| 7 | +#include <cmath> |
| 8 | +#include <iostream> |
| 9 | +#include "neuronapi.h" |
| 10 | + |
| 11 | +using std::cerr; |
| 12 | +using std::endl; |
| 13 | + |
| 14 | +extern "C" void modl_reg(){/* No modl_reg */}; |
| 15 | + |
| 16 | +static bool check(bool cond, const char* msg) { |
| 17 | + if (!cond) { |
| 18 | + cerr << "FAIL: " << msg << endl; |
| 19 | + } |
| 20 | + return cond; |
| 21 | +} |
| 22 | + |
| 23 | +static bool eq(double got, double want, const char* msg) { |
| 24 | + if (std::fabs(got - want) > 1e-12) { |
| 25 | + cerr << "FAIL: " << msg << " — got " << got << ", want " << want << endl; |
| 26 | + return false; |
| 27 | + } |
| 28 | + return true; |
| 29 | +} |
| 30 | + |
| 31 | +int main(void) { |
| 32 | + static const char* argv[] = {"global_scalar", "-nogui", "-nopython", nullptr}; |
| 33 | + nrn_init(3, argv); |
| 34 | + |
| 35 | + bool ok = true; |
| 36 | + |
| 37 | + // NOTUSER: a runtime scalar. Its data lives in the top-level object-data |
| 38 | + // array, not at sym->u.pval -- this is the case the fix addresses. |
| 39 | + nrn_hoc_call("myvar = 42"); |
| 40 | + double* p = nrn_symbol_dataptr(nrn_symbol("myvar")); |
| 41 | + ok &= check(p != nullptr, "NOTUSER dataptr is non-null"); |
| 42 | + ok &= eq(*p, 42.0, "NOTUSER dataptr dereferences to 42"); |
| 43 | + |
| 44 | + // The pointer must alias the storage HOC uses: write through it, then have |
| 45 | + // HOC copy myvar into the built-in hoc_ac_ and confirm HOC saw the change. |
| 46 | + *p = 3.5; |
| 47 | + nrn_hoc_call("hoc_ac_ = myvar"); |
| 48 | + double* ac = nrn_symbol_dataptr(nrn_symbol("hoc_ac_")); |
| 49 | + ok &= eq(*ac, 3.5, "HOC reads the value written through the NOTUSER dataptr"); |
| 50 | + |
| 51 | + // USERDOUBLE built-in (t): dataptr already worked; make sure it still does. |
| 52 | + double* t = nrn_symbol_dataptr(nrn_symbol("t")); |
| 53 | + *t = 12.0; |
| 54 | + nrn_hoc_call("hoc_ac_ = t"); |
| 55 | + ok &= eq(*ac, 12.0, "USERDOUBLE dataptr round-trips through HOC"); |
| 56 | + |
| 57 | + return ok ? 0 : 1; |
| 58 | +} |
0 commit comments