Files
epics-base/modules/database/test/std/rec/epicsExportTest.c

147 lines
3.2 KiB
C

/*************************************************************************\
* Copyright (c) 2025 Dirk Zimoch
* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* Compile and link test for epicsExport.h
*
* Test if macros eppicsExportAddr, epicsExportRegistrar and epicsRegisterFunction
* expand to valid C and C++ code, in the latter case regardless if
* wrapped with extern "C" {} or not.
* Also test that those macros have the intended effect in both cases.
*
* This file is compiled directly as C
* and included from epicsExportTestxx.cpp as C++
*/
#include <epicsUnitTest.h>
#include <dbUnitTest.h>
#include <testMain.h>
#include <dbAccess.h>
#include <longinRecord.h>
#include <aSubRecord.h>
#include <iocsh.h>
#include <registryFunction.h>
#include <epicsExport.h>
int i1, i2;
volatile int v1=10, v2=20;
const int c1=100, c2=200;
static long myReadLongin(struct dbCommon* prec)
{
struct longinRecord* pli =
#ifdef __cplusplus
reinterpret_cast<struct longinRecord*>(prec);
#else
(struct longinRecord*)prec;
#endif
pli->val=5;
return 0;
}
/* Also test cast from user-specific const mydset to dset */
const struct mydset {
long number;
long (*report)(int);
long (*init)(int);
long (*init_record)(struct dbCommon*);
long (*get_ioint_info)(int, struct dbCommon*, IOSCANPVT*);
long (*process)(struct dbCommon*);
long (*something_else)(struct dbCommon*);
} dset1 = {
6,
NULL,
NULL,
NULL,
NULL,
myReadLongin,
NULL
}, dset2 = {
6,
NULL,
NULL,
NULL,
NULL,
myReadLongin,
NULL
};
static void registrar1() {
i1++;
testPass("registrar1 executed");
}
static void registrar2() {
i2++;
testPass("registrar2 executed");
}
/* Also test cast from int(*)() to REGISTRAR */
static int registrar3() {
i1++;
testPass("registrar3 executed");
return 0;
}
static int registrar4() {
i2++;
testPass("registrar4 executed");
return 0;
}
/* Test both, native (potentially C++) and extern "C" functions */
static long aSubInit1(aSubRecord* prec) {
*(epicsInt32*)prec->a = 1;
return 0;
}
static long aSubProc1(aSubRecord* prec) {
*(epicsInt32*)prec->b = 2;
return 0;
}
#ifdef __cplusplus
extern "C" {
#endif
static long aSubInit2(aSubRecord* prec) {
*(epicsInt32*)prec->a = 3;
return 0;
}
static long aSubProc2(aSubRecord* prec) {
*(epicsInt32*)prec->b = 4;
return 0;
}
#ifdef __cplusplus
}
#endif
/* Test without wrapping */
epicsExportAddress(int, i1);
epicsExportAddress(int, v1);
epicsExportAddress(int, c1);
epicsExportAddress(dset, dset1);
epicsExportRegistrar(registrar1);
epicsExportRegistrar(registrar3);
epicsRegisterFunction(aSubInit1);
epicsRegisterFunction(aSubProc1);
/* In C++ test wrapped in extern "C" {} */
#ifdef __cplusplus
extern "C" {
#endif
epicsExportAddress(int, i2);
epicsExportAddress(int, v2);
epicsExportAddress(int, c2);
epicsExportAddress(dset, dset2);
epicsExportRegistrar(registrar2);
epicsExportRegistrar(registrar4);
epicsRegisterFunction(aSubInit2);
epicsRegisterFunction(aSubProc2);
#ifdef __cplusplus
}
#endif