com — Передача логической переменной VB6 в функцию stdcall в C ++ DLL

Я ищу наиболее надежный способ передачи булевой переменной 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.
Я знаю, что это не так приятно, но я не вижу другого пути.

Кто-нибудь замечает что-то не так в моем коде?

0

Решение

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). В противном случае вы находитесь в зависимости от параметров, указанных в файле проекта и других файлах заголовков. Даже если вы довольны настройками по умолчанию, используемыми компилятором, ваши публичные заголовки должны быть явными, потому что в конечном итоге кто-то попытается использовать две библиотеки в одной программе, а другая библиотека может потребовать изменения параметров компиляции.

2

Другие решения

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) это правда.

2

По вопросам рекламы [email protected]