Craig Sanders
Craig Sanders

Reputation: 51

In C++, can an externally defined global variable be accessed from within a dynamic library?

In C++, can an externally defined global variable be accessed from within a dynamic library?

I have a global variable declared in a header file as follows ;

Filename : TestVariable.hpp

#ifndef TESTVARIABLE_HPP
#define TESTVARIABLE_HPP

extern
int   testVariable;

#endif 

and then defined in a source code file as follows ;

Filename : TestVariable.cpp

int   testVariable;

The source code which comprises my dynamic library is as follows ;

Filename : Plugin.cpp

#include <TestVariable.hpp>

#ifdef __cplusplus
extern "C" {
#endif

void *
__attribute__((constructor))
loadLibrary
(
 void
)
{
    testVariable = 100;
}

void *
__attribute__((destructor))
unloadLibrary
(
 void
)
{
}

#ifdef __cplusplus
}
#endif

My main function is then defined as follows ;

Filename : main.cpp

#include <iostream>
#include <dlfcn.h>
// dlopen
#include <TestVariable.hpp>

using std::cout;
using std::endl;

int main(void)
{
    void * libHandle_p = NULL;


    cout << "Test variable = " << testVariable << endl;

    // Load the dynamic library.

    libHandle_p = dlopen("./.libs/libPlugin.so", RTLD_LAZY);

    if (libHandle_p == NULL)
    {
        cout << "Error loading library" << endl;
        return(-1);
    }

    cout << "Test variable = " << testVariable << endl;
    return(0);
}

I can compile and link all of the code correctly (and without any warnings) using GNU Autotools, g++ and ld, but when I run the resulting binary executable, it can't dlopen the dynamic library file. If however, I comment out the one and only line of code that comprises the body of the function loadLibrary and then re-compile and link, the program works correctly!

If I didn't know better, I'd say that the library can't resolve its reference to the global variable testVariable when dlopen is called on it (the library) and this is what is causing the dlopen operation to fail. Might linkage types and/or name mangling have something to do with this problem?

If I run the Linux nm utility on the generated dynamic library, it informs me that the symbol testVariable is undefined, i.e. "U". If I run the nm utility on the binary executable, it informs me that the symbol testVariable exists and resides within the uninitialized data section, i.e. "B". So why can't dlopen resolve this symbol when it loads the dynamic library?

I only generate the dynamic library from the source file Plugin.cpp. The binary executable is being generated from the 2 source code files main.cpp and TestVariable.cpp.

Can someone please help. I could swear the answer is staring me in the face but I am just not seeing it.

Thanks in advance.

Upvotes: 3

Views: 2056

Answers (1)

Craig Sanders
Craig Sanders

Reputation: 51

It seems I have solved my own problem. Passing the following argument to the GNU g++ compiler when compiling the binary executable (not the dynamic library) fixed the problem ;

-Wl,--export-dynamic

It works because it forces the linker to add the symbol testVariable to the Dynamic Symbol Table, and according to the man page for ld (the GNU linker), the Dynamic Symbol Table contains the set of symbols which are visible to dynamic objects (my library in this case) at run time.

Sorry for the inconvenience.

Upvotes: 2

Related Questions