dlsym () с глобальной переменной в C ++ - PullRequest
5 голосов
/ 28 марта 2011

Я хочу создать программу, способную dlopen() серию библиотек (написанных мной) и запускать все функции, хранящиеся в глобальной переменной с именем test_suite внутри этого .so файла, который является NULL- прерванный массив указателей на функции (подписи функций предварительно определены мной, об этом не нужно беспокоиться).

Проблема в том, что g ++ искажает эту переменную. Библиотека скомпилирована как:

g++ -Wall -shared -rdynamic -fPIC foo.cpp -o foo.so

и «индекс функции» объявляется и статически выделяется как:

const testunit_testcase test_suite = { ... }

еще

objdump -t foo.so  | grep test_suite

показывает:

0000000000200940 l     O .data.rel.ro   0000000000000020              _ZL10test_suite

Что мне нужно, это

0000000000200940 l     O .data.rel.ro   0000000000000020              test_suite

Так что я могу dlsym(dlh, "test_suite") в программе dlopen() 'ing foo.so

Спасибо


Добавление

Да, extern "C" было первым, что я попробовал:

extern "C" {
        const testunit_testcase test_suite[] = { 
                //TESTUNIT_DEF_TESTCASE(doTest),
                {NULL, NULL},
        };  
}

Я использую:

g ++ -v Использование встроенных спецификаций. COLLECT_GCC = G ++ COLLECT_LTO_WRAPPER = / USR / Библиотека / GCC / x86_64-неизвестно-Linux-гну / 4.5.2 / LTO-обертка Цель: x86_64-unknown-linux-gnu Настраивается с: /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-уникальный-объект --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 Модель потока: posix gcc версия 4.5.2 20110127 (предварительный выпуск) (GCC)


Приложение 2

По любым причинам

extern "C" {
     const testunit_testcase test_suite = { ... }
}

не не работает, НО это делает:

extern "C" const testunit_testcase test_suite = { ... }

Мой вопрос сейчас : Как я вижу в некоторых из ваших ответов, для вас подходит включение extern "C" { ... }. Есть ли какие-либо флаги компилятора, которые я мог бы использовать, чтобы убедиться, что test_suite никогда не будет искажен, независимо от того, какая версия 4.x (по крайней мере) g ++ используется?

Ответы [ 4 ]

8 голосов
/ 28 марта 2011

Проблема не в искажении имен. (Или, возможно, нет: публичный имена переменных обычно не искажены.) Реальная проблема заключается в том, что «const» означает неявное static, делая переменную невидимой снаружи переводческий блок. Чтобы избежать этого, переменная должна быть явно объявлен extern. И "Форма спецификации связи, которая содержит заключенное в скобки объявление-seq не влияет на объявления являются определениями или нет (3.1); форма спецификация связи, непосредственно содержащая одно объявление рассматривается как внешний спецификатор (7.1.1) с целью определения является ли содержащаяся декларация определением. похоже, не решает вашу проблему напрямую (наличие инициализатор гарантирует, что объявление является определением), кажется указать намерение: в спецификаторе связи, заключенном в фигурные скобки, применяются обычные правила; если спецификатор связи применяется непосредственно к декларация, это как если бы декларация была явно внешней. Так что вы можно написать либо:

extern "C" {
    testunit_testcase const test_suite[] // ...
}

или

extern "C" testunit_testcase const test_suite[] // ...

Но должен быть внешний, который явно применяется к определению, для того, чтобы переопределить неявное "static" of "const".

1 голос
/ 28 марта 2011

Это

x.cxx:

 extern "C"
 {
    extern const int test_suite[] = { 0 };
 }

у меня работает:

~/ec% g++ -Wall -rdynamic -shared x.cxx -o x.so
~/ec% objdump -t x.so | grep test_suite
00000444 g     O .rodata        00000004              test_suite

Если я не extern test_suite, он вообще не экспортируется. Это имеет смысл, поскольку const в области видимости файла или пространства имен подразумевает static. Это не имеет смысла, потому что я ожидал бы, что блок extern "C" "посчитает" за это. Я не знаю, это ошибка GCC или нет. Можете ли вы уменьшить проблему до чего-то похожего по размеру?

0 голосов
/ 28 марта 2011

Не делайте эту переменную static.

static означает, что переменная является локальной для текущей единицы компиляции, поэтому g ++ изменяет ее имя.Если вы хотите, чтобы переменная была доступна «извне», вы не должны делать это static.Итак, в файле .cpp определите переменную следующим образом:

const testunit_testcase test_suite = { ... }

Если вы также объявите переменную в соответствующем файле .h, сделайте это объявление extern:

extern const testunit_testcase test_suite;
0 голосов
/ 28 марта 2011

Вы используете компилятор C ++, поэтому имя искажено.Попробуйте использовать либо gcc (если возможно), либо используйте

extern "C" {
     const testunit_testcase test_suite = { ... }
}

. extern "C" отключает искажение имени.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...