DLL 的"good"调用约定是什么?

What is the "good" calling convention for a DLL?

本文关键字:是什么 约定 good DLL 调用      更新时间:2023-10-16

我正在尝试编写一个可以从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框中(。我正在使用受本演练启发的__declspecextern "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