Recent

Author Topic: Loading .so Files in Program  (Read 14761 times)

PatrickS

  • New member
  • *
  • Posts: 9
Loading .so Files in Program
« on: August 07, 2015, 02:20:52 pm »
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?
« Last Edit: August 07, 2015, 02:26:30 pm by PatrickS »

Leledumbo

  • Hero Member
  • *****
  • Posts: 8111
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: Loading .so Files in Program
« Reply #1 on: August 07, 2015, 02:28:17 pm »
Where's the library located?

PatrickS

  • New member
  • *
  • Posts: 9
Re: Loading .so Files in Program
« Reply #2 on: August 07, 2015, 02:30:44 pm »
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.
« Last Edit: August 07, 2015, 02:39:08 pm by PatrickS »

Leledumbo

  • Hero Member
  • *****
  • Posts: 8111
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: Loading .so Files in Program
« Reply #3 on: August 07, 2015, 02:48:26 pm »
What does GetLoadErrorStr say?

PatrickS

  • New member
  • *
  • Posts: 9
Re: Loading .so Files in Program
« Reply #4 on: August 07, 2015, 03:23:33 pm »
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....
« Last Edit: August 07, 2015, 03:36:16 pm by PatrickS »

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 7493
Re: Loading .so Files in Program
« Reply #5 on: August 07, 2015, 04:22:52 pm »
man ldconfig 

and environment variable LD_LOAD_LIBRARY_PATH

Leledumbo

  • Hero Member
  • *****
  • Posts: 8111
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: Loading .so Files in Program
« Reply #6 on: August 07, 2015, 06:42:38 pm »
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

  • Hero Member
  • *****
  • Posts: 618
Re: Loading .so Files in Program
« Reply #7 on: August 07, 2015, 08:04:19 pm »
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

  • New member
  • *
  • Posts: 9
Re: Loading .so Files in Program
« Reply #8 on: August 10, 2015, 08:24:19 am »
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.
« Last Edit: August 10, 2015, 08:44:03 am by PatrickS »

garlar27

  • Hero Member
  • *****
  • Posts: 618
Re: Loading .so Files in Program
« Reply #9 on: August 10, 2015, 03:55:06 pm »
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

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 7493
Re: Loading .so Files in Program
« Reply #10 on: August 10, 2015, 04:10:55 pm »
Why aren't you reading the default libc.so ? in /lib or so?

PatrickS

  • New member
  • *
  • Posts: 9
Re: Loading .so Files in Program
« Reply #11 on: August 11, 2015, 01:15:09 pm »
Why 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,

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.

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

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 7493
Re: Loading .so Files in Program
« Reply #12 on: August 11, 2015, 02:06:46 pm »
Why 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

  • New member
  • *
  • Posts: 9
Re: Loading .so Files in Program
« Reply #13 on: August 12, 2015, 07:47:50 am »
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.GetProcedureAddress(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

  • Hero Member
  • *****
  • Posts: 618
Re: Loading .so Files in Program
« Reply #14 on: August 12, 2015, 03:36:06 pm »
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\project1_dll.'+sharedsuffix);for
Code: [Select]
mylib:=LoadLibrary('C:\Users\USERNAME\Desktop\Proba\project1_dll');The extension is not needed and again this is more cross-platform.