Recent

Author Topic: GetModuleFileName - Linux Equivalen  (Read 459 times)

FOV_2001

  • Newbie
  • Posts: 2
GetModuleFileName - Linux Equivalen
« on: September 10, 2019, 12:32:49 am »
Hi Friend of the Forum,

After searching as far as I know, quite strongly, I have no choice but to ask for your help and annoy them with something perhaps extremely simple.

I have been running an application developed in Delphi 2010 for a long time under Windows, which works acceptably well.

For platform reasons, fundamentally the new ones, smaller and cheaper, I am trying to translate it into Multiplatform, so far quite reasonably Fast.

The problem I encounter is with GetModuleFileName, a function that returns the name of the Library / Application that I am running.

I can't find a way to find the Linux equivalent.

Why do I need it? So that when I run Logs, which I have separated by Library, I can generate the name of the corresponding log file.

This function is in a general Unit, which is called with several DLL / SOs that use common functions / procedures.

Will it be possible to help me in this regard?

From already thank you very much
« Last Edit: September 10, 2019, 12:40:07 am by FOV_2001 »

jamie

  • Hero Member
  • *****
  • Posts: 1922
Re: GetModuleFileName - Linux Equivalen
« Reply #1 on: September 10, 2019, 03:56:32 am »
I don't know much about Linux but I am sure the TApplication.FileName and Location maybe give you some fruit..

 that is will work in a application file. as for libraries I am not so sure about that one.

 you could also look at "paramstr" that should be the command line info which I believe also includes the app name

PascalDragon

  • Hero Member
  • *****
  • Posts: 573
  • Compiler Developer
Re: GetModuleFileName - Linux Equivalen
« Reply #2 on: September 10, 2019, 11:56:30 am »
As jamie wrote for the path of the main binary you can use TApplication.Filename or TApplication.Location or if you don't use a GUI you can use ParamStr(0). Alternatively you can (at least no Linux) check what file the symbolic link /proc/self/exe is pointing to.

For libraries things are more complicated. At least on Linux you can parse /proc/self/maps and find out the correct address range of your current instruction address or so. On other *nix systems things might be completely different however.

FOV_2001

  • Newbie
  • Posts: 2
Re: GetModuleFileName - Linux Equivalen
« Reply #3 on: September 10, 2019, 03:40:19 pm »
As jamie wrote for the path of the main binary you can use TApplication.Filename or TApplication.Location or if you don't use a GUI you can use ParamStr(0). Alternatively you can (at least no Linux) check what file the symbolic link /proc/self/exe is pointing to.

For libraries things are more complicated. At least on Linux you can parse /proc/self/maps and find out the correct address range of your current instruction address or so. On other *nix systems things might be completely different however.

Hi Guys, thaks for your reply.

TApplication.FileName has a problema thar if I call it from a Library, it return us the name of the Host application (the caller) not the library name.

I'm continuing searching.

varianus

  • New Member
  • *
  • Posts: 17
Re: GetModuleFileName - Linux Equivalen
« Reply #4 on: September 10, 2019, 08:22:24 pm »
I've found this function in my sources library. I do not remember where I've copied it from (maybe Double Commander sources), hope it is what you are looking for

Code: Pascal  [Select]
  1. uses dl;
  2.  
  3. function mbGetModuleName(Address: Pointer): String;
  4. const
  5.   Dummy: Boolean = False;
  6. var
  7.   dlinfo: dl_info;
  8. begin
  9.   if Address = nil then Address:= @Dummy;
  10.   FillChar({%H-}dlinfo, SizeOf(dlinfo), #0);
  11.   if dladdr(Address, @dlinfo) = 0 then
  12.     Result:= EmptyStr
  13.   else begin
  14.     Result:= UTF8Encode(dlinfo.dli_fname);
  15.   end;
  16. end;

PascalDragon

  • Hero Member
  • *****
  • Posts: 573
  • Compiler Developer
Re: GetModuleFileName - Linux Equivalen
« Reply #5 on: September 11, 2019, 09:38:01 am »
TApplication.FileName has a problema thar if I call it from a Library, it return us the name of the Host application (the caller) not the library name.
That's what we both already said...

I've found this function in my sources library. I do not remember where I've copied it from (maybe Double Commander sources), hope it is what you are looking for

Code: Pascal  [Select]
  1. uses dl;
  2.  
  3. function mbGetModuleName(Address: Pointer): String;
  4. const
  5.   Dummy: Boolean = False;
  6. var
  7.   dlinfo: dl_info;
  8. begin
  9.   if Address = nil then Address:= @Dummy;
  10.   FillChar({%H-}dlinfo, SizeOf(dlinfo), #0);
  11.   if dladdr(Address, @dlinfo) = 0 then
  12.     Result:= EmptyStr
  13.   else begin
  14.     Result:= UTF8Encode(dlinfo.dli_fname);
  15.   end;
  16. end;

Oh, that's a good one! :D It might not be POSIX standard, but it seems to exist at least on macOS as well. Other *nix platforms would need to be checked...

Also here is a potential convenience function:
Code: Pascal  [Select]
  1. function GetCurrentModuleName: String;
  2. begin
  3.   Result := mbGetModuleName(get_caller_addr(get_frame));
  4. end;
I've not tested it, but it should return the name of the library that is calling GetCurrentModuleName.

For Windows an equivalent function would simply use HInstance of the current library together with GetModuleFileName. :)

MarkMLl

  • Jr. Member
  • **
  • Posts: 77
Re: GetModuleFileName - Linux Equivalen
« Reply #6 on: September 11, 2019, 08:52:57 pm »
Oh, that's a good one! :D It might not be POSIX standard, but it seems to exist at least on macOS as well. Other *nix platforms would need to be checked...

I agree: very nice. I usually wrap a dynamically-loaded library in an object, and that's definitely something I'll investigate adding.

One thing that I usually do is this in the .lpr:

Code: Pascal  [Select]
  1. EXPORTS ModuleAboutText;
  2.  
  3. CONST   projectName= {$I %FILE% } ;
  4.  
  5. VAR     projectSuffix: STRING= '';      (* Typically from a .ini or .conf file  *)
  6.  
  7. {$R *.res}
  8.  

That makes sure that you've got an invariant name that you can use to make sure that a renamed executable or library isn't about to trample over an API even if a binary has been renamed.

MarkMLl