Loading .so Files in Program lazarus / 66-Unix ---------------------------------------------------------------------- PatrickS · 2015-08-07 12:20 Dear Community, I have a Problem. At the moment I'am trying to load a shard lib into a lazarus prgramm. The *.so files is created also with lazarus but the Lib is not loaded (file exists). The Hardware is an BananaPi with armhf aritectur.  (fpc and lazarus are also running under armhf (debian wheezy)) Is there any solution or workaround to fix this? Or did anybody achieved something like tis befor? ---------------------------------------------------------------------- Leledumbo · 2015-08-07 12:28 Where's the library located? ---------------------------------------------------------------------- PatrickS · 2015-08-07 12:30 It is located in the source folder of the new project. Sorry I'am new to this forum. I'am using lazarus version 1.2.6 with the fpc-2.6.4 compiler using gtk2, the processor achitecture is armhf running with Bananian15.04 (Debian 7/Wheezy)). I'm trying to load a shared library in my new lazarus project using this (pseudo code): uses ...dynlibs... procedure UseDLL; type   TMyFunc=function (aInt:Integer; aStr: string):String; StdCall; var   MyLibC: TLibHandle= dynlibs.NilHandle;   MyFunc: TMyFunc;   FuncResult: string; begin   MyLibC := LoadLibrary('libc.so');   if MyLibC = dynlibs.NilHandle then Exit;  //DLL was not loaded successfully   MyFunc:= TMyFunc(GetProcedureAddress(MyLibC, 'MyFunc');   FuncResult:= MyFunc (5,'Test');  //Executes the function   if MyLibC <>  DynLibs.NilHandle then if FreeLibrary(MyLibC) then MyLibC:= DynLibs.NilHandle; the shared lib is also created on thiy computer system with lazarus, but it fails to load. But it is possible to load other libs which are not created by lazarus/fpc. ---------------------------------------------------------------------- Leledumbo · 2015-08-07 12:48 What does GetLoadErrorStr say? ---------------------------------------------------------------------- PatrickS · 2015-08-07 13:23 The file or could not be found or be opened, but the Files defintely exists. ( also the speeling is correct checked serveral times). I will recheck with some other files and will report Thank you four your help. Also tried with this: LoadLibrary('Path_toFile.so') does not work.... ---------------------------------------------------------------------- marcov · 2015-08-07 14:22 man ldconfig  and environment variable LD_LOAD_LIBRARY_PATH ---------------------------------------------------------------------- Leledumbo · 2015-08-07 16:42 What if you execute: Code: [Select]$ LD_LIBRARY_PATH=. ./yourappActually, under *nix shared libraries are meant to be loaded from static locations, e.g.: /usr[/local]/lib, but of course you can register another directories to be searched by the dynamic linker, which is what marco said. ---------------------------------------------------------------------- garlar27 · 2015-08-07 18:04 Are you passing the full path to the library? I have a proyect which uses dynlibs and runs in both OS windows and linux. Code: [Select]      LIBRARY_MYLIB_NAME := 'MyLib'; FMyLibHandle := dynlibs.LoadLibrary(TheLibrariesLocation + LIBRARY_MYLIB_NAME); LoadLibrary adds prefix "lib" if on Linux and add the appropiate extension (".so" on Linux and ".dll" on windows). And don't forget to use THE FULL PATHWAY. Otherwise it won't find the library. ---------------------------------------------------------------------- PatrickS · 2015-08-10 06:24 Hello, sorry for my late response. today I tried to load the libc.so in lazarus eith two differeten locations. Code: [Select]Hndl1:=LoadLibrary('libc.so'); S:=GetLoadErrorStr; Writeln(s);             //   S = 'usr/lib/arm-linux-gnueabihf/lib6.so: Ungültiger ELF-Header' Hndl2:=LoadLibrary('/root/Desktop/libc.so'); // here is a copy of libc.so S:=GetLoadErrorStr; Writeln(s); // same like before Hndl2:=LoadLibrary('/root/Desktop/own_lib.so'); // self created lib in lazarus S:=GetLoadErrorStr; Writeln(s);             //   S = 'root/Desktop/own_lib.so: Can not open the Shared-Object-File : File or Directory not found' The file and the directory exists, see atttachment. ---------------------------------------------------------------------- garlar27 · 2015-08-10 13:55 Do you have permissions to read / write in that folder? My gess is you don't or you shouldn't. I don't remember if the library needs execution permissions. The way we use it is like this: Code: [Select]LIBRARY_MYLIB_NAME := 'libMyLib';// We use the lib prefix because we want to have the "same" file name on Windows and Linux. Without extension thus is more cross-platform. TheLibrariesLocation := Application.Location;// = '/usr/UserName/MyApplication/' FMyLibHandle := dynlibs.LoadLibrary(TheLibrariesLocation + LIBRARY_MYLIB_NAME); ATM I'm not on Linux so I can't try your code. ---------------------------------------------------------------------- marcov · 2015-08-10 14:10 Why aren't you reading the default libc.so ? in /lib or so? ---------------------------------------------------------------------- PatrickS · 2015-08-11 11:15 Quote from: marcov on August 10, 2015, 04:10:55 pmWhy aren't you reading the default libc.so ? in /lib or so? I do not want to use this lib I just want to show that it is possible to load libs from the specified location, Quote from: garlar27 on August 10, 2015, 03:55:06 pmDo you have permissions to read / write in that folder? My gess is you don't or you shouldn't. I don't remember if the library needs execution permissions. The way we use it is like this: Code: [Select]LIBRARY_MYLIB_NAME := 'libMyLib';// We use the lib prefix because we want to have the "same" file name on Windows and Linux. Without extension thus is more cross-platform. TheLibrariesLocation := Application.Location;// = '/usr/UserName/MyApplication/' FMyLibHandle := dynlibs.LoadLibrary(TheLibrariesLocation + LIBRARY_MYLIB_NAME); ATM I'm not on Linux so I can't try your code. I set the permission to 777 with chmod 777 /path_to_file/own_lib.so so I should be able to read the file. also I running this program as root for testing so the permission should not be important because root is able to do what he wants. Is any other able to create a lib.so file in lazarus AND load this lib into a new program? <-- This is the main problem, that the self-build lib ( also with fpc an lazarus) can not be opened. Thank you for your ideas and the support! ---------------------------------------------------------------------- marcov · 2015-08-11 12:06 Quote from: PatrickS on August 11, 2015, 01:15:09 pmQuote from: marcov on August 10, 2015, 04:10:55 pmWhy aren't you reading the default libc.so ? in /lib or so? I do not want to use this lib I just want to show that it is possible to load libs from the specified location, But an application that can load libraries is already linked to libc. (just run ldd ./yourprogram) Try a different library to test such theories than libc. ---------------------------------------------------------------------- PatrickS · 2015-08-12 05:47 Hello together; here is an example what I'm trying. This is the source-Code of my Programm which should load the shard-lib which is created in the second code part. Code: [Select] program project1; {$mode objfpc}{$H+} uses   {$IFDEF UNIX}{$IFDEF UseCThreads}   cthreads,   {$ENDIF}{$ENDIF}   Classes,dynlibs   { you can add units after this }; type  TPatrick_Add=function(a,b:integer):integer; var mylib:TLibHandle = dynlibs.NilHandle;     MyFunc: TPatrick_Add;     result:integer; begin      Writeln('Hello');      mylib:=LoadLibrary('C:\Users\USERNAME\Desktop\Proba\project1_dll. '+sharedsuffix);      if mylib = dynlibs.NilHandle then Writeln('Problem found')                                   else begin                                     Writeln('OK');                                     MyFunc:=TPatrick_Add(dynlibs.GetPr ocedureAddress(mylib,'Patrick_Add'));                                     if MyFunc<>nil then Writeln('Func Found');                                     //Writeln(MyFunc(1,1));                                   end;      Writeln(GetLoadErrorStr);      Readln; end. This is my shared lib /dll (under Windows): Code: [Select]library project1_dll; {$mode objfpc}{$H+} uses   Classes   { you can add units after this };   function Patrick_Add(a,b:integer):integer;cdecl;export;   begin       Patrick_Add:=a+b;   end; exports Patrick_Add; begin end. If everything is created under windows every thing runs great! ( See attachment) if the lib is created under linux (armhf) it is not posible to load the lib. May you see any problems in the code? (Spelling of the path & shared lib is correct). ---------------------------------------------------------------------- garlar27 · 2015-08-12 13:36 I don't see any obvious problem and it is more or less what I'm using on Linux and windows. I think the problem might be in dynlibs ARM's implementation. I know it's an example but (just in case) I have a two sugestions: 1- It is better to get the library location from a config file or the "Application.Location" or te command line (using "IncludeTrailingBackslash(ExtractFilePath(ParamStr(0)))"). Which are more cross-platform. NOTE that "Application.Location" and "ParamStr(0)" do not return the right folder on some OS (on windows and linux works fine  ). 2- I would change the line Code: [Select]mylib:=LoadLibrary('C:\Users\USERNAME\Desktop\Proba\proj ect1_dll.'+sharedsuffix);for Code: [Select]mylib:=LoadLibrary('C:\Users\USERNAME\Desktop\Proba\proj ect1_dll');The extension is not needed and again this is more cross- platform. ---------------------------------------------------------------------- garlar27 · 2015-08-12 13:40 If ZEOS DBO component can run on ARM you should be able to use dynlib on ARM too!!! ---------------------------------------------------------------------- marcov · 2015-08-12 14:00 Try export LD_LIBRARY_PATH=/path/to/dll;%LD_LIBRARYPATH% and then run your library. Under *nix there is a list of paths that may contain libraries. (usually /lib, /usr/lib and /usr/local/lib). The list is maintained via the ldconfig command, but an user specific  LD_LIBRARY_PATH can overrides/add to it. ---------------------------------------------------------------------- PatrickS · 2015-08-14 10:47 Hallo, I tried the command with  Quote from: marcov on August 12, 2015, 04:00:36 pmexport LD_LIBRARY_PATH=/path/to/dll;%LD_LIBRARYPATH% but still nothing happens. Still not possible to load self created lib (created with pascal) in programm. all other libs work, also libs which are created with C. It MUST be an error of the compiler because everything is running, but not under armhf! Did somebody checked ut the examles which i send with before under armhf? ---------------------------------------------------------------------- marcov · 2015-08-14 11:56 That should be a :  btw, not a ;   my bad. No I haven't investigated, I don't have the time to mimick the circumstances atm, and in general avoid creating shared libs on *nix, so it is not really my area of expertise. ---------------------------------------------------------------------- garlar27 · 2015-08-14 13:34 Quote from: marcov on August 14, 2015, 01:56:06 pmThat should be a :  btw, not a ;   my bad. No I haven't investigated, I don't have the time to mimick the circumstances atm, and in general avoid creating shared libs on *nix, so it is not really my area of expertise. I didn't have the time to test your code too. I'm writing this during my job time and I'm far behind schedule, thus isn't much what I can do ATM and near future. But we use libraries (with dynamic and static linking and currently I'm moving everything to the dynamic way) on Linux and windows. We are connecting to hardware and third-party servers trhough our own libraries and everything is working smoothly with same code on both OSes and without using IFDEFs. AFAICS it can be caused by:   1- something silly, like file name / path miss spelled.   2- something more serioius like a difference on ARM's Linux which could cause a problem with FPC's dynlib.pas (least probable). You can check point 2 easily by trying to run an app with ZEOS which uses dynlib to connect to DB. Lets say if youinstall SQLite3 on your ARM device and try to open or create a new SQLite DB using TZConnection. If no error then everything's great. you also can avoid instaling SQLite-3 and copy the library to your test proyect folder an try the following code : Put a TZConnection, a TOpenDialog, and a TButton on a form and a put this code inside the TButton.OnClick event: Code: [Select]   if OpenDialog1.Execute then begin       ZConnection1.LibraryLocation := OpenDialog1.FileName;       ZConnection1.Database := Application.Location+'test.db';       ZConnection1.Protocl := 'sqlite-3';       ZConnection1.Connect;    end; Execute it and select the sqlite 3 library file from the dialog and press OK button. if everything is fine a new file with the name "test.db" will appear in the same folder as the binary is. ---------------------------------------------------------------------- marcov · 2015-08-14 13:53 Another thing to try is passing an absolute path. But I avoided pascal generated shared libs, and installed other libs in their directories and registered any new library directories with "ldconfig". ---------------------------------------------------------------------- garlar27 · 2015-08-14 20:41 Quote from: marcov on August 14, 2015, 03:53:28 pmAnother thing to try is passing an absolute path. But I avoided pascal generated shared libs, and installed other libs in their directories and registered any new library directories with "ldconfig". And that's the right way!! ---------------------------------------------------------------------- PatrickS · 2015-08-19 12:21 I tried all of this but the problem still exists.... Probably an error of the compiler. Please can anybody verify this problem before a bug report will be generated. Architecure is armhf compiler 2.6.4  (debian wheezy) ( Pakages is in backports) also with the compiler 3.1.1 this error occurs. Best regards Patrick ---------------------------------------------------------------------- garlar27 · 2015-08-20 12:31 Now I'm on Linux trying your code but I cant compile the library because a weird error (Error: Illegal parameter: -WR). It's not in your code but in the project config, I think. I never had this error compiling and I can't find that parameter.... ---------------------------------------------------------------------- garlar27 · 2015-08-20 13:06 Quote from: garlar27 on August 20, 2015, 02:31:19 pmNow I'm on Linux trying your code but I cant compile the library because a weird error (Error: Illegal parameter: -WR). It's not in your code but in the project config, I think. I never had this error compiling and I can't find that parameter.... My bad, I found it. The attached example runs on my Ubuntu 10.04, compiled using FPC 2.6.2 and an old Lazarus. No need to register anything to OS just compile the library, the tester project and run it!! Is weird that I had to do this Code: [Select]const    PROJECT1_DLL_LIBRARY_NAME = {$IFDEF UNIX}'lib'+{$ENDIF}'project1_dll.' + SharedSuffix;    PROJECT1_DLL_LIBRARY_PROC_PATRICK_ADD = 'Patrick_Add'; although I was telling you it wasn't necessary (to add the prefix and the suffix). My projects do not have it!!! If you keep having problems, then I think you should report it to the bug tracker. ---------------------------------------------------------------------- garlar27 · 2015-08-20 13:08 Sorry, forgot to attach the files.... ---------------------------------------------------------------------- PatrickS · 2015-08-21 13:00 Thank you for yout try. Here is also a link from a forum, which also handles with this topic: http://free-pascal-general.1045716.n5.nabble.com/shared-library-on- arm-linux-raspberry-pi-td5719653.html I already started a ticket in Bugtracker of fpc. 28545