Ошибка выполнения 49, недопустимое соглашение о вызовах DLL в DLL языка D для Excel/VBA - Что мне не хватает?

Я пытаюсь получить простейшую возможную библиотеку D-языка, работающую из VBA в Excel. Я использую Visual D. Во-первых, я скопировал пример шаблона из https://wiki.dlang.org/Win32_DLLs_in_D, DLL с интерфейсом C, используя следующий код:

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;
}

Код приложения D, который я пытаюсь вызвать из VBA:

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 (two doubles) работает, как и ожидалось, но оба примера int приводят к

Runtime Error 49, Bad DLL calling convention

в VBA. На первый, второй и третий взгляд объявления аргументов выглядят хорошо - Long на стороне VBA, int в D.

Почему double пример работы в то время как int потерпит неудачу?

1 ответ

Совет Адама Руппе был точным. Код приложения 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 не работает).

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,

Другие вопросы по тегам