Использование COM-DLL с параметрами BSTR* -> ошибка Float Div By Zero

В настоящее время я разрабатываю собственное приложение среднего размера, которое должно включать некоторые функции, которые уже были включены в предыдущее приложение. Это было разработано в Visual Basic 6 много лет назад внешним поставщиком. К сожалению, у меня нет доступа к исходному коду, но, к счастью, необходимые классы содержатся в COM DLL, которая также была создана в VB6. В настоящее время используется среда разработки C++ Builder 10.1. Я могу легко установить DLL через regsvr32.exe. Функция импорта библиотеки типов в CBuilder сгенерировала красивую оболочку VCL на основе TOleServer. DLL довольно большая, и после импорта уже возникла проблема с отсутствующей перегрузкой функции, которую мне пришлось добавить вручную. Иначе оболочка вроде бы работает.

Теперь к настоящей проблеме:

DLL содержит класс, поля которого можно загрузить из файла XML с помощью метода Load. Эта функция имеет 2 параметра: Файл в виде строки и Схема в виде строки в VB6 и VBA (проверено в Excel 2010). Параметр Schema является необязательным. Если я сейчас создаю объект класса в VBA, я могу передать строку имени файла в качестве параметра File, и поля класса загружаются без проблем. Если я посмотрю на сгенерированный класс-оболочку в CBuilder, у функции Load есть два параметра типа "BSTR *". Параметр Schema помечается как необязательный в автоматически сгенерированном комментарии, но ему не назначено значение по умолчанию, и поэтому он не является обязательным (?). Поэтому я должен использовать параметр Схема. Странно, но вместо BSTR ожидается указатель на BSTR. Поэтому я попробовал следующее:

BSTR File = SysAllocString(L"C:\\temp\\file.xml");
BSTR Schema = SysAllocString(L"");

TMyOleClass *MyClass = new TMyOleClass(this);

MyClass->Load(&File, &Schema);

Поскольку файлы схемы обычно не используются, у меня их нет. Поэтому это нулевая строка.

Класс создается без ошибок, но функция Load выдает ошибку Float Divide By Zero в MSVBVM60.dll. Другие функции класса, для которых требуется обычный BSTR (не указатель на него), работают без проблем.

Так...

  • Почему второй параметр не является обязательным в сгенерированной оболочке VCL?
  • Почему параметры типа BSTR *, а не типа BSTR, как и другие?
  • Почему указанная ошибка?

Спасибо за все ответы.


РЕДАКТИРОВАТЬ:

Я открыл класс с oleview.exe. Функция Load имеет следующее определение:

HRESULT Load(
            [in, out] BSTR* Filepath, 
            [in, out, optional] BSTR* Schema, 
            [out, retval] VARIANT* );

хотя только в каталоге объектов Excel VBA

Function Load(Filepath As String, [Schema As String])

показано (нет ссылок).

Идея установить для параметра схемы значение NULL не сработало. Появилась та же ошибка div.

Благодаря @Remy Lebeau я создал вариант и попробовал снова:

BSTR Path = SysAllocString(L"C:\\temp\\file.xml");
VARIANT varOpt;

varOpt.vt = VT_ERROR;
varOpt.scode = DISP_E_PARAMNOTFOUND;

TC_MyClass *MyClass = new TC_MyClass(this);

MyClass->Load(&Path, (BSTR*)&varOpt);

-> та же ошибка.

Я обнаружил, что если пропустить Исключения с продолжением в 3 раза, появится ошибка: этот массив исправлен или временно заблокирован.

Ниже приведены некоторые картинки;

Ошибка (немецкий BCB)

Строка кода в utilcls.h после этого поднимается ошибка


Вот некоторые части созданного CBuilder VCL-Wrapper:

class PACKAGE TC_MyClass : public Vcl::Oleserver::TOleServer
{
   _C_MyClassPtr m_DefaultIntf;
   _di_IUnknown __fastcall GetDunk();
public:
  __fastcall TC_MyClass(System::Classes::TComponent* owner) : Vcl::Oleserver::TOleServer(owner)
 {}

...  

VARIANT __fastcall Load(BSTR* Filepath/*[in,out]*/, BSTR* Schema/*[in,out,opt]*/)
{
    VARIANT Param3;
    OLECHECK(GetDefaultInterface()->Load(Filepath, Schema, (VARIANT*)&Param3));
    return Param3;
}  

...

@ Реми Лебо: функция, которую мне пришлось изменить вручную, была

HRESULT __fastcall  set_Sections(MyHugeAndComplex_dll_tlb::_E_SectionsPtr* Param1/*[in,out]*/)
{
    return set_Sections((MyHugeAndComplex_dll_tlb::_E_Sections*)Param1/*[in,out]*/);
}

где мне пришлось добавить вторую реализацию

HRESULT __fastcall  set_Sections(MyHugeAndComplex_dll_tlb::_E_SectionsPtr** Param1/*[in,out]*/)
{
    return set_Sections(Param1/*[in,out]*/);
}

а также мне пришлось добавить его для второй функции:

HRESULT __fastcall  set_Document(Msxml2_tlb::IXMLDOMDocument2Ptr* Param1/*[in,out]*/)
{
    return set_Document((Msxml2_tlb::IXMLDOMDocument2*)Param1/*[in,out]*/);
}

РЕДАКТИРОВАТЬ 2:

Я создал VI в LabVIEW, который создает экземпляр класса и может без проблем вызывать функцию "Загрузка".

Теперь, когда оборачиваем сам этот созданный ВП в новую DLL-библиотеку Win32 с экспортированным вызовом функции-оболочки "Загрузить" и открываем эту DLL с помощью кода в CBuilder с помощью вызова "SafeLoadLibrary", возникает та же ошибка с плавающей запятой, даже когда я жестко программирую путь к XML в LabVIEW-VI. Я могу вызывать функцию "Загрузка" почти везде, кроме C++ Builder. Думая о том, может быть, это ошибка в CBuilder, а не моя вина...

String DLL_FileName = ExtractFilePath(Application->ExeName) + "MyNewCreatedDLLWrapper.dll";
HINSTANCE hInstance = (HINSTANCE)SafeLoadLibrary(DLL_FileName.w_str());

if(!hInstance)
    throw(Exception("Error loading DLL"));

Load = (Load_Ptr)GetProcAddress(hInstance,"Load");

int32_t Length = 1000;

uint8_t Array[1000];
int32_t RetVal = Load("", Array, &Length); // <-- path can be omitted as it is hard coded in DLL

FreeLibrary(hInstance);

1 ответ

Решение

Итак... Я наконец-то запустил его и запустил, благодаря предложению z32a7ul установить 2-й параметр на NULL и рекомендации Реми Лебо о проверке редактируемого вручную метода. Похоже, что сам этот отредактированный метод вызывается функцией Load. Это была моя ошибка, когда я думал о недостающей перегрузке, когда просто нужно было изменить параметр def на тип указателя. Наконец, мне пришлось установить второй параметр в NULL, как упоминалось выше, но косвенно:

BSTR Path = SysAllocString(L"C:\\temp\\file.xml");
BSTR Schema = NULL;

TC_MyClass *MyClass = new TC_MyClass(this);

MyClass->Load((BSTR*)&Path, (BSTR*)&Schema);

Спасибо за ваши ответы.

Другие вопросы по тегам