From acf4c92697378591e290326f88e4564a92b0ef6e Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Wed, 12 Mar 2025 11:59:49 +0100 Subject: [PATCH] fix epicsExport for volatile and const variables --- documentation/RELEASE_NOTES.md | 2 +- modules/database/test/std/rec/Makefile | 1 + .../database/test/std/rec/epicsExportTest.c | 10 ++++- .../database/test/std/rec/epicsExportTest.dbd | 4 ++ .../test/std/rec/epicsExportTestMain.c | 44 +++++++++++++------ modules/libcom/src/misc/epicsExport.h | 10 ++--- 6 files changed, 50 insertions(+), 21 deletions(-) diff --git a/documentation/RELEASE_NOTES.md b/documentation/RELEASE_NOTES.md index 8e934cf8c..f1953168f 100644 --- a/documentation/RELEASE_NOTES.md +++ b/documentation/RELEASE_NOTES.md @@ -22,7 +22,7 @@ __Add new items below here__ ### epicsExport simplifications `epicsExportAddress()`, `epicsExportRegistrar()` and `epicsRegisterFunction()` -no loger require to be wrapped in `extern "C" { }` in C++ code. +no longer require to be wrapped in `extern "C" { }` in C++ code. ### Build system `$(PYTHON)` default changed diff --git a/modules/database/test/std/rec/Makefile b/modules/database/test/std/rec/Makefile index c49050c49..4cc1b8886 100644 --- a/modules/database/test/std/rec/Makefile +++ b/modules/database/test/std/rec/Makefile @@ -231,6 +231,7 @@ TARGETS += $(COMMON_DIR)/epicsExportTestIoc.dbd DBDDEPENDS_FILES += epicsExportTestIoc.dbd$(DEP) epicsExportTestIoc_DBD += base.dbd epicsExportTestIoc_DBD += epicsExportTest.dbd +TESTFILES += $(COMMON_DIR)/epicsExportTestIoc.dbd ../epicsExportTest.db TESTLIBRARY += epicsExportTestLib epicsExportTestLib_SRCS += epicsExportTest.c epicsExportTestLib_LIBS += dbCore Com diff --git a/modules/database/test/std/rec/epicsExportTest.c b/modules/database/test/std/rec/epicsExportTest.c index 0dda3c0b4..aaa3f2215 100644 --- a/modules/database/test/std/rec/epicsExportTest.c +++ b/modules/database/test/std/rec/epicsExportTest.c @@ -27,6 +27,8 @@ #include int i1, i2; +volatile int v1=10, v2=20; +const int c1=100, c2=200; static long myReadLongin(struct dbCommon* prec) { @@ -40,8 +42,8 @@ static long myReadLongin(struct dbCommon* prec) return 0; } -/* Also test cast from user-specific mydset to dset */ -struct mydset { +/* Also test cast from user-specific const mydset to dset */ +const struct mydset { long number; long (*report)(int); long (*init)(int); @@ -118,6 +120,8 @@ static long aSubProc2(aSubRecord* prec) { /* Test without wrapping */ epicsExportAddress(int, i1); +epicsExportAddress(int, v1); +epicsExportAddress(int, c1); epicsExportAddress(dset, dset1); epicsExportRegistrar(registrar1); epicsExportRegistrar(registrar3); @@ -129,6 +133,8 @@ epicsRegisterFunction(aSubProc1); extern "C" { #endif epicsExportAddress(int, i2); +epicsExportAddress(int, v2); +epicsExportAddress(int, c2); epicsExportAddress(dset, dset2); epicsExportRegistrar(registrar2); epicsExportRegistrar(registrar4); diff --git a/modules/database/test/std/rec/epicsExportTest.dbd b/modules/database/test/std/rec/epicsExportTest.dbd index 6f547c5e4..fc9ee2f6d 100644 --- a/modules/database/test/std/rec/epicsExportTest.dbd +++ b/modules/database/test/std/rec/epicsExportTest.dbd @@ -1,5 +1,9 @@ variable(i1,int) variable(i2,int) +variable(v1,int) +variable(v2,int) +variable(c1,int) +variable(c2,int) device(longin, CONSTANT, dset1, "dset1") device(longin, CONSTANT, dset2, "dset2") registrar(registrar1) diff --git a/modules/database/test/std/rec/epicsExportTestMain.c b/modules/database/test/std/rec/epicsExportTestMain.c index 32b22cb40..060ab3733 100644 --- a/modules/database/test/std/rec/epicsExportTestMain.c +++ b/modules/database/test/std/rec/epicsExportTestMain.c @@ -18,11 +18,30 @@ void epicsExportTestIoc_registerRecordDeviceDriver(struct dbBase *); +static int* testVarEquals(const char* name, int expected) +{ + const iocshVarDef *var; + int *p; + + var = iocshFindVariable(name); + if (!var) { + testFail("Cannot access variable %s", name); + return NULL; + } + if (var->type != iocshArgInt) { + testFail("Variable %s has wrong type", name); + return NULL; + } + p = (int*)(var->pval); + testOk(*p == expected, "Variable %s == %d", name, expected); + return p; +} + MAIN(epicsExportTest) { - const iocshVarDef *var_i1, *var_i2; + int *p1, *p2; - testPlan(26); + testPlan(30); testdbPrepare(); testdbReadDatabase("epicsExportTestIoc.dbd", 0, 0); epicsExportTestIoc_registerRecordDeviceDriver(pdbbase); @@ -52,22 +71,21 @@ MAIN(epicsExportTest) testdbGetFieldEqual("asub2.B", DBF_LONG, 4); testDiag("Testing if variable access works"); - var_i1 = iocshFindVariable("i1"); - var_i2 = iocshFindVariable("i2"); - if (var_i1 && var_i2 && var_i1->type == iocshArgInt && var_i2->type == iocshArgInt) { - int *pi1 = (int*)(var_i1->pval); - int *pi2 = (int*)(var_i2->pval); + p1 = testVarEquals("i1", 2); + p2 = testVarEquals("i2", 2); + testVarEquals("v1", 10); + testVarEquals("v2", 20); + testVarEquals("c1", 100); + testVarEquals("c2", 200); - testOk(*pi1==2, "Variable i1 counted registrars: %d == 2", *pi1); - testOk(*pi2==2, "Variable i2 counted registrars: %d == 2", *pi2); + if (p1 && p2) { testDiag("Testing if variables are accessible from iocsh"); testOk(iocshCmd("var i1,4") == 0, "Setting i1 = 4 in iocsh"); testOk(iocshCmd("var i2,5") == 0, "Setting i2 = 5 in iocsh"); - testOk(*pi1==4, "Variable i1: %d == 4", *pi1); - testOk(*pi2==5, "Variable i2: %d == 5", *pi2); - } else { - testFail("Cannot access variables i1, i2"); + testOk(*p1==4, "Variable i1 == 4"); + testOk(*p2==5, "Variable i2 == 5"); } + testIocShutdownOk(); testdbCleanup(); return testDone(); diff --git a/modules/libcom/src/misc/epicsExport.h b/modules/libcom/src/misc/epicsExport.h index c3aba1376..356d62b39 100644 --- a/modules/libcom/src/misc/epicsExport.h +++ b/modules/libcom/src/misc/epicsExport.h @@ -41,6 +41,10 @@ extern "C" { typedef void (*REGISTRAR)(void); +#ifdef __cplusplus +} +#endif + #define EPICS_EXPORT_POBJ(typ, obj) pvar_ ## typ ## _ ## obj #define EPICS_EXPORT_PFUNC(fun) EPICS_EXPORT_POBJ(func, fun) @@ -79,7 +83,7 @@ typedef void (*REGISTRAR)(void); #ifdef __cplusplus #define epicsExportAddress(typ, obj) \ extern "C" { epicsShareExtern typ *EPICS_EXPORT_POBJ(typ,obj); } \ - epicsShareDef typ *EPICS_EXPORT_POBJ(typ, obj) = reinterpret_cast(&obj) + epicsShareDef typ *EPICS_EXPORT_POBJ(typ, obj) = (typ *) (char *) &obj #else #define epicsExportAddress(typ, obj) \ epicsShareExtern typ *EPICS_EXPORT_POBJ(typ,obj); \ @@ -136,8 +140,4 @@ typedef void (*REGISTRAR)(void); epicsExportRegistrar(register_func_ ## fun) #endif -#ifdef __cplusplus -} -#endif - #endif /* INC_epicsExport_H */