After converting my Delphi Alexandria 11.3 program from 32 to 64 bits, I noticed that connecting to a (64bit) FireBird database required other DLLs.
In FireDac.Phys.IBWrapper
this procedure gets called with
AVendorHome=''
AVendorLib=''
ALibNames=('ibclient64.dll', 'ibtogo64.dll')
procedure TIBLib.LoadBase(const AVendorHome, AVendorLib: String; AThreadSafe: Boolean
{$IFNDEF FireDAC_IB_STATIC} ; const ALibNames: array of String {$ENDIF});
{$IFNDEF FireDAC_IB_STATIC}
var
sDLLName: String;
aDLLNames: array of String;
i, j, n: Integer;
{$ENDIF}
begin
FThreadSafe := AThreadSafe;
{$IFNDEF FireDAC_IB_STATIC}
for j := 1 to 2 do begin
sDLLName := AVendorHome;
if sDLLName <> '' then begin
sDLLName := FDNormPath(sDLLName);
if j = 2 then
sDLLName := FDNormPath(sDLLName + C_FD_DLLFolder);
end
else if j = 2 then
Break;
n := Length(aDLLNames);
if AVendorLib <> '' then begin
SetLength(aDLLNames, n + 1);
aDLLNames[n] := sDLLName + AVendorLib;
end
else begin
SetLength(aDLLNames, n + Length(ALibNames));
for i := 0 to Length(ALibNames) - 1 do <-- HERE
aDLLNames[n + i] := sDLLName + ALibNames[i];
end;
end;
inherited Load(aDLLNames, True);
{$ELSE}
LoadEntries;
GetLibraryInfo;
{$ENDIF}
end;
What this does is filling the initially empty aDLLNames
with the two entries in ALibNames
('HERE')
The inherited Load(aDLLNames, True)
(the True meaning Required) then tries to load both DLLs with inherited LoadLibrary(ADLLNames, ARequired)
I copied the two files ibclient64.dll
and interbase.msg
from c:\Users\Public\Documents\Embarcadero\Interbase\redist\InterBase2020\win64\
to my program directory,
but the above code also requires ibtogo64.dll
, so this then fails on the ibtogo64.dll
with 'Cannot load vendor library':
My code does not use IBToGo.
The array with the two names was set up in ('HERE'):
procedure TIBLib.LoadIB(const AVendorHome, AVendorLib: String;
AEmbedded, AThreadSafe: Boolean);
{$IFNDEF FireDAC_IB_STATIC}
const
C_GDS: String = {$IFDEF MSWINDOWS} {$IFDEF FireDAC_64} 'ibclient64' {$ELSE} 'gds32' {$ENDIF} {$ENDIF}
{$IFDEF POSIX} 'libgds' {$ENDIF} + C_FD_DLLExt;
C_TOGO: String = {$IFDEF MSWINDOWS} {$IFDEF FireDAC_64} 'ibtogo64' {$ELSE} 'ibtogo' {$ENDIF} {$ENDIF}
{$IFDEF POSIX} 'libibtogo' {$ENDIF} + C_FD_DLLExt;
{$ENDIF}
begin
{$IFDEF ANDROID}
FDSetEnv('INTERBASE', TPath.GetDocumentsPath + PathDelim + 'interbase');
{$ENDIF}
if AEmbedded then
// Force ToGo
LoadBase(AVendorHome, AVendorLib, AThreadSafe
{$IFNDEF FireDAC_IB_STATIC},
[C_TOGO]
{$ENDIF}
)
else
LoadBase(AVendorHome, AVendorLib, AThreadSafe
{$IFNDEF FireDAC_IB_STATIC},
{$IF DEFINED(MACOS) and not DEFINED(IOS)}
// MacOSX: InterBase ToGo is preferred, and thus LIBIBTOGO has a higher priority
[C_TOGO, C_GDS]
{$ELSEIF DEFINED(IOS) or DEFINED(ANDROID)}
// iOS, iOSSim, Android: no client/server, and thus no LIBGDS
[C_TOGO]
{$ELSE}
// Windows: client/server is preferred over ToGo
[C_GDS, C_TOGO] <-- HERE
{$ENDIF}
{$ENDIF}
);
end;
Isn't that strange? If I have ibclient64.dll
, why require ibtogo64.dll
?
Should I report this as a bug?
And the next question is what the best solution is (assuming that ibtogo64.dll
is indeed not necessary). Distribute ibtogo64.dll
with my app as well *, or hack the code to not include C_TOGO
in the array?
That conditional define FireDAC_IB_STATIC
is set in FireDac.Inc
as:
{$IF DEFINED(IOS) and (DEFINED(CPUARM) or DEFINED(CPUARM64)) or DEFINED(ANDROID)}
{$DEFINE FireDAC_IB_STATIC} // Use IB driver static linking
{$DEFINE FireDAC_IB_STATIC_IBBRAND} // Use IbTogo static linking library
{$ENDIF}
Using that define would seem to 'solve' the issue, were it not that the definition of TIBLib.LoadBase
changes. I'd probably open a can of worms trying to use that.
* Actually , there are 3 DLLs in c:\Users\Public\Documents\Embarcadero\Interbase\redist\InterBase2020\win64_togo\
: ibtogo64.dll
, ibxml64.dll
and ib_util64.dll