c++c++builder-xe5c++builder-5

C++ XE 5 Application and C++ Builder 5 dll compatibility


I have BCB5 dll with method:

extern "C" void __declspec(dllexport) __stdcall SM(TDataSource *DS) {

 TForm *form = new TForm(Application);
 form->Width = 300;
 form->Height = 300;
 form->Name = "frm";

 TDBGrid *grd = new TDBGrid(form);
 grd->Parent = form;
 grd->Name = "grd";
 grd->Align = alClient;
 grd->DataSource = DS;

 form->ShowModal();

}

When I call this method from C++ builder 5 application, it's working fine.

try {
 typedef void __declspec(dllexport) __stdcall SM(TDataSource *DS);
 SM *Upload;
 HINSTANCE hDll = LoadLibrary("main.dll");

 Upload = (SM*) GetProcAddress(hDll,"SM");
 Upload(DataSource1);
 FreeLibrary(hDll);

}
catch (Exception *ex) {
  ShowMessage(ex->Message);
}

But, if I'm trying to call this method from C++ XE 5 application, I get Access Violation.

Is there a way to solve the problem of data transmission from XE 5 application to BCB 5 dll without recompile dll in XE5?


Solution

  • It is not safe to pass/use RTL/VCL objects over the DLL boundary like you are doing, unless both EXE and DLL are compiled with Runtime Packages enabled so that they share a common instance of the same RTL and VCL frameworks (but then you have to deploy the RTL/VCL BPL binaries with your app).

    Your DLL doesn't work in XE5 because the DLL is expecting the BCB5 version of the TDataSource component, not the XE5 version. No, they are not compatible, as they have different memory layouts and dependancies.

    So your choices are to either:

    1. recompile the DLL in XE5, and live with the risk that passing TDataSource over the DLL boundary is not safe in general, unless you enable Runtime Packages.

    2. re-write the DLL to be a Runtime Package (BPL) instead. Then passing TDataSource between EXE and DLL is safe. However, Runtime Packages are version-specific, so you will need to compile separate BPLs if you need to continue using the code in both BCB5 and XE5.

    3. re-write the DLL to not pass a TDataSource over the DLL boundary to begin with. Figure out another interop-safe way to exchange data between EXE and DLL.