从 Visual Basic 应用程序调用 DLL 函数
若要使 Visual Basic 应用程序(或诸如 Pascal 或 Fortran 等其他语言编写的应用程序)调用 C/C++ DLL 中的函数,必须使用正确的调用约定导出函数,而无需编译器进行任何名称修饰
__stdcall
为函数创建正确的调用约定(被调用的函数会清理堆栈,且参数从右向左传递),但以不同方式修饰函数名称。 因此,当对 DLL 中的已导出函数使用 __declspec(dllexport)
时,导出修饰名。
__stdcall
名称修饰使用下划线字符 () 作为符号名称的前缀,并向符号追加 at 符号 (@),后跟参数列表中的字节数(所需堆栈空间)。 因此,在声明为以下内容时:
int __stdcall func (int a, double b)
函数在输出中修饰为 _func@12
。
C 调用约定 (__cdecl
) 将名称修饰为 _func
。
若要获取修饰名,请使用 /MAP。 使用 __declspec(dllexport)
可以执行以下操作:
如果函数是使用 C 调用约定 (
__cdecl
) 导出的,则它会在导出名称时去掉前导下划线字符 ()。如果导出的函数不使用 C 调用约定(例如
__stdcall
),则它会导出修饰名。
因为无法替代发生堆栈清理的位置,所以必须使用 __stdcall
。 若要使用 __stdcall
取消修饰名称,必须通过在 .def 文件的 EXPORTS 部分中使用别名来指定它们。 对于以下函数声明,这会显示如下:
int __stdcall MyFunc (int a, double b);
void __stdcall InitCode (void);
在 .DEF 文件中:
EXPORTS
MYFUNC=_MyFunc@12
INITCODE=_InitCode@0
若要使 Visual Basic 编写的程序可调用 DLL,.def 文件中需要本主题中所示的别名技术。 如果别名在 Visual Basic 程序中完成,则不需要在 .def 文件中使用别名。 可以通过将别名子句添加到 Declare 语句,在 Visual Basic 程序中完成此操作。