Hi,
Apart from just starting with Lazarus after a many year hiatus, I am necessarily in the OSX world. This is because of issues with Delphi which, even at 10.2.3, there are problems and no 64bit version for the foreseeable future (which is bad if you are doing OSX).
Now (I think) I had my code working the 32 bit version (carbon). It's a simple statically loaded DYLIB (so it gets loaded first) with one call (_say_Hello). I have converted to 64bit. This in and of itself has been plagued with issues. My settings now are (so we are all on the same page):
Tools>Settings>Environment>FilesCompiler Executable: /usr/local/bin/ppcx64
Project Options>Compiler Options>Config and TargetTarget OS: (Default)
Target CPU Family: x86_x64
Target Processor: (Default)
For clarity I've included the code below, but when I look at the DYLIB with
nm -gU there is definitely an entry for _say_Hello(). Please take the time to have a look, this is a blocker.
Regardless, I cannot seem to get past this error (no matter what combination of '_' I use or whether or not I put in the full path of the DYLIB. There error messages are:
Hint: (11030) Start of reading config file /etc/fpc.cfg
Hint: (11031) End of reading config file /etc/fpc.cfg
Free Pascal Compiler version 3.0.4 [2017/11/26] for x86_64
Copyright (c) 1993-2017 by Florian Klaempfl and others
(1002) Target OS: Darwin for x86_64
(3104) Compiling pDYLIBTestAPP.lpr
(3104) Compiling udylibtestapp.pas
/Users/kevin/Dropbox/Lazarus/DYLIBTest/udylibtestapp.pas(28,28) Hint: (5024) Parameter "Sender" not used
/Users/kevin/Dropbox/Lazarus/DYLIBTest/udylibtestapp.pas(27,28) Hint: (5024) Parameter "Sender" not used
/Users/kevin/Dropbox/Lazarus/DYLIBTest/udylibtestapp.pas(26,28) Hint: (5024) Parameter "Sender" not used
(9001) Assembling (pipe) /Users/kevin/Dropbox/Lazarus/DYLIBTest/lib/x86_64-darwin/udylibtestapp.s
(9001) Assembling (pipe) /Users/kevin/Dropbox/Lazarus/DYLIBTest/lib/x86_64-darwin/pDYLIBTestAPP.s
(9022) Compiling resource /Users/kevin/Dropbox/Lazarus/DYLIBTest/lib/x86_64-darwin/pDYLIBTestAPP.or
(9015) Linking /Users/kevin/Dropbox/Lazarus/DYLIBTest/darwin/pDYLIBTestAPP
Undefined symbols for architecture x86_64:
"__say_Hello", referenced from: [MY COMMENT] NOTE THE Double '_' as in '__'
_UDYLIBTESTAPP$_$TFDYLIBTESTAPP_$__$$_BITBTN1CLICK$TOBJECT in udylibtestapp.o
ld: symbol(s) not found for architecture x86_64
An error occurred while linking
pDYLIBTestAPP.lpr(25) Error: (9013) Error while linking
pDYLIBTestAPP.lpr(25) Fatal: (10026) There were 1 errors compiling module, stopping
Fatal: (1018) Compilation aborted
If I take the '_' out of the function name in the coed this shows the same error, but with a single '_'. I have used the application bundle option and that is an issue because it don't build the Host. If I take out the call to the DYLIB, it works fine.
Host Code:
UPDATE:According to what I have found, I don't need to use the full name of the DYLIB because the system will fix that. So I only need
and the system will prefix wth lib and postfix with .dylib. And modified to remove '_' for 64 bit version as seen in lazarus documentation. Did that, same issue?
unit uDYLIBTestAPP;
{$mode objfpc}{$H+}
interface
uses
Classes,
SysUtils,
Forms,
Controls,
Graphics,
Dialogs,
Buttons,
StdCtrls;
type
{ TfDylibTestApp }
TfDylibTestApp = class(TForm)
BitBtn1: TBitBtn;
BitBtn2: TBitBtn;
BitBtn3: TBitBtn;
Memo1: TMemo;
procedure BitBtn1Click(Sender: TObject);
procedure BitBtn2Click(Sender: TObject);
procedure BitBtn3Click(Sender: TObject);
private
public
end;
const
// Windows DLL Names
{$IFDEF MSWINDOWS}
TestDLL = 'pdylibtest.dll';
{$ENDIF MSWINDOWS}
// macOS DYLIB Names
{$IFDEF DARWIN}
TestDLL = 'pdylibtest';
{$ENDIF DARWIN}
{$IFDEF MSWINDOWS}
function say_Hello(Hello: string): boolean; stdcall; external TestDLL Delayed;
{$ENDIF MSWINDOWS}
{$IFDEF DARWIN}
function say_Hello(Hello: string): boolean; cdecl; external TestDLL;
{$ENDIF DARWIN}
function localFunction(localIn: string; out localOut: string): boolean;
var
fDylibTestApp: TfDylibTestApp;
implementation
function localFunction(localIn: string; out localOut: string): boolean;
begin
LocalOut := 'This was passed to the function: ' + LocalIn;
Result := True;
end;
{$R *.lfm}
{ TfDylibTestApp }
procedure TfDylibTestApp.BitBtn3Click(Sender: TObject);
begin
// Quit the test application
close;
end;
procedure TfDylibTestApp.BitBtn2Click(Sender: TObject);
var
sOut: string;
begin
// This is a local function
ShowMessage('Local Function Call');
if localFunction('Local in', sOut) then
showmessage('Local Function: TRUE (' + sOut + ')')
else
showmessage('Local Function: FALSE');
end;
procedure TfDylibTestApp.BitBtn1Click(Sender: TObject);
var
b:boolean;
sType: string;
sDLLString: string;
begin
b := False;
// Call the DLL Function
{$IFDEF MSWINDOWS}
sType := 'Windows DLL';
sDLLString := 'The string passed to the Windows DLL';
b := say_Hello(sDLLString);
{$ENDIF MSWINDOWS}
{$IFDEF DARWIN}
sType := 'macOS DYLIB';
sDLLString := 'The string passed to the macOS DYLIB';
b := say_Hello(sDLLString);
{$ENDIF DARWIN}
if b then
showmessage('Returned From: ' + sType + ': TRUE')
else
showmessage('Returned From: ' + sType + ': FALSE');
end;
end.
DYLIB CODE (the dylib builds OK without error):
library pDYLIBTest;
{$mode objfpc}{$H+}
{$R *.res}
uses
Classes,
SysUtils,
Forms,
Controls,
Graphics,
StdCtrls,
Dialogs,
Buttons,
Interfaces;
var
sType: string;
//function say_Hello(Hello: string): boolean; cdecl;{$IFDEF DARWIN} alias : '_say_Hello'; {$ENDIF DARWIN}
function say_Hello(Hello: string): boolean; cdecl;
begin
ShowMessage('[DYLIB] This is the new direct call: DYLIB / DLL using FMX.Forms and FMX.Dialogs');
{$IFDEF WINDOWS}
sType := 'Windows DLL';
{$ENDIF WINDOWS}
{$IFDEF DARWIN}
sType := 'macOS DYLIB';
{$ENDIF DARWIN}
Result := True;
end;
end.
exports
//say_Hello;{$IFDEF DARWIN} name '_say_Hello'; {$ENDIF DARWIN}
say_Hello;
initialization
ShowMessage('[DYLIB] initialization');
finalization
ShowMessage('[DYLIB] finalization');
end.
``
So apart from the obvious question, why can the Host application NOT see the function in the DYLIB?
Does anyone have
simple test code that is working that has a 64bit Host and a 64bit DYLIB that they might share with me (or point me to an example) so that I can see where I am going wrong?
Many thanks