从 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 程序中完成此操作。

你想进一步了解什么?

另请参阅

在 Visual Studio 中创建 C/C++ DLL