I want to make a program which is able to dlopen() a series of libraries (written by myself) and run all the functions stored in a global variable called test_suite inside that .so file, which is a NULL-terminated array of function pointers (the functions’ signatures are predefined by myself, no need to worry about that).
The problem is g++ mangles that variable. The library is compiled as:
g++ -Wall -shared -rdynamic -fPIC foo.cpp -o foo.so
and the “function index” is declared and allocated statically as:
const testunit_testcase test_suite = { ... }
yet
objdump -t foo.so | grep test_suite
shows:
0000000000200940 l O .data.rel.ro 0000000000000020 _ZL10test_suite
What I need is
0000000000200940 l O .data.rel.ro 0000000000000020 test_suite
So I can dlsym(dlh, "test_suite") in the program dlopen()‘ing foo.so
Thanks
Addendum
Yes, extern "C" was the first thing I’ve tried:
extern "C" {
const testunit_testcase test_suite[] = {
//TESTUNIT_DEF_TESTCASE(doTest),
{NULL, NULL},
};
}
I am using:
g++ -v Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-unknown-linux-gnu/4.5.2/lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with:
/build/src/gcc-4.5-20110127/configure
–prefix=/usr –enable-languages=c,c++,fortran,objc,obj-c++,ada
–enable-shared –enable-threads=posix –enable-__cxa_atexit –enable-clocale=gnu –enable-gnu-unique-object –enable-lto –enable-plugin –enable-gold –with-plugin-ld=ld.gold –disable-multilib –disable-libstdcxx-pch –with-system-zlib –with-ppl –with-cloog –with-cloog-include=/usr/include/cloog-ppl
–libdir=/usr/lib –libexecdir=/usr/lib –mandir=/usr/share/man –infodir=/usr/share/info Thread model: posix gcc version 4.5.2
20110127 (prerelease) (GCC)
Addendum 2
For whatever reasons
extern "C" {
const testunit_testcase test_suite = { ... }
}
does not work, BUT this one does:
extern "C" const testunit_testcase test_suite = { ... }
My question now: As I can see in some of your answers, enclosing extern "C" { ... } works for you. Are there any compiler flags I could use to make sure that test_suite will never be mangled, no matter what 4.x (at least) g++ version is used?
The problem isn’t one of name mangling. (Or probably isn’t: public
variable names are not usually mangled.) The real problem is that the
“const” means implicit static, rendering the variable invisible outside
the translation unit. To avoid this, the variable must be explicitly
declared extern. And “The form of linkage-specification that contains
a brace-enclosed declaration-seq does not affect whether the contained
declarations are definitions or not (3.1); the form of
linkage-specification directly containing a single declaration is
treated as an extern specifier (7.1.1) for the purpose of determining
whether the contained declaration is a definition.” Which, while it
doesn’t seem to address your issue directly (the presence of an
initializer ensures that the declaration is a definition), it does seem
to indicate the intent: within a brace enclosed linkage specifier, the
usual rules apply; if the linkage specifier applies directly to the
declaration, it’s as if the declaration were explicitly extern. So you
can write either:
or
But there must be an extern which applies explicitly to the definition,
in order to override the implicit “static” of “const”.