c-如何在动态链接库中调用全局变量



我有3.c源文件:common.c、interface_1.c、interface=2.c.

在common.c中,我定义了一些函数和全局变量,在interface_1.c和interface_2.c中,这些函数和全局变数将被调用。

现在,interface_1.c和interface_2.c将被编译为.dll,以便其他程序使用。问题是,当调用两个dll文件时,公共.c中定义的全局变量应该是相同的,这意味着:如果在调用interface_1.dll的过程中更改了全局变量,那么interface_2.dll中的相同变量应该同时更改。

背景我想使用PLECS进行电力电子仿真。有一个名为DLL的块非常强大。用户可以编写c/cpp代码并将其编译为动态链接库。每个DLL块只能调用一个.DLL文件。我有两个DLL块,想制作一个全局变量在它们之间进行通信。将编译为dll的c源文件的模板如下所示。

DllHeader.h

#ifndef PLECSDLLHEADER_H_
#define PLECSDLLHEADER_H_
#if defined _WIN32
#define DLLEXPORT __declspec(dllexport)
#elif __GNUC__ >=4
#define DLLEXPORT __attribute__ ((visibility("default")))
#else
#define DLLEXPORT
#endif
#ifdef __cplusplus
extern "C" {
#endif
#pragma pack(push, 4)
struct SimulationSizes {
int numInputs;      /* the number of inputs that the DLL needs           */
int numOutputs;     /* the number of outputs that the DLL provides       */
int numStates;      /* the number of discrete states that the DLL needs  */
int numParameters;  /* the number of user parameters that the DLL needs  */
};
struct SimulationState {
const double* const inputs;     /* array of input values (read-only)      */
double* const outputs;          /* array of output values (to fill by DLL) */
double* const states;           /* array of discrete states (read/write)  */
const double* const parameters; /* array of parameters (read-only)        */
const double time;              /* current simulation time (read-only)    */
const char* errorMessage;       /* error message to set by DLL            */
void* userData;                 /* pointer to any DLL data (untouched by PLECS) */
};
#pragma pack(pop)
/* Required: DLL needs to set all fields in aSizes.                          */
/* Called once before the simulation.                                        */
DLLEXPORT void plecsSetSizes(struct SimulationSizes* aSizes);
/* Optional: DLL may acquire resources, initialize states and outputs.       */
/* Called once during the initialization of a new simulation.                */
DLLEXPORT void plecsStart(struct SimulationState* aState);
/* Required: DLL needs to set outputs depending on inputs and states.        */
/* Called whenever the simulation time reaches a multiple of the sample      */
/* time.                                                                     */
DLLEXPORT void plecsOutput(struct SimulationState* aState);
/* Optional: DLL may release any acquired resources.                         */
/* Called when the simulation is finished, even when an error occured.       */
DLLEXPORT void plecsTerminate(struct SimulationState* aState);
#ifdef __cplusplus
}
#endif
#endif /* PLECSDLLHEADER_H_ */

接口.c

#include "DllHeader.h"
//Map input and output parameters to meaningful names
#define in aState->inputs[0]
#define out aState->outputs[0]

DLLEXPORT void plecsSetSizes(struct SimulationSizes* aSizes)
{
aSizes->numInputs = 1;
aSizes->numOutputs = 1;
aSizes->numStates = 0;
aSizes->numParameters = 0; //number of user parameters passed in
}
//This function is automatically called at the beginning of the simulation
DLLEXPORT void plecsStart(struct SimulationState* aState)
{
// do some initialization ...
}

//This function is automatically called every sample time
//output is written to DLL output port after the output delay
DLLEXPORT void plecsOutput(struct SimulationState* aState)
{
// do some calculation ...
}

使用LoadLibrary有效。请注意,在interface.c中应指定common.dll的完整路径!解决方案显示在最后。

对于Lundin来说,它涉及嵌入式开发,一些变量是基于时间的,这意味着它们一直是活动的,并由其他控制函数调用。例如,一个信号被采样并传递给一个变量,这个采样的数据将被用于几个地方,例如滤波器、闭环控制。。。因此,很难将这些混乱的用法解耦。。。

common.h

#ifndef COMMON_H_
#define COMMON_H_
#if defined _WIN32
#define DLLEXPORT __declspec(dllexport)
#elif __GNUC__ >=4
#define DLLEXPORT __attribute__ ((visibility("default")))
#else
#define DLLEXPORT
#endif
#ifdef __cplusplus
extern "C" {
#endif
#pragma pack(push, 4)
typedef struct{
float a;
float b;
} Coord;
#pragma pack(pop)
extern Coord curPos;
DLLEXPORT Coord GetcurPos(void);
DLLEXPORT float getMax(float a, float b);
DLLEXPORT void SetcurPos(float a, float b);
#ifdef __cplusplus
}
#endif
#endif /* COMMON_H_ */

common.c

#include "common.h"
Coord curPos;

DLLEXPORT float getMax(float a, float b){
return a>b?a:b;
}
DLLEXPORT Coord GetcurPos(void){
return curPos;
}
DLLEXPORT void SetcurPos(float a, float b){
curPos.a=a;
curPos.b=b;
}

接口a.c

#include "DllHeader.h"
#include <windows.h>
#include "common.h"

//Map input and output parameters to meaningful names
#define in aState->inputs[0]
#define out aState->outputs[0]

HMODULE module;
typedef float(*AddFunc)(float, float);
typedef Coord (*PosGetter)(void);
AddFunc dllmax;
PosGetter getCurPos;
DLLEXPORT void plecsSetSizes(struct SimulationSizes* aSizes)
{
aSizes->numInputs = 1;
aSizes->numOutputs = 1;
aSizes->numStates = 0;
aSizes->numParameters = 0; //number of user parameters passed in
}
DLLEXPORT void plecsStart(struct SimulationState* aState)
{
module = LoadLibrary(TEXT("D:\Simulation\PLECSLearn\DLL\global_test\common.dll"));
if (module == NULL)
{
aState->errorMessage = "Failed to load common.dll";
}
dllmax = (AddFunc)GetProcAddress(module, "getMax");
getCurPos = (PosGetter)GetProcAddress(module, "GetcurPos");
}

//This function is automatically called every sample time
//output is written to DLL output port after the output delay
DLLEXPORT void plecsOutput(struct SimulationState* aState)
{
if (getCurPos().a == 1){
out = 2;
} else {
out = -1;
}
// out = dllmax(200,300);
}

接口b.c

#include "DllHeader.h"
#include <windows.h>
#include "common.h"
//Map input and output parameters to meaningful names
#define in aState->inputs[0]
#define out aState->outputs[0]
HMODULE module;
typedef float(*AddFunc)(float, float);
typedef Coord (*PosGetter)(void);
typedef void (*PosSetter)(float, float);
AddFunc dllmax;
PosGetter getCurPos;
PosSetter setCurPos;
DLLEXPORT void plecsSetSizes(struct SimulationSizes* aSizes)
{
aSizes->numInputs = 1;
aSizes->numOutputs = 1;
aSizes->numStates = 0;
aSizes->numParameters = 0; //number of user parameters passed in
}
DLLEXPORT void plecsStart(struct SimulationState* aState)
{
module = LoadLibrary(TEXT("D:\Simulation\PLECSLearn\DLL\global_test\common.dll"));
if (module == NULL)
{
aState->errorMessage = "Failed to load common.dll";
}
dllmax = (AddFunc)GetProcAddress(module, "getMax");
getCurPos = (PosGetter)GetProcAddress(module, "GetcurPos");
setCurPos = (PosSetter)GetProcAddress(module, "SetcurPos");
}

//This function is automatically called every sample time
//output is written to DLL output port after the output delay
DLLEXPORT void plecsOutput(struct SimulationState* aState)
{
static int cnt = 0;
if (cnt<5000){
setCurPos(0,0);
}else{
setCurPos(1,2);
}
cnt++;
out = getCurPos().a;
}

最新更新