运行时错误49,针对Excel / VBA的D语言DLL中的错误DLL调用约定-我缺少什么?

时间:2019-01-17 17:57:16

标签: vba dll d visual-d

我正在尝试从VBA在Excel中获得最简单的D语言DLL。我正在使用VisualD。首先,我使用以下代码从https://wiki.dlang.org/Win32_DLLs_in_D具有C接口的DLLs 中复制了示例示例:

module DDLL;

import core.sys.windows.windows;
import core.sys.windows.dll;

__gshared HINSTANCE g_hInst;

extern (Windows)
BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved)
{
    switch (ulReason)
    {
        case DLL_PROCESS_ATTACH:
            g_hInst = hInstance;
            dll_process_attach( hInstance, true );
            break;

        case DLL_PROCESS_DETACH:
            dll_process_detach( hInstance, true );
            break;

        case DLL_THREAD_ATTACH:
            dll_thread_attach( true, true );
            break;

        case DLL_THREAD_DETACH:
            dll_thread_detach( true, true );
            break;

        default:
    }
    return true;
}

我试图从VBA调用的D应用程序代码是:

module myfns;
export double testdd(double a, double b) { return a + b + 0; }
export int testi(int x) {return 42 + x ; }
export int testii(int a, int b) { return a + b + 0; }

VBA代码为:

Option Explicit

Declare Function testdd Lib "C:\Users\vvkozlov\sources\DDLL\Win32\Debug\DDLL.dll" _
    Alias "_D5myfns6testddFddZd" (ByVal x As Double, ByVal y As Double) As Double
Declare Function testi Lib "C:\Users\vvkozlov\sources\DDLL\Win32\Debug\DDLL.dll" _
    Alias "_D5myfns5testiFiZi" (ByVal x As Long) As Long
Declare Function testii Lib "C:\Users\vvkozlov\sources\DDLL\Win32\Debug\DDLL.dll" _
    Alias "_D5myfns6testiiFiiZi" (ByVal x As Long, ByVal y As Long) As Long

Public Sub test()

    Dim x As Long: x = 42000

    Debug.Print "two doubles: " & testdd(84#, -42#)
    Debug.Print "one long: " & testi(x)
    Debug.Print "two longs: " & testii(x, -x)

End Sub

请注意,我进去并从生成的DLL中钓出损坏的名称。

testdd(两个双打)示例按预期方式工作,但是两个int示例都产生

Runtime Error 49, Bad DLL calling convention
在VBA中

。乍一看,第二和第三次,参数声明似乎很好-在VBA端为Long,在D中为int

为什么double失败时int示例仍然起作用?

1 个答案:

答案 0 :(得分:1)

亚当·D·鲁佩的建议很明确。 D应用程序代码现在看起来像

module myfns;
import std.conv;
extern(Windows) export double testdd(double a, double b) { return a + b + 0; }
extern(Windows) export int testi(int x) {return 42 + x ; }
extern(Windows) export int testii(int a, int b) { return a + b + 0; }

这还具有至少简化名称修饰的令人愉快的副作用(不,从VBA代码中删除Alias无效)。

VBA现在看起来像

Option Explicit

Declare Function testdd Lib "C:\Users\vvkozlov\sources\DDLL\Win32\Debug\DDLL.dll" _
    Alias "_testdd@16" (ByVal x As Double, ByVal y As Double) As Double

Declare Function testi Lib "C:\Users\vvkozlov\sources\DDLL\Win32\Debug\DDLL.dll" _
    Alias "_testi@4" (ByVal x As Long) As Long

Declare Function testii Lib "C:\Users\vvkozlov\sources\DDLL\Win32\Debug\DDLL.dll" _
    Alias "_testii@8" (ByVal x As Long, ByVal y As Long) As Long

现在到BSTR,然后到SAFEARRAY。否Variant