这是我第一次处理 DLL。根据 MSDN 文档,我创建了一个头文件 fooExports.h,其中包含根据预处理器定义定义的宏:
#ifdef FOODLL_EXPORTS
#define FOO_API __declspec( dllexport )
#else
#define FOO_API __declspec( dllimport )
我的意图是在我的 DLL 实现和控制台应用程序中都使用这个 header 。到目前为止,导入和导出功能工作得很好。当我尝试导出一个我需要的已定义结构作为其中一个导出函数的参数时,问题就出现了。例如,在上述头文件中,我声明了 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 语言。
最佳答案
如果客户端对 FooParams
的唯一用途是获取从 DLL 函数返回的指向它的指针并将这些指针传递给其他 DLL 函数,您可以将其设为“不透明类型” : 放
typedef struct FooParams FooParams;
在 fooExports.h 中。 FOO_API
宏不属于该声明。不透明类型意味着客户端代码不能:
- 创建
FooParams
类型的任何变量(但FooParams * ptr = NULL;
没问题)。 - 对
FooParams
的任何成员做任何事情。 - 找到
sizeof(FooParams)
- 因此无法为一个或多个FooParams
对象正确地malloc
空间。
您也不能使用#define
宏来对执行上述任何操作的客户端可见。因此,您的 DLL 需要具有一个或多个“构造函数”或“工厂”函数,可能类似于
FOO_API FooParams* CreateFooParams(const char * input);
定义匹配的“析构函数”函数也是一种很好的做法,例如
FOO_API void DestroyFooParams(FooParams * p);
即使定义就像{ free(p); }
,因为如果在 DLL 内部分配的内存被 DLL 外部的代码释放,反之亦然(因为并非所有 Windows 代码都使用相同的 malloc
和 free 定义,有时会出现问题
)。
如果这一切都过于极端,唯一的其他选择是将 #include
struct
定义放在导出的头文件中,并使其对客户端可见。否则,除了传递指针外,任何对 FooParams
做某事的尝试都将是不可能的,因为编译器不知道 FooParams
中有什么。编译器(与链接器相反)仅从命令行参数和 #include
-d 文件中获取信息,而不是从库或 DLL 中获取信息。
关于c - 如何使用 __declspec( dllexport/import ) 从 DLL 导出/导入 C 结构/到控制台应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15342138/