如何使用__declspec(dllexport/import)从DLL /导出/导入C结构到控制台应用程序

wot*_*n07 7 c dll struct dllimport dllexport

这是我第一次处理DLL.在MSDN文档之后,我创建了一个头文件fooExports.h,其中宏根据预处理器定义定义:

#ifdef FOODLL_EXPORTS
    #define FOO_API __declspec( dllexport )
#else
    #define FOO_API __declspec( dllimport )
Run Code Online (Sandbox Code Playgroud)

我的目的是在我的DLL实现以及控制台应用程序中使用此标头.到目前为止,导入和导出功能工作正常.当我尝试导出一个已经定义的结构作为其中一个导出函数的参数时,问题就出现了.例如,在前面提到的头文件中,我声明FOO_API void foo( FooParams *args )并且args是一个如下定义的结构:

typedef struct FooParams
{
    char *a;
    char *b;
    void *whatever; //some other type
} FooParams;
Run Code Online (Sandbox Code Playgroud)

此结构必须在foo.h中定义,而不是在fooExports.h定义.是否有任何方法可以导出此结构而不将其从原始头文件中删除(考虑到我希望将导出/导入集中在fooExports.h中).这样做会有什么更好的方法?DLL都是C以及使用它的客户端应用程序.

asc*_*ler 11

如果客户端将使用的唯一用途FooParams是获取从DLL函数返回的指针并将这些指针传递给其他DLL函数,则可以使其成为"不透明类型":Put

typedef struct FooParams FooParams;
Run Code Online (Sandbox Code Playgroud)

在fooExports.h中.该FOO_API宏不属于该声明.opaque类型意味着客户端代码不能:

  • 创建任何类型的变量FooParams(但FooParams * ptr = NULL;没关系).
  • 对任何成员做任何事情FooParams.
  • 查找sizeof(FooParams)- 因此无法正确地malloc为一个或多个FooParams对象留出空间.

您也不能#define对执行上述任何操作的客户端显示宏.所以你的DLL需要有一个或多个"构造函数"或"工厂"函数,可能就像

FOO_API FooParams* CreateFooParams(const char * input);
Run Code Online (Sandbox Code Playgroud)

定义匹配的"析构函数"函数也是一种很好的做法

FOO_API void DestroyFooParams(FooParams * p);
Run Code Online (Sandbox Code Playgroud)

即使定义很简单{ free(p); },因为如果在DLL内部分配的内存被其外部的代码释放,反之亦然(因为并非所有Windows代码都使用相同的malloc和的定义),有时会出现问题free.

如果这一切都太极端,唯一的选择就是把或#includestruct在导出的头文件中定义,并使其客户端可见.如果没有这个,FooParams除了传递指针之外,任何对a做某事的尝试都是不可能的,因为编译器不会知道它中的内容FooParams.编译器(与链接器相对)仅从命令行参数和#include-d文件获取信息,而不是从库或DLL获取信息.