Recent

Author Topic: [Solved] getprocaddress  (Read 9575 times)

RednosePete

  • New Member
  • *
  • Posts: 17
Re: getprocaddress
« Reply #15 on: February 24, 2018, 08:18:59 pm »
Haven't tried Application bundle.

Just tested with the libndfd.dylib library that can be built from this example:

https://macpgmr.github.io/MacXPlatform/PascalDynLibs_2.html

Created Frameworks folder in test app's bundle and copied libndfd.dylib to it.

When run in debugger (lldb) it prints "1.0.4" to console.

Ok, thanks. I will try that (bundle).

rvk

  • Hero Member
  • *****
  • Posts: 6594
Re: getprocaddress
« Reply #16 on: February 24, 2018, 08:23:28 pm »
I see in Lazarus itself (under Project > Project Options) that for running and debugging the Application bundle is used. (no idea what that actually means for a standalone compiled application)

There is a button at the bottom of the options, Show Options. You could try ppcx64 with those options and see if it also fails. If it does then you can strip the options to see which one causes it.


RednosePete

  • New Member
  • *
  • Posts: 17
Re: getprocaddress
« Reply #17 on: February 24, 2018, 08:59:01 pm »
I see in Lazarus itself (under Project > Project Options) that for running and debugging the Application bundle is used. (no idea what that actually means for a standalone compiled application)

There is a button at the bottom of the options, Show Options. You could try ppcx64 with those options and see if it also fails. If it does then you can strip the options to see which one causes it.

Thanks,
I'll give it a try.

RednosePete

  • New Member
  • *
  • Posts: 17
Re: getprocaddress
« Reply #18 on: February 25, 2018, 07:20:05 am »
I see in Lazarus itself (under Project > Project Options) that for running and debugging the Application bundle is used. (no idea what that actually means for a standalone compiled application)

There is a button at the bottom of the options, Show Options. You could try ppcx64 with those options and see if it also fails. If it does then you can strip the options to see which one causes it.

Thanks,
I'll give it a try.
It wasn't due to compiler options; adding them to ppcx64 didn't change the behaviour of the executable.

RednosePete

  • New Member
  • *
  • Posts: 17
Re: getprocaddress
« Reply #19 on: February 25, 2018, 09:12:05 am »
Yet, dylibs in e.g. /usr/lib are "visible" (can be loaded) perfectly well also with an app compiled via Lazarus. I don't have write-permission to /usr/lib and nor do I have admin-rights. I tried to add my dylib path to PATH, DYLD_LIBRARY_PATH, DYLD_FALLBACK_LIBRARY_PATH but no success. This seems to be more OSX- than Lazarus-issue.
« Last Edit: February 25, 2018, 09:50:14 am by RednosePete »

RednosePete

  • New Member
  • *
  • Posts: 17
Re: getprocaddress
« Reply #20 on: February 25, 2018, 10:29:50 am »
I getting more and more confused ...

My current code:
Code: Pascal  [Select][+][-]
  1. procedure TMyApplication.DoRun;
  2. var
  3.   ErrorMsg: String;
  4.    prm1                    : single;
  5.    ptr1                    : Pointer;
  6.    Handle1                 : TLibHandle;
  7.    GetFigm                 : TGetFigm;
  8.    opath                   : string;
  9.    FIGM                    : string = 'libvol.dylib';
  10.    MYFUN                   : string = 'figm';
  11. begin
  12.      writeln('Trying to load');
  13.      writeln('CurrentDir=',GetCurrentDir);
  14.      FIGM := GetCurrentDir+'/'+FIGM;
  15.      if FileExists(FIGM) then writeln(FIGM,' exists');
  16.      Handle1 := LoadLibrary(FIGM);
  17.      if Handle1 <> nilhandle then
  18.      begin
  19.         writeln('handle 1 ok, looking for ',MYFUN);
  20.         ptr1 := GetProcAddress(Handle1, MYFUN);
  21.         if ptr1 <> nil then
  22.            writeln(MYFUN,' found')
  23.         else
  24.           writeln(MYFUN,' not found');
  25.          FreeLibrary(Handle1);
  26.      end
  27.      else
  28.          writeln(FIGM,' not loaded');
  29.   Terminate;
  30. end;

Compiled via Lazarus or lazbuild, this is how it executes:
Trying to load
CurrentDir=/Users/myusername/Documents/TestCodes/LTest
/Users/myusername/Documents/TestCodes/LTest/libvol.dylib exists
/Users/myusername/Documents/TestCodes/LTest/libvol.dylib not loaded

And the same application compiled with ppcx64:
Trying to load
CurrentDir=/Users/myusername/Documents/TestCodes/LTest
/Users/myusername/Documents/TestCodes/LTest/libvol.dylib exists
handle 1 ok, looking for figm
figm found


rvk

  • Hero Member
  • *****
  • Posts: 6594
Re: getprocaddress
« Reply #21 on: February 25, 2018, 11:02:40 am »
What does getloaderrorstr give back after the failed loading of that library?

https://www.freepascal.org/docs-html/rtl/dynlibs/getloaderrorstr.html

It should be the first system call after loadlibrary so do s := getloaderrorstr; directly after it and then output s. (Not sure it's needed under macos but better to make sure)
« Last Edit: February 25, 2018, 11:07:12 am by rvk »

RednosePete

  • New Member
  • *
  • Posts: 17
Re: getprocaddress
« Reply #22 on: February 25, 2018, 11:36:32 am »
What does getloaderrorstr give back after the failed loading of that library?

https://www.freepascal.org/docs-html/rtl/dynlibs/getloaderrorstr.html

It should be the first system call after loadlibrary so do s := getloaderrorstr; directly after it and then output s. (Not sure it's needed under macos but better to make sure)

Finally, we are getting closer:
dlopen(/Users/myusername/Documents/TestCodes/LTest/libvol.dylib, 1): no suitable image found.  Did find:
   ./libvol.dylib: mach-o, but wrong architecture


and file libvol.dylib gives:
file libvol.dylib
libvol.dylib: Mach-O 64-bit dynamically linked shared library x86_64


My next guess is to compile a 32-bit -version of libvol.dylib and "lipo" then 32bit and 64bit dylibs together. Could it be so easy that LoadLibrary in Lazarus can load only 32-bit libraries?

RednosePete

  • New Member
  • *
  • Posts: 17
Re: getprocaddress
« Reply #23 on: February 25, 2018, 12:06:05 pm »
Okay,

I think we (!!! thank you rvk and Phil) probably solved it;

lipo -create libvol32.dylib libvol64.dylib -output libvol.dylib

and file libvol.dylib returns:

libvol.dylib: Mach-O universal binary with 2 architectures
libvol.dylib (for architecture i386):   Mach-O dynamically linked shared library i386
libvol.dylib (for architecture x86_64):   Mach-O 64-bit dynamically linked shared library x86_64


Now both versions (ppcx64 and Lazarus) open the 2-architecture -dylib and find the function in it. I haven't yet tried the function, so there might be still a chance that I get a wrong handle and incorrect (=32bit) function address (I have no previous experience on using double-architecture libraries).
« Last Edit: February 25, 2018, 12:09:12 pm by RednosePete »

rvk

  • Hero Member
  • *****
  • Posts: 6594
Re: getprocaddress
« Reply #24 on: February 25, 2018, 12:11:34 pm »
That would mean your lazbuild project is still i386, doesn't it? If ppcx64 is capable of producing code for loadlibrary which can load x64 libraries, lazbuild should be too. So my guess is that you lazbuild is somehow still stuck on i386.

Can you check the architecture of your lazbuild project using the file command?
« Last Edit: February 25, 2018, 12:14:29 pm by rvk »

RednosePete

  • New Member
  • *
  • Posts: 17
Re: getprocaddress
« Reply #25 on: February 25, 2018, 12:34:43 pm »
That would mean your lazbuild project is still i386, doesn't it? If ppcx64 is capable of producing code for loadlibrary which can load x64 libraries, lazbuild should be too. So my guess is that you lazbuild is somehow still stuck on i386.

Can you check the architecture of your lazbuild project using the file command?

You are absolutely correct:
file Project1 gave:
Project1: Mach-O executable i386

After adding the correct options to lazbuilt:

lazbuild -B Project.lpi --ws=cocoa --cpu=x86_64 --os=darwin --compiler=/usr/local/lib/fpc/3.0.4/ppcx64

and now file Project1 gives:

Project1: Mach-O 64-bit executable x86_64

and 64bit 1-architecture libvol.dylib is found!

Conclusion: although project options have <TargetCPU Value="x86_64"/> I must specify target architecture as lazbuild's command line option

Thanks for help!! This case is so far solved. My next step is get what I've learned and go back to the original (large) project. If I can get dylibs correctly loaded there, this case is finally solved.

RednosePete

  • New Member
  • *
  • Posts: 17
Re: getprocaddress
« Reply #26 on: February 25, 2018, 01:04:59 pm »
An update: even though the target CPU family in project options is x86_64, building via Lazarus produces 32-bit app if Compiler Command is "$(CompPath)". When I change it to "/usr/local/lib/fpc/3.0.4/ppcx64", I get a 64-bit app. Perhaps this is something I should have known in the first place, isn't it.

Finally; the reason my application was unable to load a 64-bit dylib was that the application never was built for 64-bit platform. It took a bit too long for me to figure that out, and without your help I pretty sure would be still lost and confused. Why in earth I didn't check the architecture of my executables until rvk told me to do so :-[. I probably have to change my username to RedFacePete.
« Last Edit: February 25, 2018, 01:18:35 pm by RednosePete »

rvk

  • Hero Member
  • *****
  • Posts: 6594
Re: getprocaddress
« Reply #27 on: February 25, 2018, 01:19:04 pm »
An update: even though the target CPU family in project options is x86_64, building produces 32-bit app if Compiler Command is "$(CompPath)". When I change it to "/usr/local/lib/fpc/3.0.4/ppcx64", I get a 64-bit app. Perhaps this is something I should have known in the first place, isn't it.
Well, I think choosing x86_64 as Target CPU should/could have done that automatically for you. Although choosing a CPU target in the option, which the $(CompPath) compiler does not support, gets me a warning when pressing OK. Is this not the case in the Mac version?

Quote
Compiler "C:\dev\fpc\bin\i386-win32\fpc.exe" does not support target x86_64-win32

Quote
Finally; the reason my application was unable to load a 64-bit dylib was that the application never was built for 64-bit platform. It took a bit too long to figure that out, and without your help I pretty sure would be still lost and confused.
Yeah, I should have asked after the first post to check the arch with file :D
But I also just assumed a 64 bit version was created.

Glad it works now.

ChPr

  • Jr. Member
  • **
  • Posts: 52
Re: getprocaddress
« Reply #28 on: September 06, 2024, 10:49:15 am »
... Can you check the architecture of your lazbuild project using the file command?

Hello everybody,

I have much the same problem.
On MacOS, I want to link a library to my program.

Code: Pascal  [Select][+][-]
  1. function InstalleLib(FchLib: String): Boolean;
  2. var
  3.   Fch: String;
  4.   Menu, SousMenu: TMenuItem;
  5.   i, N, NbM, NoM, PosM: Integer;
  6. begin
  7.   Fch:= DirEXE;
  8.   Fch:= IncludeTrailingPathDelimiter(Fch+FchLib);
  9. {$IFDEF WINDOWS}
  10.   FchLib:= Fch+FchLib+'.dll';
  11. {$ENDIF}
  12. {$IFDEF LINUX}
  13.   FchLib:= Fch+'lib'+LowerCase(FchLib)+'.so';
  14. {$ENDIF}
  15. {$IFDEF DARWIN}
  16.   FchLib:= Fch+'lib'+LowerCase(FchLib)+'.dylib';
  17. {$ENDIF}
  18.   HndLib:= LoadLibrary(PChar(FchLib));
  19.   if HndLib <> 0 then
  20.   begin
  21.     Pointer(AddMenu):= GetProcAddress(HndLib, PChar('AddMenu'));
  22.     Pointer(EnvoiDirLib):= GetProcAddress(HndLib, 'EnvoiDirLib');
  23.     Pointer(ArticleEnBdD):= GetProcAddress(HndLib, 'ArticleEnBdD');
  24.     Pointer(MajStock):= GetProcAddress(HndLib, 'MajStock');
  25.     if (Pointer(AddMenu) <> nil)
  26.     and (Pointer(EnvoiDirLib) <> nil)
  27.     and (Pointer(ArticleEnBdD) <> nil)
  28.     and (Pointer(MajStock) <> nil) then
  29.     begin
  30.       EnvoiDirLib(PChar(Fch));         {Envoie le Dir de la BdD : .../Articles}
  31.       Menu:= TMenuItem.Create(Base.MenuPrinc);
  32.       PosM:= 1;                      {Position d'insertion des menus de la Lib}
  33.       N:= 0;{AddMenu(0) retourne le nom du menu à ajouter et le Nb de Sousmenu}
  34.       Menu.Caption:= String(AddMenu(N));              {Récupère le nom du menu}
  35.       SetLength(ListSousMenu, Length(ListSousMenu)+N);
  36.       NbM:= Base.MenuPrinc.Items.Count;            {Nombre de menus prédéfinis}
  37.       Base.MenuPrinc.Items.Insert(PosM, Menu);              {Insertion du menu}
  38.       for i:= 1 to N do                             {Création des N sous-menus}
  39.       begin
  40.         SousMenu:= TMenuItem.Create(Base.MenuPrinc);
  41.         ListSousMenu[High(ListSousMenu)-N+i]:= SousMenu;
  42.         NoM:= i;
  43.         SousMenu.ImageIndex:= i+11;   {11 = dernier indice des des menus fixes}
  44.         SousMenu.Caption:= string(AddMenu(NoM));
  45.         SousMenu.Enabled:= True;
  46.         SousMenu.Tag:= i;          {Mémo de l'indice du sous-menu dans son Tag}
  47.         SousMenu.OnClick:= @Base.ClickMenu;  {Affectation de la fonction Click}
  48.         Base.MenuPrinc.Items[PosM].Add(SousMenu);       {Installe le sous-menu}
  49.       end;
  50.       LibOK:= True;
  51.       Result:= True;
  52.     end
  53.     else
  54.       LibOK:= False;
  55.   end
  56.   else
  57.     LibOk:= False;
  58.   Result:= LibOK;
  59. end;

 I've done what was recommended above, i.e. not to leave a default value, I've put, both in the library parameters and in those of the program :
  •     Destination OS: Darwin
  •     CPU family: X86-64
  •     Target processor: ATHLON64
The library is found and, although the following test :
Code: Pascal  [Select][+][-]
  1. chpr@Mac-de-chpr Facturation % file FactDevEI
  2. FactDevEI: Mach-O 64-bit executable x86_64
shows that my architecture is indeed X86_64, "getProcAddress" always returns “nil”.

An idea of the problem ?

Sincerely.

Pierre.

 

TinyPortal © 2005-2018