Ошибка выполнения 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
,