我正在尝试编写一个可以从Excel VBA调用的DLL函数(C++(。当我尝试调用带有参数的函数时,我一直Run-time error '49': Bad DLL calling convention
。调用没有参数的函数没有问题。我相信我涵盖了大多数明显的陷阱(例如,我使用 > dumpbin /EXPORTS
验证了函数名称(,所以我真的一定错过了一些基本的东西。我在下面发布代码。
我在Windows 7和Windows 10上都收到相同的错误。我正在使用Visual Studio 2017和MS Excel 2007和2016(2007在7框中,2016在10框中(。我正在使用受本演练启发的__declspec
和extern "C"
语法
数学图书馆.h
#pragma once
#ifdef MATHLIBRARY_EXPORTS
#define MATHLIBRARY_API __declspec(dllexport)
#else
#define MATHLIBRARY_API __declspec(dllimport)
#endif
extern "C" MATHLIBRARY_API int add_integers(int a, int b);
extern "C" MATHLIBRARY_API int get_integer();
数学图书馆.cpp
#include "stdafx.h"
#include "MathLibrary.h"
int add_integers(int a, int b)
{
return a + b;
}
int get_integer()
{
return 69;
}
VBA 模块函数和定义
Option Explicit
Declare Function add_integers Lib "..MathLibrary.dll" (ByVal x As Integer, ByVal y As Integer) As Integer
Declare Function get_integer Lib "..MathLibrary.dll" () As Integer
Public Function test()
Dim x As Integer
Dim y As Integer
Dim i As Integer
x = 42
y = 27
' this returns 69
i = get_integer()
' this throws Run-time error 49
i = add_integers(x, y)
End Function
感謝 Hans Passant 為我指出了正確的方向。如果使用__stdcall
定义函数,则它可以工作。
数学图书馆.h
#pragma once
#ifdef MATHLIBRARY_EXPORTS
#define MATHLIBRARY_API __declspec(dllexport)
#else
#define MATHLIBRARY_API __declspec(dllimport)
#endif
extern "C" MATHLIBRARY_API int __stdcall add_integers(int a, int b);
extern "C" MATHLIBRARY_API int __stdcall get_integer();
数学图书馆.cpp
/* MathLibrary.cpp : Defines the exported functions for the DLL application. */
#include "stdafx.h"
#include "MathLibrary.h"
int __stdcall add_integers(int a, int b)
{
return a + b;
}
int __stdcall get_integer()
{
return 69;
}
这些函数导出为"_add_integers@8"和"_get_integer@0",我从 VBA 中这样调用它们。
Option Explicit
Declare Function add_integers Lib "..MathLibrary.dll" Alias "_add_integers@8" (ByVal x As Integer, ByVal y As Integer) As Integer
Declare Function get_integer Lib "..MathLibrary.dll" Alias "_get_integer@0" () As Integer
Public Function test()
Dim x As Integer
Dim y As Integer
Dim i As Integer
x = 42
y = 27
' this returns 69
i = get_integer()
' this also returns 69
i = add_integers(x, y)
End Function