2011-12-23 2 views
3

Я пытаюсь сделать простейшую библиотеку.g ++ генерирует неправильные символы в динамической библиотеке

#include <stdio.h> 
    void PutLoLoLo(){ 
    puts("Lololo"); 
} 

компиляции с г ++:

g++ -shared -fPIC main2.cpp -o simple.so -Wall 

и я получаю это в таблице символов:

:$ nm -D --dynamic --defined-only simple.so 
0000048c T _Z9PutLoLoLov 
00002010 A __bss_start 
00002010 A _edata 
00002018 A _end 
000004f8 T _fini 
00000354 T _init 

, но я надеюсь, что-то вроде этого:

0000048c T PutLoLoLo 
00002010 A __bss_start 
00002010 A _edata 
00002018 A _end 
000004f8 T _fini 
00000354 T _init 

Так что, Конечно, я получаю ошибку dlopen() при попытке загрузить ее.

Пожалуйста, помогите мне: что я делаю неправильно?

ответ

4

C++ mangles имена символов. Если вы хотите, чтобы избежать коверкая, функция должна быть объявлена ​​как extern C, например, так:

#include <stdio.h> 
    extern "C" void PutLoLoLo(){ 
    puts("Lololo"); 
} 

Тогда ссылка:

$ g++ -shared -fPIC lolo.cc -o lolo.so -Wall 

даст вам то, что вы ожидаете:

$ nm -D --dynamic --defined-only ./lolo.so 
000000000000061c T PutLoLoLo 
0000000000002018 A __bss_start 
0000000000002018 A _edata 
0000000000002028 A _end 
0000000000000668 T _fini 
0000000000000500 T _init 

Вы сможете распаковать библиотеку и получить символ через его «нормальное» имя. Функция ограничена семантикой C. Таким образом, вы не можете, например, делать это с помощью функций-членов или использовать объекты с семантикой класса в качестве аргументов и т. Д. Поэтому, если вам нужно передать объекты, вам нужно будет принять эти аргументы как void * и выполнить бросок.

+0

Спасибо! Это помогло! Разве вы не знаете, есть способ загрузить измененные символы каким-то образом по имени без использования «extern C»? Этого достаточно для моей библиотеки, но мне просто интересно. – ov7a

+0

Насколько я знаю, нет никакого переносного способа определить искаженное имя символа. Каждая инструментальная цепочка может свободно калечить по своему усмотрению; это своего рода точка. Способ типичной работы с этой проблемой с динамически загружаемым C++ состоит в том, чтобы иметь одну точку входа «extern C», которая требуется для возврата указателя на объект, который реализует абстрактный интерфейс (vtable), который разделяет как загружаемый, так и загруженный код. Затем загрузчик может переименовать_интерфейс в этот тип интерфейса, и теперь у вас есть доступ к C++-функциям библиотеки. Но это сложно сделать правильно! – acm

3

Это выглядит как C++ name mangling. Попробуйте следующее:

extern "C" void PutLoLoLo(){ 
    puts("Lololo"); 
} 
Смежные вопросы