Я хочу скомпилировать DLL в C ++, а затем вызвать библиотеку из VBA. Я сделал это на битах windows32. Но я хотел повторить такое упражнение, так как я использую Windows 64 бит на работе. Учитывая этот факт, я скачал mingw 64.
Мой пример:
main.h
#ifndef __MAIN_H__
#define __MAIN_H__
#ifdef BUILD_DLL
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif
extern "C"{
int DLL_EXPORT __stdcall add2(int num);
int DLL_EXPORT __stdcall mult(int num1, int num2);
}
#endif // __MAIN_H__
main.cpp
#include "main.h"
int DLL_EXPORT __stdcall add2(int num)
{
return num + 2;
}int DLL_EXPORT __stdcall mult(int num1, int num2)
{
int product;
product = num1 * num2;
return product;
}
Когда я компилирую dll, я передаю следующие параметры компоновщика:
Wl,--add-stdcall-alias
и / или
Wl,--kill-at
Я также создаю файл .def, который выглядит следующим образом:
EXPORTS
add2 @1
mult @2
Я ожидал файл .def, который выглядит примерно так (как на моем 32-битном ПК):
EXPORTS
add2 @1
mult @2
add2 = add2 @1
mult = mult @2
Затем я вызываю DLL и функции из VBA следующим образом:
Public Declare PtrSafe Function add2 _
Lib "C:\MyPath\dll.dll" _
(ByVal num As Long) As Long
Проблема в том, что функции могут быть вызваны из редактора VBA и дают правильные результаты, но при вызове из листа Excel они выбрасывают другое число (адрес переданного аргумента ??). Если я пытаюсь вызвать функцию из VBA ПОСЛЕ того, как я попробовал в Excel, то VBA выдает ошибку (из стека Space).
Этой проблемы нет, когда я использую mingw4.7 32bit. Проблема заключается в том, что при компиляции с использованием 64-разрядной версии mingw 4.6.3 (я установил 64-разрядную версию mingw4.7, но обнаружил в Интернете, что люди говорят, что 4.6.3 более стабильна)
Я также заметил, что файл .def выглядит так же, как и выше, даже если я не передаю параметры компоновщика.
Кто-нибудь может помочь? что происходит? Mingw64 или VBA / Excel плохо? или у меня конфигурация mingw64?
ОБНОВИТЬ….
хорошо, я нашел этот сайт:https://sites.google.com/site/jrlhost/links/excelcdll#array и, как объясняется там с помощью функции itermediate в VBA, моя функция add2 работает с листа.
Public function fromWorksheetAdd2 ( dim x as Long) as Long
fromWorksheetAdd2 = add2(x)
end function
тогда я могу использовать fromWorksheetAdd2 на рабочих листах и Add2 на VBA. Однако такой подход довольно утомителен. Надеюсь, что кто-то может помочь с элегантным подходом.
Посмотри на свои параметры.
Long в VBA составляет 64 бита (8 байт). На стороне C ++ размер int равен размеру sizeof (int), который, скорее всего, составляет 4 байта в среде, которую вы используете.
Вы должны гарантировать, что типы, которые вы отправляете и возвращаете между VBA и C ++, имеют одинаковый размер, иначе вы можете столкнуться с повреждением стека.
Других решений пока нет …