Я ищу наиболее надежный способ передачи булевой переменной VB6 в функцию (написано на C ++, stdcall).
Функция C ++ устанавливает переменную «bool» структуры, используя эту переменную VB6.
Я попытался объявить это так в C ++:
extern "C" __declspec(dllexport) int SetParameter( BOOL bErrorView)
{
DLL_sSettings nSet;
nSet.bErrorView =(bErrorView != FALSE);
int ret = stSetParameter(sizeof(DLL_sSettings), nSet);
return (ret);
}
stSetParameter объявлен как
extern "C" int ST_COMDLL_API stSetParameter(int DataLen, DLL_sSettings Settings);
DLL_sSetting объявлен как
typedef struct
{
bool bErrorView; // true: Show
// false: Don't show
(...)
} DLL_sSettings;
Однако я не могу заставить его работать.
Я называю это в VB6, используя
Private Declare Function SetParameter Lib "MyDLL.dll" Alias "_SetParameter@4" (ByVal bErrorView As Boolean) As Long
Но это не работает, как ожидалось, я думаю, что где-то VB6 Boolean теряется или неправильно конвертируется.
В настоящее время я использую VB6 Boolean, C ++ BOOL и C ++ bool.
Я знаю, что это не так приятно, но я не вижу другого пути.
Кто-нибудь замечает что-то не так в моем коде?
VB6 по умолчанию использует соглашение о вызовах StdCall (соглашение cdecl поддерживается, если вы создаете библиотеку типов с module
раздел, описывающий ваш импорт, вместо использования Declare Function
). А C ++ поддерживает целый ряд соглашений о вызовах: stdcall, fastcall, cdecl, thiscall.
Важно отметить, что вызова функций с использованием stdcall в другой библиотеке недостаточно для изменения ваших функций на stdcall. Вы можете использовать параметр командной строки для компилятора, но наиболее надежным является включение __stdcall
Ключевое слово в вашем исходном коде. Он применяется к имени функции, например так:
int __stdcall functionname(int args);
Так как вы также захотите экспортировать эти функции для VB6, чтобы найти их, вы захотите extern "C"
уменьшить искажение имени, и __declspec(dllexport)
разместить их в таблице экспорта.
Довольно часто используется макрос для выполнения всего вышеперечисленного сразу. Похоже, что библиотека, которую вы упаковываете, делает это с ST_COMDLL_API
, Внутри библиотеки, которая будет расширяться до __declspec(dllexport) __stdcall
, Для потребителей это будет использовать dllimport
вместо.
Каждый раз, когда вы определяете API, который будет использоваться в разных компиляторах (или даже в разных языках), хорошей идеей будет быть очень явным в отношении соглашения о вызовах и упаковки структуры (#pragma pack
). В противном случае вы находитесь в зависимости от параметров, указанных в файле проекта и других файлах заголовков. Даже если вы довольны настройками по умолчанию, используемыми компилятором, ваши публичные заголовки должны быть явными, потому что в конечном итоге кто-то попытается использовать две библиотеки в одной программе, а другая библиотека может потребовать изменения параметров компиляции.
BOOL
это определение типа для int
,
он объявлен в Windef.h следующим образом:
typedef int BOOL;
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
bool
тип C ++, который нельзя использовать в прототипе функции, если вы объявляете функцию с extern "C"
,
поэтому VB должен рассматривать BOOL как Long (32-разрядное целое число), а не как Bolean. 0 означает ложь в противном случае (обычно 1) это правда.