Recent

Author Topic: Avoiding duplicate symbols across packages (defining weak symbols)  (Read 500 times)

Khrys

  • Sr. Member
  • ****
  • Posts: 256
I'm using multiple statically-linked C libraries (in separate packages) in the same project. For maximum compatibility (i.e. to avoid having to install yet another VC++ redistributable) I'm linking against  msvcrt.dll  on Windows. It's a legacy component, but for my purposes it's sufficient.

There is one caveat, however - it doesn't define  atexit,  which is used by the C library code. There's the Microsoft equivalent  _onexit,  so it'd be trivial to just declare a shim function:

Code: Pascal  [Select][+][-]
  1. function onexit(func: pcvoid): cint; cdecl; external name '_onexit';
  2.  
  3. function atexit(func: pcvoid): cint; cdecl; public name 'atexit';
  4. begin
  5.   Result := onexit(func);
  6. end;

But then the question becomes where to place this definition:
  • Within each project: Inelegant, would like to avoid such boilerplate
  • Within each package: Only works if exactly one such package is used in a project, because otherwise the  atexit  symbol is defined multiple times and the linker complains
I've also tried marking the  atexit  symbol as weak by implementing it in C with GCC's  __attribute__((weak)),  but then FPC's internal linker aborts because it can't recognize the symbol's type.

So far it seems like the only viable option is to create a static library (e.g.  libmsvcrt_shim.a) containing the  atexit  definition and link against that, because I know from prior experience that FPC aggressively deduplicates  {$linklib}  directives.

Any other suggestions?   :(

Thaddy

  • Hero Member
  • *****
  • Posts: 17418
  • Ceterum censeo Trumpum esse delendum (Tnx Charlie)
Re: Avoiding duplicate symbols across packages (defining weak symbols)
« Reply #1 on: May 29, 2025, 01:38:13 pm »
The shim should point to AddExitProc() or if you want (not recommended) to the exitProc entry point in system.
You need to route the C code to the Pascal equivalent.  The Pascal system must be able to comply and exitproces are, well, exitprocs. You can' t mix them. You must make them point to the same entry point.
I remember a similar situation about 25 years ago.(with Delphi)
The C code will not be executed otherwise. This is a case of:"There can be only one".(Exit)
The C code doesn't mind to use the Pascal ExitProc,because it is basically the same.
« Last Edit: May 29, 2025, 01:56:02 pm by Thaddy »
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

Khrys

  • Sr. Member
  • ****
  • Posts: 256
Re: Avoiding duplicate symbols across packages (defining weak symbols)
« Reply #2 on: May 29, 2025, 02:36:43 pm »
You can' t mix them. You must make them point to the same entry point.

I haven't run into this issue - in fact, the following works just fine and prints "Pascal" followed by "C", as expected, on my machine (linked against my shim library wrapping  _onexit):

Code: Pascal  [Select][+][-]
  1. program TestExit;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. uses
  6.   SysUtils;
  7.  
  8. procedure Pascal_Exit();
  9. begin
  10.   WriteLn('Pascal');
  11.   Sleep(1000);
  12. end;
  13.  
  14. procedure C_Exit();
  15. begin
  16.   WriteLn('C');
  17.   Sleep(1000);
  18. end;
  19.  
  20. function atexit(Func: Pointer): Integer; cdecl; external name 'atexit';
  21.  
  22. {$linklib msvcrt_shim} // Maps 'atexit' to '_onexit'
  23. {$linklib msvcrt}
  24.  
  25. begin
  26.   AddExitProc(@Pascal_Exit);
  27.   atexit(@C_Exit);
  28. end.

440bx

  • Hero Member
  • *****
  • Posts: 5582
Re: Avoiding duplicate symbols across packages (defining weak symbols)
« Reply #3 on: May 30, 2025, 07:06:00 pm »
if you don't mind that your program would only work with Windows 8 and above, kernelbase exports atexit.

The prototype is exactly the same as the documented one (kernelbase's one isn't documented)  Also, just about every dll other than ntdll is dependent on kernelbase, therefore using it wouldn't add anything that your program isn't likely already using.

HTH.
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v4.0rc3) on Windows 7 SP1 64bit.

 

TinyPortal © 2005-2018