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

Я пытаюсь получить простейшую 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?

1 Ответ

0 голосов
/ 18 января 2019

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

...