Anedar
Anedar

Reputation: 4275

How to identify in which module a function/object is compiled

I have currently a project where different shared libraries are linked together. The users of those libraries are able to add their own shared libraries to the project. Inside all of those libraries one is able to write something like this:

int a;
OBJECT(a)

double b;
OBJECT(b)

OBJECT is a macro that collects information about the linked int, double or whatever other type/class and makes them available via a common interface in all other shared libraries. It is defined in a header that is shared across all libraries.

What i would like to do now, is identify in which of the shared libraries the macro is called.

At the moment i use something like this in a header file that is shared across all shared libraries:

Module& getModule();

#define MODULE(name) Module& getModule() { \
    static Module mod{ #name }; \
    return mod; \
}

This introduces a declaration and a macro to provide a definition. Then in every shared library i call the macro in exactly one .cpp, using a different name each time to introduce a definition. This defines exactly one static Module mod; per shared library, each with its own name. The OBJECT macro calls this function internally to "register" itself with the given Module. This way i can get a list of all the objects created with OBJECT, ordered by their Module (which is ordered by the shared library they are in) .

With MSVC this works fine. Since i don't add a _declspec(dllimport/dllexport) in front i force the linker to link to the definition given inside the same shared library. However under Linux(gcc) this does not work and all OBJECT macros use the definition in a single shared library, which means i can not identify anymore in which library the macro was called.

I am aware, that the C++ standard does not say anything about shared libraries at all, but what i am looking for is a way that is "as standard compliant as possible" or at least as portable as possible.

I thought about using a macro that just returns the "libary name" as a string. But that would mean if you include headers of other libraries, you need to make sure they either don't contain a definition of the macro as well or the order of include/definition matters, both of which is hard to make sure in practice.

Is there any other (smart) way to solve this problem?

Upvotes: 1

Views: 257

Answers (1)

parpwhick
parpwhick

Reputation: 26

A simple solution, working even on Linux is to put this Module static function identifier in every library you link, but hiding it so it is not exported by default:

#ifdef _WIN32
    #define DLL_LOCAL
#elif __linux__
    #define DLL_LOCAL  __attribute__ ((visibility ("hidden")))
#endif

#define MODULE(name) DLL_LOCAL Module& getModule() { \
    static Module mod{ #name }; \
    return mod; \
}

Upvotes: 1

Related Questions