从 Visual Basic 应用程序调用 DLL 函数

更新:2007 年 11 月

为使 Visual Basic 应用程序(或使用 Pascal 或 Fortran 等其他语言的应用程序)可以调用 C/C++ DLL 中的函数,必须使用正确的调用约定导出函数,但不要让编译器进行任何名称修饰。

__stdcall 为函数创建正确的调用约定(被调用函数清理堆栈,而参数从右向左传递),但以不同的方式修饰函数名。因此,当在 DLL 中的导出函数上使用 __declspec(dllexport) 时,修饰名被导出。

__stdcall 名称修饰用下划线 (_) 作为符号名的前缀,并在符号的后面追加一个 @ 符,@ 符后是参数列表中的字节数(所需的堆栈空间)。因此,函数声明为:

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 文件中使用别名。在 Visual Basic 程序中,这可以通过将别名子句添加到 Declare 语句来完成。

您想进一步了解什么?

请参见

概念

DLL