Board index » cppbuilder » Advanced: using a D5 written DLL in C++Builder4

Advanced: using a D5 written DLL in C++Builder4


2003-08-01 03:32:34 PM
cppbuilder2
We have written a 'V43lib.dll' in Delhi5 we wish to use in C++Builder 4.
If we try to "follow the rules" we get tons off errors, but if we do the
following it runs (almost) OK.
With Implib we create a V43lib.lib file for this dll.
In a new project under C++Builder4 we use this lib.
Next we add a header file with the translation in C++ (TNsNavigation) of the
Delphi wrapper class decribed below. And the declaration of the
imported functions:
extern "C" {
TNsNavigation* __declspec(dllimport) __stdcall InitNavigation(TComponent
*AOwner);
void __declspec(dllimport) __stdcall FreeNavigation();
}
In the private section of TForm1 (in C++Builder) we have written:
private: // User declarations
TNsNavigation *Paco;
Now comes the serious part:
if we do this in C++Builder:
void __fastcall TForm1::FormCreate(TObject *Sender)
{
Paco = InitNavigation(this);
if ( Paco != NULL ) {
Paco->OnMainObsDownLoadProgres = FUpdateDownLoadMemo;
Paco->OnRouteUpdate = FUpdateRouteInfo;
}
...
}
At the start of the Application we get first an empty dialog as wide as the
screen with an OK button.
If you click OK you get a small dialog with a few 'chaos' characters and an
OK button.
If you click OK next you get access errors.
But if we do this:
void __fastcall TForm1::FormCreate(TObject *Sender)
{
LoadLibrary("V43lib.lib");
Paco = InitNavigation(this);
if ( Paco != NULL ) {
Paco->OnMainObsDownLoadProgres = FUpdateDownLoadMemo;
Paco->OnRouteUpdate = FUpdateRouteInfo;
}
...
}
At the start of the application we first get a message that 'V43Lib.lib' is
not a valid windows image and if we click ok the whole thing runs smoothly
without problems. The first message is correct of course because
'V43Lib.lib' is not a dll but the result of Implib.
The question is how to get rid of this message.
We expected that in Delphi5 we should have written:
function InitNavigation(AOwner:TComponent):TNsNavigation; stdcall;
{$IFNDEF V43Lib} external 'V43lib.dll' {$ENDIF}
procedure FreeNavigation(); stdcall;
{$IFNDEF V43Lib} external 'V43lib.dll' {$ENDIF}
But this results in the same errors as decribed above with the dialogs and
access errors.
In Delphi we have the following situation:
in the interface section of a unit we have:
TNavigatie = class(TComponent)
private
FOnRouteUpdate :TNotifyEvent;
FRouteUpdateEventEnable :boolean;
FOnObstructionsFound :TNotifyEvent;
FObstructionsFoundEventEnable:boolean;
FOnCalculationFail :TNotifyEvent;
...
public
Captions : TCaptions;
MemoStrings : TMemoStrings;
RouteTrack : TRouteTrack;
...
// Main functions/procedures
constructor Create(AOwner:TComponent); override;
destructor Destroy; override;
function MainObstructionsFileDate():string;
function MainObstructionsCreationDate():string;
function MainDownLoadObstructions():boolean;
...
published
// Main Properties
property OnMainObsDownLoadProgres :TFtpProgresEvent read
FOnMainObsDownLoadProgres write FOnMainObsDownLoadProgres;
property MainSelectedRoute :integer read FSelectedRoute;
// Route Properties
property OnRouteUpdate :TNotifyEvent read FOnRouteUpdate
write FOnRouteUpdate;
property OnRouteObstructionsFound :TNotifyEvent read
FOnObstructionsFound write FOnObstructionsFound;
...
end;
To export this class we've written
a wrapper in wich we wrap the properties and methods we want to export:
{$Define V43Lib}
TNsNavigation = class(TObject)
private
//MAIN
FOnMainObsDownLoadProgres:TFtpProgresEvent;
//SHIPS
FOnShipsListUpdate :TNotifyEvent;
FOnShipsShipUpdate :TNotifyEvent;
//ROUTE
FOnRouteUpdate :TNotifyEvent;
...
public
{$IFDEF V43Lib}
Constructor Create();
{$ENDIF}
//MAIN
function MainGetCopyright: string; virtual;
stdcall; {$IFNDEF V43Lib} abstract; {$ENDIF}
Function MainDownLoadObstructions():Boolean; virtual;
stdcall; {$IFNDEF V43Lib} abstract; {$ENDIF}
procedure MainApplyDownloadedObstructions(); virtual;
stdcall; {$IFNDEF V43Lib} abstract; {$ENDIF}
procedure MainCancelDownloadedObstructions(); virtual;
stdcall; {$IFNDEF V43Lib} abstract; {$ENDIF}
...
published
//MAIN
property OnMainObsDownLoadProgres :TFtpProgresEvent read
FOnMainObsDownLoadProgres write FOnMainObsDownLoadProgres;
//SHIPS
property OnShipsListUpdate :TNotifyEvent read
FOnShipsListUpdate write FOnShipsListUpdate;
end;
function InitNavigation(AOwner:TComponent):TNsNavigation;
{$IFNDEF V43Lib} external 'V43lib.dll' {$ENDIF}
procedure FreeNavigation();
{$IFNDEF V43Lib} external 'V43lib.dll' {$ENDIF}
//according to the rules this should be:
{function InitNavigation(AOwner:TComponent):TNsNavigation; stdcall;
{$IFNDEF V43Lib} external 'V43lib.dll' {$ENDIF}}
{procedure FreeNavigation(); stdcall;
{$IFNDEF V43Lib} external 'V43lib.dll' {$ENDIF} }
// now we declare 2 vars
Var
GNavigatie : TNavigatie;
GNsNavigation : TNsNavigation;
// In the implementation section we do this:
implementation
// Internal
constructor --------------------------------------------------------
constructor TNsNavigation.Create();
begin
inherited Create();
// Definitions of the event properties:
GNavigatie.OnMainObsDownLoadProgres := FSendMainObsDownLoadProgresEvent;
GNavigatie.OnRouteUpdate := FSendRouteUpdateEvent;
...
end;
...
function TNsNavigation.MainGetCopyright: string;
Begin
Result:=CopyRight
end;
Function TNsNavigation.MainDownLoadObstructions():Boolean;
Begin
Result:=GNavigatie.MainDownLoadObstructions();
end;
procedure TNsNavigation.MainApplyDownloadedObstructions();
Begin
GNavigatie.MainApplyDownloadedObstructions();
end;
...
// Finally we do this:
// External
constructor --------------------------------------------------------
function InitNavigation(AOwner:TComponent):TNsNavigation;
begin
...
if Assigned(GNavigatie) then
GNsNavigation := nil
else
begin
GNavigatie := TNavigatie.Create(AOwner);
GNsNavigation := TNsNavigation.Create();
end;
result := GNsNavigation
end;
// External
destructor --------------------------------------------------------
procedure FreeNavigation();
begin
...
if Assigned(GNavigatie) then
begin
GNavigatie.Free;
GNsNavigation.Free;
end;
end;
// In the library unit we do this
uses
ShareMem,
SysUtils,
Classes,
unitAsDecribedAvove,
...
;
{$R *.RES}
Exports
InitNavigation,
FreeNavigation;
begin
end.
I hope someone can help us out of this problem.
Thanks in advance,
Peter Feenstra
 
 

Re:Advanced: using a D5 written DLL in C++Builder4

Peter Feenstra wrote:
Quote
We have written a 'V43lib.dll' in Delhi5 we wish to use in C++Builder 4.
If we try to "follow the rules" we get tons off errors, but if we do the
following it runs (almost) OK.
Too much code for someone to look at. Yet again you fail to give the most
important information: what's the type of TFtpProgresEvent ?
Anyway in these situations the most important thing is to keep dll and exe
code completely isolated. Don't use sharemem (are they the same for builder
4 and Delphi 5 ?), don't pass "AnsiString"s, pass "char *"s (is the
implementation of AnsiString of Builder 4 compatible with the implementation
of Delphi 5 ?) and in general never allow anything allocated from the dll
code to be deallocated from the exe code and vise versa.
Also some other questions:
Is the internal structure of TObject the same for builder 4 and delphi 5 ?
Is TComponent the same ? ... and all the components you seem you are using
from both sides?
Cheers.
Sam.
--
Please remove "sam_" from email address.