0

I'm explicitly loading a c-API dynamic library (dll/so), where it is not possible to link symbols with a lib-file. So I use GetProcAddress and dlsym to find the apropriate functions.

The problem I have is due to the static declaration of "foo" and "baz" I have to use GetProcAddress/dlsym for every implementation file that includes this header.

The behaviour I want is that I only want to lookup the symbols once for the process.

Do I have to declare them all as "extern" then have a own set of function pointers in the project that I then set with GetProcAddress/dlsym?

What is the recommended way to fix it?

Example API header:

#ifdef _WIN32
#define API_IMPORT __declspec(dllimport)
#define API_EXPORT __declspec(dllexport)
#elif defined(__GNUC__)
#define API_EXPORT __attribute__((visibility("default")))
#define API_IMPORT
#else
#error Unsupported for now
#endif

#if LIB_COMPILING
#define API_DECL API_EXPORT
#else
#define API_DECL API_IMPORT
#endif

#ifdef __cplusplus
extern "C" {
#endif

API_DECL int ifoo(int bar);
API_DECL void ibaz(int qux);
typedef int (* PFN_FOO_PROC)(int);
typedef void (* PFN_BAZ_PROC)(int);
static PFN_FOO_PROC foo = 0;
static PFN_BAZ_PROC baz = 0;

#ifdef __cplusplus
}
#endif

"ifoo" and "ibaz" contains the actual implemenations in a c-file for the dynamic library.

So in this example to load symbols for linux:

        foo = (PFN_FOO_PROC) dlsym(handle, "ifoo");
        baz = (PFN_BAZ_PROC) dlsym(handle, "ibaz");

Thanks for any help

Decaf Sux
  • 305
  • 1
  • 11
  • "*it is not possible to link symbols with a lib-file*" - why not? `GetProcAddress()`/`dlsym()` only work with exported symbols, which means any symbol they can find, a sttatic-link `.lib` file can also provide linkage for. If you have a `.lib` file that doesn't provide those linkages, then simply generate a new `.lib` file from the export data of the `.dll`/`.so` itself. Your compiler likely has tools for that exact purpose. – Remy Lebeau Nov 29 '21 at 22:42
  • Do not define static variables in a header-file. Correction: don't define variables in a header-file. Headers files are meant to contain only the _declaration_ of the variables. – Zsigmond Lőrinczy Nov 30 '21 at 06:33

1 Answers1

2

The whole idea behind delay loading is that you don't have to use LoadLibrary / GetProcAddress. Instead, if (say) foo is a function in your delay loaded DLL you can simply say if (foo) before calling it to see if it's actually available.

I know less about Linux and macOS, but I do know that macOS has 'weak linking' which operates in a similar way. I don't know what Linux does, sorry, but I imagine it offers something similar.

Paul Sanders
  • 24,133
  • 4
  • 26
  • 48
  • Sorry a miss by me... I meant that they are explicitly loaded, not delay loaded... I'll edit – Decaf Sux Nov 29 '21 at 22:00
  • Why not delay load them then? https://learn.microsoft.com/en-us/cpp/build/reference/linker-support-for-delay-loaded-dlls?view=msvc-170 – Paul Sanders Nov 29 '21 at 22:01
  • And: https://stackoverflow.com/a/3749780/5743288 – Paul Sanders Nov 29 '21 at 22:03
  • Because I need to be able to load different implementations of the same API in runtime. For example (not the only case) one library is targeting "special hardware A" while another is targeting "hardware B" but they use the same API for the desired function. The user needs to be able to dynamically switch this in runtime. – Decaf Sux Nov 29 '21 at 22:05
  • 1
    At least on Windows, it is possible to unload and reload delay-loaded DLLs at runtime. See [Linker support for delay-loaded DLLs](https://learn.microsoft.com/en-us/cpp/build/reference/linker-support-for-delay-loaded-dlls?view=msvc-170). Delay-Loading is just a convenience wrapper provided by the compiler/linker for calling `LoadLibrary()`/`GetProcAddress()` for you. – Remy Lebeau Nov 29 '21 at 22:46