for the first time I have to call an external DLL from Delphi. It's the DLL provided with a weight scale. First thing, I would like to connect to this scale. Here is my code:
unit XOdeca;
interface
[...]
type
TXFSOdecaConnected = function: boolean; stdcall;
TXFSOdecaConnect = procedure (SERIAL_PORT: PChar); stdcall;
TXOdeca = class
protected
FOdecaDllHandle: THandle;
FFLBilanciaConnessa: boolean;
public
constructor Create;
destructor Destroy; override;
procedure LoadOdeca;
end;
implementation
uses
System.UITypes;
[...]
procedure TXOdeca.LoadOdeca;
const
LibName = 'OdecaDeviceControl.dll';
var
libreria: string;
fnIsScanLibraryRegistered: TXFSOdecaConnected;
fnConnectOdeca: TXFSOdecaConnect;
begin
if FOdecaDllHandle = 0 then
begin
libreria := ExtractFilePath( Application.ExeName ) + LibName;
if not FileExists( libreria ) then
raise Exception.Create( 'Non posso aprire la libreria ' + libreria );
try
FOdecaDllHandle := LoadLibrary( @libreria[1] );
if FOdecaDllHandle = 0 then
raise Exception.Create('Errore in caricamento libreria "' + LibName + '"' );
@fnConnectOdeca := GetProcAddress( FOdecaDllHandle, 'Odeca.SerialDevice.Connect');
if not Assigned( @fnConnectOdeca ) then
raise Exception.Create( 'Impossibile trovare il punto di ingresso "fnConnectOdeca" in "' + LibName + '"' );
@fnIsScanLibraryRegistered := GetProcAddress( FOdecaDllHandle, 'Odeca.SerialDevice.Connected');
if not Assigned( @fnIsScanLibraryRegistered ) then
raise Exception.Create( 'Impossibile trovare il punto di ingresso "FSIsScanLibraryRegistered" in "' + LibName + '"' );
FFLBilanciaConnessa := fnIsScanLibraryRegistered;
except
[...]
end;
end;
end;
end.
I get to load correctly the library (FOdecaDllHandle gets a value different from 0), but then I can't connect to any function or procedure in the library, the GetProcAddress always returns 0.
From the documentation provided with the library, the names of the procedures are correct.
There are also two working examples in VB.net and C# coming with the library, and they both declare objects such as (VB.net)
Private odecaDevice As New Odeca.SerialDevice
but I think this is not possible in Delphi, since I don't add references to the objects of the library.
Does it have anything to do with the dot notation used in the library? (consider for example that every procedure comes in two versions, to be used depending on the connection type of the weight scale, e.g. Odeca.SerialDevice.Connect and Odeca.NetworkDevice.Connect).
Thank you very much, Fabio
--- UPDATE 29/03/2019
Following the examples at this link Work around with Delphi DLL I created the following OdecaWrapper.dll:
procedure CONNECT; export;
var
adll: Thandle;
afunc: function:Boolean;
begin
adll:=LoadLibrary('OdecaDeviceControl.dll');
afunc:= GetProcAddress(adll,'Odeca.SerialDevice.Connect');
afunc;
FreeLibrary(adll);
end;
exports
CONNECT;
In my Delphi code, I define.
procedure CONNECT; stdcall; external 'OdecaWrapper.dll';
with no implementation. In the same Delphi unit, I have a procedure calling this external procedure
procedure TXOdeca.LoadOdeca;
begin
try
CONNECT;
[missing]
except
on E:Exception do
begin
MessageDlg( E.Message, mtWarning, [mbOK], 0 );
end;
end;
end;
All I get is Access Violation when I get to the CONNECT command of my procedure, what am I doing wrong?
Odeca.SerialDevice.Connectfor example, I'm pretty sure is not a valid function name for standard interop. It likely is something such as COM or .NET as mentioned. - Jerry Dodge