Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2025-01

External library name

10 messages · 6 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Hairy Pixels

I see this pattern in C translated header often but I’ve honestly never understood it entirely.

Why does this “cDllName" need to be added to every single function which you could just use {$linklib xxxx}?

Furthermore, I’m not even aware that it’s possible to tell the linker that you want to search for a specific symbol in a specific library so I wonder does the external library name actually do anything or does it just call {$linklib} behind the scenes? I’m on macOS and I don’t know how the linkers work on other platforms so maybe that’s relevant too.

============================================================

const
  cDllName = {$IFDEF WINDOWS}
                     {$IFDEF DEBUG}
                             {$IFDEF WIN64} 'libraylib64-debug.dll' {$ELSE}
'libraylib32-debug.dll' {$ENDIF}
                     {$ELSE}
                            {$IFDEF WIN64} 'libraylib64.dll' {$ELSE}
'libraylib32.dll' {$ENDIF}
                     {$ENDIF}
             {$IFEND}
             {$IFDEF DARWIN} 'libraylib.dylib' {$IFEND}
             {$IFDEF LINUX} 'libraylib.so' {$IFEND};
procedure InitWindow(aWidth : Integer; aHeight : Integer; aTitle :
PAnsiChar); cdecl; external cDllName;
function  WindowShouldClose() : Boolean; cdecl; external cDllName;
procedure CloseWindow(); cdecl; external cDllName;

Regards,
Ryan Joseph

Reply by email

Adriaan van Os
to Hairy Pixels
Hairy Pixels wrote 5 lines
I see this pattern in C translated header often but I’ve honestly never understood it entirely. Why does this “cDllName" need to be added to every single function which you could just use {$linklib xxxx}?

This is a habit from the WIndows and Delphi world. In a one-levell namespace on MacOS, the dll name is superflouous. Note that ObjC symbols are always global ,which implies a one-level namespace.

Regards,

Adriaan van Os

Reply by email

Hairy Pixels
to Adriaan van Os

On Jan 5, 2025 at 11:53:36 AM, Adriaan van Os via fpc-pascal <

Show quoted text 7 lines
wrote: This is a habit from the WIndows and Delphi world. In a one-levell namespace on MacOS, the dll name is superflouous. Note that ObjC symbols are always global ,which implies a one-level namespace.

what do you mean a one level namespace?

I thought the idea of external names is that you could resolve name conflicts. Like if you had “exit” declared in 2 libraries can they both be linked together in one program using the external name? I’m curious about this though because I’ve never seen a way to do that with a linker, all you can ever do is specify libraries then the linker does all the work and if there are duplicates you get an error, end of story.

Regards,
Ryan Joseph

Reply by email

Jonas Maebe
to Hairy Pixels
Hairy Pixels wrote 16 lines
On Jan 5, 2025 at 11:53:36 AM, Adriaan van Os via fpc-pascal < > wrote: > This is a habit from the WIndows and Delphi world. In a one-levell > namespace on MacOS, the dll name > is superflouous. Note that ObjC symbols are always global ,which > implies a one-level namespace. what do you mean a one level namespace? I thought the idea of external names is that you could resolve name conflicts. Like if you had “exit” declared in 2 libraries can they both be linked together in one program using the external name? I’m curious about this though because I’ve never seen a way to do that with a linker, all you can ever do is specify libraries then the linker does all the work and if there are duplicates you get an error, end of story.

That is exactly what namespaces mean.

On Windows, every DLL has its own namespace. I.o.w., the external symbol's mangled name is in part determined by the DLL it gets imported from, and in part by the symbol name itself.

Most Unix platforms use a single-level namespace, where the name of the library is irrelevant and all external symbols' names only depend on the symbol name. If multiple libraries export the same symbol, generally the one of the last one loaded gets used (when manually looking up a symbol address at run time, you have more options). Of course, programming language themselves can still use namespaces themselves (e.g. Pascal units and C++ namespaces).

That said, Darwin also uses two-level namespaces:
https://blog.darlinghq.org/2018/07/mach-o-linking-and-loading-tricks.html#two-level-symbol-namespace . However, it does not do this through name mangling. The linker simply encodes in the generated binary in which library/framework it found the symbol at link time. Then, at run time, the dynamic linker will only look for that symbol in that specific library (unless you force a flat/single namespace through an environment variable).

However, as Adriaan also mentioned, an exception to this is Objective-C, which has its own name-based resolution logic. And having the same Objective-C class defined in multiple files, or having multiple categories adding the same method to the same class, will result in a random one getting picked at run time. And that results in real-world problems:
https://steamcommunity.com/app/335620/eventcomments/4843147760499908525?snr=1_2108_9__2107&ctp=2#c4840896974229538203

Jonas

Reply by email

Hairy Pixels
to Jonas Maebe

On Jan 5, 2025 at 4:43:39 PM, Jonas Maebe via fpc-pascal <

Show quoted text 11 lines
wrote: That said, Darwin also uses two-level namespaces: https://blog.darlinghq.org/2018/07/mach-o-linking-and-loading-tricks.html#two-level-symbol-namespace . However, it does not do this through name mangling. The linker simply encodes in the generated binary in which library/framework it found the symbol at link time. Then, at run time, the dynamic linker will only look for that symbol in that specific library (unless you force a flat/single namespace through an environment variable).

Thank you for your very detailed response.

It sounds like maybe the external library name is only useful for DLLs and maybe the Darwin two level namespaces?

Regards,
Ryan Joseph

Reply by email

Tomas Hajny
to Hairy Pixels
Hairy Pixels wrote 18 lines
On Jan 5, 2025 at 4:43:39 PM, Jonas Maebe via fpc-pascal wrote: > That said, Darwin also uses two-level namespaces: > https://blog.darlinghq.org/2018/07/mach-o-linking-and-loading-tricks.html#two-level-symbol-namespace > . However, it does not do this through name mangling. The linker > simply > encodes in the generated binary in which library/framework it found > the > symbol at link time. Then, at run time, the dynamic linker will only > look for that symbol in that specific library (unless you force a > flat/single namespace through an environment variable). Thank you for your very detailed response. It sounds like maybe the external library name is only useful for DLLs and maybe the Darwin two level namespaces?

As you might have noticed, it's simply a more general solution allowing to cover all target platforms supporting dynamic libraries in a more or less equal way.

Tomas

Reply by email

Hairy Pixels
to Tomas Hajny
Tomas Hajny wrote
As you might have noticed, it's simply a more general solution allowing to cover all target platforms supporting dynamic libraries in a more or less equal way.

Yeah if DLLs have their own namepace and $LINKLIB doesn’t propagate to all external functions in the unit then I guess the functions won’t link when a DLL is used.

Regards,
Ryan Joseph

Reply by email

Marco van de Voort
to Jonas Maebe: That is exactly what namespaces mean. On Windows, every DLL has its own namespace.…

Op 5-1-2025 om 10:43 schreef Jonas Maebe via fpc-pascal:

Show quoted text 9 lines
That said, Darwin also uses two-level namespaces: https://blog.darlinghq.org/2018/07/mach-o-linking-and-loading-tricks.html#two-level-symbol-namespace . However, it does not do this through name mangling. The linker simply encodes in the generated binary in which library/framework it found the symbol at link time. Then, at run time, the dynamic linker will only look for that symbol in that specific library (unless you force a flat/single namespace through an environment variable).

(.. and windows require the DLL to be present when linking, so can't use this, thus requires the extra information)

Reply by email

Marco van de Voort
to Marco van de Voort

Op 5-1-2025 om 13:23 schreef Marco van de Voort via fpc-pascal:

Show quoted text 16 lines
Op 5-1-2025 om 10:43 schreef Jonas Maebe via fpc-pascal: > > > That said, Darwin also uses two-level namespaces: > https://blog.darlinghq.org/2018/07/mach-o-linking-and-loading-tricks.html#two-level-symbol-namespace > . However, it does not do this through name mangling. The linker > simply encodes in the generated binary in which library/framework it > found the symbol at link time. Then, at run time, the dynamic linker > will only look for that symbol in that specific library (unless you > force a flat/single namespace through an environment variable). (.. and windows require the DLL to be present when linking, so can't use this, thus requires the extra information)

Oops: should have been "Windows DOESN'T require the DLL to be present....

Reply by email

Tony Whyman
to Hairy Pixels: Yeah if DLLs have their own namepace and $LINKLIB doesn’t propagate to all external…

Having stumbled over this problem last year, I now have a very simple rule (and which seems to work).

If you are linking with an external static library (e.g. libssl.a) then you omit the external library name on each function call, but must include a $LINKLIB e.g. ($LINKLIB ssl.a}.

If you are linking with an external shared  library (e.g. libssl-3-x64.dll) then you must explicitly provide the external library name on each function call so that the loader knows which library to look in. Note. No $LINKLIB directive.

Hairy Pixels wrote 16 lines
On Jan 5, 2025 at 6:45:49 PM, Tomas Hajny wrote: > As you might have noticed, it's simply a more general solution allowing > to cover all target platforms supporting dynamic libraries in a more or > less equal way. Yeah if DLLs have their own namepace and $LINKLIB doesn’t propagate to all external functions in the unit then I guess the functions won’t link when a DLL is used. Regards,     Ryan Joseph _______________________________________________ fpc-pascal maillist https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Reply by email