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

时间:2013-03-11 15:15:26

标签: c dll struct dllimport dllexport

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

#ifdef FOODLL_EXPORTS
    #define FOO_API __declspec( dllexport )
#else
    #define FOO_API __declspec( dllimport )

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

typedef struct FooParams
{
    char *a;
    char *b;
    void *whatever; //some other type
} FooParams;

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

1 个答案:

答案 0 :(得分:10)

如果客户端对FooParams的唯一用途是获取DLL函数返回的指针并将这些指针传递给其他DLL函数,则可以将其设置为“opaque类型”:Put < / p>

typedef struct FooParams FooParams;
fooExports.h中的

FOO_API宏不属于该声明。 opaque类型意味着客户端代码不能:

  • 创建FooParams类型的所有变量(但FooParams * ptr = NULL;可以)。
  • FooParams的任何成员做任何事情。
  • 查找sizeof(FooParams) - 因此无法正确malloc一个或多个FooParams个对象的空间。

您也不能#define客户端看到上述任何一个的宏。所以你的DLL需要有一个或多个“构造函数”或“工厂”函数,可能类似

FOO_API FooParams* CreateFooParams(const char * input);

定义匹配的“析构函数”函数(如

)也是一种好习惯
FOO_API void DestroyFooParams(FooParams * p);

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

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