DLL的“好”调用约定是什么?

时间:2018-03-08 00:21:50

标签: c++ vba visual-studio dll

我正在尝试编写一个可以从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"语法受到this walkthrough

的启发

MathLibrary.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();

MathLibrary.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

1 个答案:

答案 0 :(得分:0)

感谢Hans Passant将我指向right direction。如果使用__stdcall定义函数则可行。

MathLibrary.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();

MathLibrary.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