首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在动态链接库中调用全局变量?

如何在动态链接库中调用全局变量?
EN

Stack Overflow用户
提问于 2020-09-17 08:05:24
回答 1查看 124关注 0票数 0

我有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文件,但common.c中定义的全局变量应该是相同的,这意味着:如果在调用interface_1.dll过程中更改了全局变量,则应该同时更改interface_2.dll中的相同变量。

背景我想用PLECS做电力电子仿真。有一个叫做DLL的块,它非常强大。用户可以编写c/cpp代码,并将它们编译成动态链接库。每个DLL块只能调用一个.dll文件。我有两个DLL块,并希望创建一个全局变量来在它们之间进行通信。下面显示了编译成dll的c源文件的模板。

DllHeader.h

代码语言:javascript
运行
复制
#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_ */

interface.c

代码语言:javascript
运行
复制
#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 ...
}
EN

回答 1

Stack Overflow用户

发布于 2020-09-17 12:36:31

使用LoadLibrary是可行的。请注意在interface.c中应该指定common.dll的完整路径!最后给出了解决方案。

对于Lundin来说,它涉及到嵌入式开发,一些变量是基于时间的,这意味着它们始终存在,并由其他控制函数调用。例如,一个信号被采样并传递给一个变量,这个采样数据将被用于几个地方,例如滤波器,闭环控制.所以很难把这些凌乱的用法.

common.h

代码语言:javascript
运行
复制
#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

代码语言:javascript
运行
复制
#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;
}

interface_a.c

代码语言:javascript
运行
复制
#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);
}

interface_b.c

代码语言:javascript
运行
复制
#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;
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63933786

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档