FlKo FlKo - 1 year ago 85
C++ Question

Using a COM-DLL with BSTR* parameters --> Float Div By Zero error

Currently, I'm developing a mid-sized in-house application, which should include some features that are already included in a previous application. This has been developed in Visual Basic 6 many years ago by an external supplier. Unfortunately I don't have access to the source code, but fortunately, the necessary classes are contained in a COM DLL, which was also created in VB6. The currently used development environment is C++ Builder 10.1. I can easily install the DLL via regsvr32.exe.
The type library import function in CBuilder has generated a nice VCL wrapper based on TOleServer. The DLL is quite huge, and after the import there was already a problem with a missing function overload, which I had to add by hand. Otherwise, the wrapper seems to work.

Now to the real problem:

The DLL contains a class whose fields can be loaded from an XML file by a method called Load. This function has 2 parameters: File As String and Schema As String in VB6 and VBA (checked with Excel 2010). The parameter Schema is optional. If I now create a class object in VBA, I can pass a filename string as the File param and the class fields are loaded without problems.
If I look at the generated wrapper class in CBuilder, the Load function has two parameters of the "BSTR *" type. The Schema parameter is marked as optional in the automatically generated comment, but has not assigned a default value and is therefore not optional (?). So I have to use the parameter Schema. Strangely, a pointer to BSTR is expected instead of BSTR. So I tried the following:

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

TMyOleClass *MyClass = new TMyOleClass(this);

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

Since schema files are not normally used, I have none. Therefore it's a zero string.

The class is created without errors, but the Load function throws a Float Divide By Zero error in MSVBVM60.dll. Other class functions that require a normal BSTR (not a pointer to it) work without problems.


  • Why is the second parameter not optional in the generated VCL wrapper?

  • Why are the parameters of type BSTR* and not of type BSTR, like the others?

  • Why is there the said error?

Thanks for all answers.


I've opened the class with oleview.exe. The function Load has the following definition there:

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

albeit in the Excel VBA Object Catalog only

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

is shown (no references).

The idea to set the schema Parameter to NULL didn't work.
The same div error came up.

Thanks to @Remy Lebeau, I created a variant and tried it again:

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

varOpt.vt = VT_ERROR;

TC_MyClass *MyClass = new TC_MyClass(this);

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

--> same error.

I've discovered, that if skipping the Exceptions with Continue for 3 times, an error comes up saying: This array is fixed or temporarily locked.

Below are some Pictures;

The error (German BCB)

The code line in utilcls.h after that the error is being raised

Here are some parts of the CBuilder generated VCL-Wrapper:

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


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


@Remy Lebeau: The function I had to change manually was

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

where I had to add a second implementation

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

and also I had to add it for a second function:

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


I've created a VI in LabVIEW which creates an instance of the class and which can call the 'Load' function without problems.

Now, when wrapping this created VI itself within a new Win32 DLL with an exported wrapper function call 'Load' and opening this DLL by code in CBuilder by a 'SafeLoadLibrary' call, the same floating point error occurs, even when I hard code the path to the XML in the LabVIEW-VI. I can call the 'Load' function from nearly everywhere, except for C++ Builder.
Thinking about, if maybe it's a bug in CBuilder and not my fault...

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

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



Answer Source

So....I finally got it up and running, thanks to z32a7ul's proposal to set the 2nd Parameter to NULL and Remy Lebeau's advice of doing a check on the manually edited method. It seems, that this edited method itself is being called by the Load function. It was my fault in thinking of a missing overload where it was just needed to change a parameter def to a pointer type. Finally, I had to set the second param to NULL as mentioned above, but indirectly:

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

TC_MyClass *MyClass = new TC_MyClass(this);

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

Thanks for your answers.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download