C++ DLL导出函数能否使用类作为参数与返回值?为何报错
问题原因
报错和函数参数/返回值使用自定义类没有直接关系,是两处语法错误导致的:
- 头文件开头的类前置声明写法不符合C标准。你写的
class gfx::BaseObject;、class gfx::MeshObject;是非法写法,C不允许在全局作用域直接通过命名空间::类名的形式前置声明命名空间内的类,这种写法会让编译器无法正确匹配类型,把你声明的类和真正定义在gfx命名空间内的类识别为两个完全不同的类型。 - 错误的类型匹配进一步触发了后续两个编译错误:
- 处理
EnqueueObject声明时,编译器认为你先声明了一个extern "C"链接、参数为错误前置类型的函数,又在cpp文件里定义了一个默认C++链接、参数为正确gfx::BaseObject*类型的同名函数,两者链接规范不兼容,触发第一个报错。 - 处理
CreateMeshObject声明时,编译器无法正确识别返回值类型gfx::MeshObject*,默认将其判定为int返回值,后续cpp文件中定义的同名函数返回值为gfx::MeshObject*,C++不允许仅通过返回值区分函数重载,触发第二个报错。
- 处理
之前的InitGraphics、ReleaseGraphics能正常编译,是因为这两个函数的参数都是Windows原生定义的UINT、HWND类型,不依赖你错误前置声明的自定义类,不会触发类型匹配问题。
修复方案
- 修正前置声明的写法,将命名空间内类的前置声明放在对应命名空间块内部:
// 正确的前置声明格式 namespace gfx { class BaseObject; class MeshObject; } - 补充必要的头文件依赖(你用了
UINT、HWND类型,需要包含<windows.h>)。 - 修正后完整的头文件代码如下:
// RendererDLL.h #pragma once #include <windows.h> namespace gfx { class BaseObject; class MeshObject; } namespace gfx { extern "C" { void __declspec(dllexport) InitGraphics(UINT width, UINT height, HWND hwnd); void __declspec(dllexport) ReleaseGraphics(); void __declspec(dllexport) EnqueueObject(gfx::BaseObject* pBaseObj); gfx::MeshObject* __declspec(dllexport) CreateMeshObject(); } }
补充说明
extern "C" 仅会修改函数的符号名修饰规则、使用C调用约定,不会禁止函数使用C++自定义类型作为参数或返回值:
- 如果导出的DLL需要给纯C代码调用,那么确实不能在
extern "C"函数的参数、返回值中使用C类类型,C语言无法识别C类的内存布局。 - 如果加
extern "C"只是为了去掉C名字修饰,方便通过GetProcAddress这类API按固定函数名查找导出函数,只要调用方也是C代码、且双方使用的类定义内存布局完全一致,使用自定义类作为参数/返回值是完全合法的。
内容的提问来源于stack exchange,提问作者Beomseo Choi
相关产品推荐
相关产品推荐

