8

这是我第一次处理 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 以及使用它的客户端应用程序。

4

1 回答 1

11

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

typedef struct FooParams FooParams;

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

  • 创建任何类型的变量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 代码都使用malloc和的相同定义free)。

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

于 2013-03-11T19:55:06.730 回答