2012-01-17 5 views
6

Я пытаюсь обернуть функцию шаблона с помощью компоновщика GNU wrap вариант. Код выглядит следующим образом:Wrapping C++ template function

// f.h 
template<typename T> 
void f(T t) { 
} 

// bar.h 
void bar(); 

// bar.cpp 
#include "bar.h" 
#include "f.h" 

void bar() { 
    f(42); 
} 

// test.cpp 
extern "C" { 
    extern void __real__Z1fIiEvT_(int i); 
    void __wrap__Z1fIiEvT_(int i) { 
    __real__Z1fIiEvT_(i); 
    } 
} 

int main() { 
    bar(); 
} 

код, приведенный выше, связан со следующей командой:

g++ -Xlinker -wrap=_Z1fIiEvT_ -o test test.o bar.o 

К сожалению, это не работает, и всегда исходной функции е называется вместо моего завернутая версия __wrap__Z1fIiEvT_. Вы видите какие-то ошибки, которые я сделал?

Отредактировано: Как указывалось я прилагаю выход нм здесь, чтобы убедиться, что я не сделал ни одной ошибки с искаженной именем функции шаблона:

$ g++ -c bar.cpp -o bar.o 
$ nm bar.o 
0000000000000000 W _Z1fIiEvT_ 
+1

Двойная проверка, что вы вызываете правильную украшенную функцию с помощью 'nm' или аналогичного инструмента. Добавление полезного результата из этого вопроса может оказаться полезным. – uesp

+0

Не должно f (42); be f (42)? –

+1

@ Fire-Dragon-DoL - функции шаблона выведут их аргументы из аргументов, а так как int - это тип в противном случае неапорированного целочисленного литерала, это отлично работает. Если f - класс, то аргумент шаблона должен быть явным. – Marc

ответ

1

http://linux.die.net/man/1/ld От:

--wrap = символ
Используйте функцию обертки для символа. Любая неопределенная ссылка на символ будет разрешена на "_ wrap symbol". Любая неопределенная ссылка на «_ real символ» будет разрешена к символу.

Я думаю, что слово «undefined» может быть ключевым здесь. Ваш символ интереса определенно определен в bar.o, и вывод nm подтверждает его, так как неопределенные символы отмечены «U», а не «W».


Update:

Я думаю, поэтому не представляется возможным, чтобы обернуть шаблон функции?

Я думаю, что это зависит в большей степени от того, где функция определена (или создана), и если это определение доступно для компоновщика. В вашем случае, если вы определили функцию без шаблона в bar.cpp, где она используется, результат будет таким же. Даже если вы определили функцию в bar.cpp, но использовали ее в main.cpp, я думаю, что это будет одно и то же, хотя и не совсем уверенное (вы можете попробовать). И я уверен, что если вы связали bar.cpp и main.cpp в разных модулях (совместно используемая библиотека и исполняемый файл), тогда вы сможете обернуть функцию из bar.cpp, используемой в main.cpp, опять же независимо от того, будь то шаблон или нет.


Update 2: Я не был уверен, но Майк подтвердил с экспериментом (см свой ответ и комментарии там), что упаковка работает, если символ не определен в файле объекта, даже если этот файл компонуется вместе с другим объектным файлом, содержащим определение символа. Большой!

+0

Вы правы. Поскольку компилятор генерирует код для созданного шаблона функции, он больше не является неопределенным символом и, следовательно, компоновщик не переносит его на «_wrap_symbol». Я думаю, поэтому невозможно обернуть функции шаблона? – Mike

1

Замечания были полезными, но я не думаю, что необходимо разбить его на исполняемую и (общую) библиотеку. Ключ состоит в том, чтобы иметь переднюю декларацию для функции шаблона в происхождении вызова и создавать экземпляр функции шаблона с используемым типом в отдельной единицы перевода. Это гарантирует, что f не определено в баре.o:

//bar.cpp 
#include "bar.h" 

template<typename T> void f(T); 

void bar() { 
f(42); 
} 

//f.h 
template<typename T> 
void f(T t) { 
} 

//f.cpp 
#include "f.h" 
template void f(int); 


$ nm bar.o 
       U _Z1fIiEvT_ 
0000000000000000 T _Z3barv 
+0

Но, по-прежнему считается undefined, когда bar.o связан вместе с f.o для создания исполняемого файла? Я признаю, что у меня нет практического опыта работы с '-wrap', чтобы точно сказать, что он будет делать. –

+0

Видимо, да, иначе компоновщик не обернул бы символ префиксом '_wrap', или я ошибаюсь? Приведенный выше пример работает при использовании с измененным завернутым именем ('_Z1fIiEvT_'), как показано в коде в начале этого сообщения. – Mike

+0

Тогда, конечно, да. Я изменю свой ответ и расскажу о вашем расследовании. Благодаря! –