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

标签 c dll struct dllimport dllexport

这是我第一次处理 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 代码都使用相同的 mallocfree 定义,有时会出现问题)。

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

关于c - 如何使用 __declspec( dllexport/import ) 从 DLL 导出/导入 C 结构/到控制台应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15342138/

相关文章:

c - Realloc 一直失败(在 C 中)

c++ - 在不加载 DLL 的情况下使用函数?

c - 结构标签和花括号后面的标签有什么区别?

c - 结构体和结构体指针之间的区别

json - 如何在 Golang 结构中使用 omitempty 标志更新 Mongodb 字段

c - malloc 实际分配了多少内存,并且可以将变量存储在分配有 malloc 的数组中以节省内存?

c - 为什么未定义大小的数组只允许在 main() 中使用?

c# - 在 C# 中将多个类绑定(bind)到一个 .dll 文件中

asp.net - 更新 ASP.NET Web 应用程序 DLL 的最佳方法是什么?

在linux中创建名称管道并在c-app和dlang之间交换结构数据