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

0

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

Но это работает не так, как ожидалось, я думаю, что где-то ошибка BBlean теряется или неправильно преобразуется.

В настоящее время я использую VB6 Boolean, C++ BOOL и C++ bool. Я знаю, что это не так хорошо, но я не вижу другого пути.

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

  • 0
    Похоже, что функция STDCALL и VB6 используют две разные функции. Сделайте также SetParameter stdcall.
  • 0
    @BenVoigt Моя C ++ DLL настроена на вызов соглашения __stdcall (/ Gz) через свои свойства. Должен ли я написать "extern" C "int SetParameter"? Не могли бы вы дать мне точное написание? И должен ли я сохранить «внешний C»?
Показать ещё 13 комментариев
Теги:
vb6
com
stdcall

2 ответа

2
Лучший ответ

VB6 использует соглашение о вызове StdCall по умолчанию (соглашение cdecl поддерживается, если вы создаете библиотеку типов с секцией module описывающей ваш импорт, вместо использования Declare Function). И C++ поддерживает целый ряд соглашений о вызовах: stdcall, fastcall, cdecl, thiscall.

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

  • 0
    Структура в порядке, VB6 не касается этого. Единственная проблема заключается в совпадении сигнатуры функции в C ++ и в VB.
  • 0
    Хорошо, я удалил последнюю строку, базовый ответ - использовать int в интерфейсе и проверить, равен ли он 0 или нет.
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню