Recent

Author Topic: Alternative solution of my requirement for OSes other than Windows  (Read 608 times)

chenyuchih

  • Jr. Member
  • **
  • Posts: 72
Hello,

I wrote a dll, which loads other data files the same directory as the dll. In case some conditions that relative path doesn't work, I use the following way to get the location of the dll:

ExtractFilePath(SysUtils.GetModuleName(HINSTANCE))+SysUtils.PathDelim

But the functions "GetModuleName" and "HINSTANCE" are Windows only, how to know the library(so, dylib) location in the library itself for other OSes?

If there's any cross platform alternative, it would make my library more portable and easy to use.

Best Regards,
ChenYuChih

hrayon

  • Full Member
  • ***
  • Posts: 100
Re: Alternative solution of my requirement for OSes other than Windows
« Reply #1 on: April 23, 2019, 12:50:16 pm »
Hi!
There are some good tips here about cross platform:
http://wiki.lazarus.freepascal.org/Multiplatform_Programming_Guide

You can put the application files in several places, but there are some standard folders among the different operating systems that are abstracted by Lazarus to help you.
Maybe you have to think a little differently (or not, I don't know the details of your application) about where to put and find the files.

dbannon

  • Hero Member
  • *****
  • Posts: 603
    • tomboy-ng, a rewrite of the classic Tomboy
Re: Alternative solution of my requirement for OSes other than Windows
« Reply #2 on: April 23, 2019, 02:15:54 pm »
Because Linux has a quite small list of places where libraries are stored, its normally best practice try one after the other until you find the file you are looking for.

But i did  resort to -

Code: Pascal  [Select]
  1. RunCommand('/bin/bash',['-c','ldconfig -p | grep hunspell'], FullName)

When I did not care what version of a library was there and it was named quite inconsistency between distributions.

Davo
Lazarus 1.8, Linux (and reluctantly Win10, OSX)
My Project - https://github.com/tomboy-notes/tomboy-ng

chenyuchih

  • Jr. Member
  • **
  • Posts: 72
Re: Alternative solution of my requirement for OSes other than Windows
« Reply #3 on: April 24, 2019, 01:56:26 am »
Well, I wish my program could run without install/uninstall. The users can extract the zip file to a non-system folder and use directly. If they don't need it anymore, the whole remove procedure is just a "delete". So it's important for me to get the path information of the executable and libraries.

As my first post in this topic, I would like to know the path of library itself because the library might be used by other people's programs, which may not always be the same location as my lib. I've implemented it in Windows and wonder if the same idea is possible in other OSes. From the link that hrayon provide, it looks different OSes have their own rules. Is there really no equivalent way for this?

Thanks for your reply!  O:-)

ChenYuChih
« Last Edit: April 24, 2019, 01:59:07 am by chenyuchih »

dbannon

  • Hero Member
  • *****
  • Posts: 603
    • tomboy-ng, a rewrite of the classic Tomboy
Re: Alternative solution of my requirement for OSes other than Windows
« Reply #4 on: April 24, 2019, 03:15:05 am »
Sorry chenyuchih, perhaps I was too brief. Longer version.

As a general rule, we don't put libraries along side an executable like windows does because Linux really tries to enforce sharing. So, if you are looking for a preinstalled "general purpose" library that's been installed properly, its likely to be in one of that short list of locations. So, if you know the name, search there.

Some applications do keep their own private libraries tucked away where only they will find them, thats OK, if they are so tucked away, you probably should not be using them anyway.

If you use a tool like strace you will see that most applications start up trying to open desired libraries, one dir after another until it finds what it needs.  Its sounds like a laborous process but its the way it works !

The other way, using ldconfig ?  That snipit of code I posted was too brief, if you need to take that approach, here is more of it ....

Code: Pascal  [Select]
  1. uses LazUTF8, SysUtils, {$ifdef linux}Process,{$endif} LazFileUtils, Forms, lazlogger;
  2. ......
  3. function THunspell.FindLibrary(out FullName : ANSIString):boolean;
  4. var
  5.     {$ifdef LINUX} I : integer = 1; {$endif}
  6.     {$ifndef LINUX}
  7.     Info : TSearchRec;
  8.     Mask : ANSIString;
  9.     {$endif}
  10. begin
  11.     Result := False;
  12.     {$IFDEF LINUX}
  13.     // Assumes ldconfig always returns same format, better than searching several dirs
  14.     if RunCommand('/bin/bash',['-c','ldconfig -p | grep hunspell'], FullName) then begin
  15.         while UTF8Pos(' ', FullName, I) <> 0 do inc(I);
  16.         if I=1 then exit();
  17.         UTF8Delete(FullName, 1, I-1);
  18.         UTF8Delete(FullName, UTF8Pos(#10, FullName, 1), 1);
  19.         Result := True;
  20.     end else
  21.         if RunCommand('/bin/bash',['-c','/sbin/ldconfig -p | grep hunspell'], FullName) then begin
  22.             while UTF8Pos(' ', FullName, I) <> 0 do inc(I);
  23.             if I=1 then exit();
  24.             UTF8Delete(FullName, 1, I-1);
  25.             UTF8Delete(FullName, UTF8Pos(#10, FullName, 1), 1);
  26.             Result := True;
  27.         end;
  28.     {$ENDIF}              
  29. ......
  30.  

Davo
Lazarus 1.8, Linux (and reluctantly Win10, OSX)
My Project - https://github.com/tomboy-notes/tomboy-ng

chenyuchih

  • Jr. Member
  • **
  • Posts: 72
Re: Alternative solution of my requirement for OSes other than Windows
« Reply #5 on: April 24, 2019, 03:33:25 am »
Thank you for your explanation, dbannon!   :)

I lack for knowledge of OSes other than Windows and don't have much cross platform development experience before. Now I know that the design ideas of OSes are different and how simple my thought is. I will investigate your example and learn more about it.

Thanks again!

ChenYuChih

hrayon

  • Full Member
  • ***
  • Posts: 100
Re: Alternative solution of my requirement for OSes other than Windows
« Reply #6 on: April 24, 2019, 07:07:33 pm »
Hello!

I would try another approach.
You would use the GetAppConfigDirUTF8 function and save a configuration file there that will contains the path of your dll.
It would be a file of a few bytes. I don't see it as a problem if it becomes orphaned when the application is deleted.
That function takes care of differences between operating systems.

PascalDragon

  • Hero Member
  • *****
  • Posts: 518
  • Compiler Developer
Re: Alternative solution of my requirement for OSes other than Windows
« Reply #7 on: April 25, 2019, 11:51:33 am »
Hello,

I wrote a dll, which loads other data files the same directory as the dll. In case some conditions that relative path doesn't work, I use the following way to get the location of the dll:

ExtractFilePath(SysUtils.GetModuleName(HINSTANCE))+SysUtils.PathDelim

But the functions "GetModuleName" and "HINSTANCE" are Windows only, how to know the library(so, dylib) location in the library itself for other OSes?

If there's any cross platform alternative, it would make my library more portable and easy to use.

Best Regards,
ChenYuChih
Please note that it's considered bad form on most platforms to have other files together with libraries. E.g. on Linux if they're resource files they're usually located in /usr/share and if they're configuration files they're either in /etc or ~/.config (depending on whether they're global or local) as libraries reside in /lib or /usr/lib. Similar conventions apply to macOS. Even on Windows configuration files are supposed to be in %APPDATA% or %PROGRAMDATA%.
So take these conventions under advisement and retrieve the paths using platform specific functionality while using ifdefs.
For configuration files you can also use GetAppConfigDirUTF8 as hrayon mentioned.