Я пытаюсь получить простейшую DLL-библиотеку D-языка, работающую из VBA в Excel. Я использую Visual D. Во-первых, я скопировал пример из библиотеки DLL https://wiki.dlang.org/Win32_DLLs_in_D, с интерфейсом 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 (два двойных) работает, как и ожидалось, но оба примера int приводят к
Runtime Error 49, Bad DLL calling convention
в VBA. На первый, второй и третий взгляд объявления аргументов выглядят хорошо - Long
на стороне VBA, int
в D.
Почему пример double
работает при сбое int
?