This is a continuation of https://developer.apple.com/forums/thread/795348
I rambled too much and did not understand the underlaying problem.
The problem is that I have a C function in a iOS library. I want to call this C function from a dylib that this library loads on runtime. When running directly from Xcode (either in debug or release mode) this works correctly. However, when the app is uploaded to testflight or distributed for debugging then the function is stripped and a null function pointer exception crashes the app.
In the last post it was really hard to explain and I was pressed on time but I've created a minimal reproducible example:
https://github.com/ospfranco/dylib_crash
The instructions to run and reproduce the crash are on the README.
After much much tweaking and testing. I finally called the C function from another place inside the library and this did work. It's only when called from the dylib that it fails.
The symbol _say_hello_world was being stripped from the binary's symbol table during the release build.
The function code existed in the binary (verified via dSYM), but Xcode's default Strip Style = All Symbols removes symbol names from the export table. Since dlsym() looks up symbols by name, it couldn't find the function.
In the app's Xcode project (not Package.swift):
Build Settings → Strip Style → Non-Global Symbols
This preserves global symbols (like _say_hello_world) in the binary's symbol table while still stripping local/debug symbols.
Limitation
This setting cannot be controlled from Package.swift. SPM package authors must document that users need to set STRIP_STYLE = non-global in their app's build settings when using dlsym() with statically linked code.
Basically, this is a dead end trying to keep the global symbols alive. The only way I have found to make it work is passing the function pointers directly to my dylib and then there is no symbol resolution necessary.