«Плохое соглашение о вызовах DLL» при использовании DLL C ++ из Excel VBA - Как решить? - PullRequest
0 голосов
/ 17 сентября 2018

Мне нужно создать DLL C ++, в которой есть одна функция, которая возвращает строку для использования в коде VBA для Excel (2010).

Я прочитал следующие сообщения: Использование C ++ DLLв Excel VBA - и учебные пособия Microsoft по созданию DLL C ++ и использованию VBA ( Пошаговое руководство. Создание и использование собственной библиотеки динамических ссылок (C ++) , Доступ к DLL в Excel ) иследуя процедуре.

Вот код:

C ++ dll (взято с веб-страницы Microsoft):

// MathLibrary.h - Contains declarations of math functions
#pragma once

#ifdef MATHLIBRARY_EXPORTS
#define MATHLIBRARY_API __declspec(dllexport)
#else
#define MATHLIBRARY_API __declspec(dllimport)
#endif

// The Fibonacci recurrence relation describes a sequence F
// where F(n) is { n = 0, a
//               { n = 1, b
//               { n > 1, F(n-2) + F(n-1)
// for some initial integral values a and b.
// If the sequence is initialized F(0) = 1, F(1) = 1,
// then this relation produces the well-known Fibonacci
// sequence: 1, 1, 2, 3, 5, 8, 13, 21, 34, ...

// Initialize a Fibonacci relation sequence
// such that F(0) = a, F(1) = b.
// This function must be called before any other function.
extern "C" MATHLIBRARY_API void fibonacci_init(
    const unsigned int a, const unsigned int b);

// Produce the next value in the sequence.
// Returns true on success and updates current value and index;
// false on overflow, leaves current value and index unchanged.
extern "C" MATHLIBRARY_API bool fibonacci_next();

// Get the current value in the sequence.
extern "C" MATHLIBRARY_API unsigned int fibonacci_current();

// Get the position of the current value in the sequence.
extern "C" MATHLIBRARY_API unsigned fibonacci_index();

код VBA (Mine, следуя документации Microsoft):

Public Declare Sub fibonacci_init Lib "C:\development\MathLibrary\Release\MathLibrary.dll" (ByVal a As Integer, ByVal a As Integer)
Public Declare Function fibonacci_next Lib "C:\development\MathLibrary\Release\MathLibrary.dll" () As Boolean
Public Declare Function fibonacci_current Lib "C:\development\MathLibrary\Release\MathLibrary.dll" () As Integer

Public Function run_dll()
    Dim b As Integer

    Call fibonacci_init(1, 1)
    b = fibonacci_current()
End Function

Когда я запускаю функцию run_dll в VBA, я получаю исключение: "Соглашение о неправильном вызове DLL" в строке Call fibonacci_init(1,1).

Что здесь не так?Я объявил функцию C ++ как extern "C", поэтому я предположил, что соглашение о вызовах фиксировано ...

ОБНОВЛЕНИЕ

Больше вещей, которые я пробовал ...

  1. Я создал новую dll с нуля, следуя советам из комментариев / ответов:

Trial.cpp:

const char* str = "abcdefg";

extern "C" __declspec(dllexport) int size()
{
    return strlen(str);
}

extern "C" __declspec(dllexport) bool test(char* pReturn)
{
    int nSize = strlen(str);
    lstrcpynA(pReturn, str, nSize);

    return true;
}

с помощьюследующий VBA:

Public Declare Function size Lib "C:\development\MathLibrary\Release\Trial.dll" () As Long
Public Declare Function test Lib "C:\development\MathLibrary\Release\Trial.dll" (ByVal p As Long) As Boolean

(1) Public Function run_dll()
(2)    Dim bb As Boolean
(3)    Dim sz As Integer
(4)    Dim s As String        
(5)    sz = size()       
(6)    s = Space(sz)        
(7)    bb = test(StrPtr(s))
(8) End Function

строка 5 работает нормально - sz получает 7. Но строка 7 выдает «Соглашение о неправильном вызове DLL».

Попытка объявить функцию C ++ с WINAPI как упомянутое в посте, который я прочитал, дает: Can't find DLL entry point size in C:\development\MathLibrary\Release\Trial.dll.

Изменение testОбъявление VBA

Public Declare Function test Lib "C:\development\MathLibrary\Release\Trial.dll" (ByRef p As String) As Boolean

и вызов (line7) как bb = test(s) - вызывает сбой Excel

Изменение объявления test VBA на

Public Declare Function test Lib "C:\development\MathLibrary\Release\Trial.dll" (ByRef p As Long) As Boolean

и вызов (line7) как bb = test(StrPtr(s)) - дает: "Соглашение о неправильном вызове DLL"

Кажется, ничего не работает.У кого-нибудь есть рабочий пример для такой настройки?

Ответы [ 2 ]

0 голосов
/ 17 сентября 2018

Эквивалентом C ++ Integer является длина VBA.

Integer в VBA - это 2-байтовый тип данных, Long в VBA - это 4-байтовый тип данных.Поскольку количество переданных байтов не соответствует ожидаемому количеству байтов, вы получаете Соглашение о неправильном вызове DLL

Обратите внимание, что VBA не поддерживает неподписанные типы, поэтому ваш выводинтерпретируется как 4-байтовое целое (длинное) со знаком.

0 голосов
/ 17 сентября 2018

Вам нужно будет сделать это как библиотеку COM.Затем их можно импортировать в код VBA после их регистрации в реестре Windows.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...