Ошибка поиска символа: объединение исполняемого файла и библиотеки на 64 битах
Я хочу сделать dlopen для библиотеки, которая использует символы исполняемого файла. Я собираю gdl-0.9 на 64-битной системе и собираю библиотеку, в которой gdl будет использовать dlopen. Проблема заключается в том, что библиотека использует код gdl, который будет находиться в исполняемом файле, и, хотя я использовал флаг -Wl,- export-dynamic, программа вылетает и печатает: gdl: ошибка поиска символа: ./two.so: неопределенный символ: _ZN4EnvT6NParamEj
Вот как я это сделал:
Скомпилировал two.cpp в качестве разделяемой библиотеки two.so.
// two.cpp
#include "envt.hpp"
using namespace std;
template< typename T>
BaseGDL* two_fun_template( BaseGDL* p0)
{
T* p0C = static_cast<T*>( p0);
T* res = new T( p0C->Dim(), BaseGDL::NOZERO);
SizeT nEl = p0->N_Elements();
for( SizeT i=0; i<nEl; ++i)
{
(*res)[ i] = 2 * ((*p0C)[ i]);
}
return res;
}
extern "C" BaseGDL* two_fun( EnvT* e)
{
SizeT nParam=e->NParam();
if (nParam != 1) {
cout << "TWO: Improper Number of Variables" << endl;
return new DLongGDL( -1);
}
BaseGDL* p0 = e->GetPar( 0);//, "TWO");
if( p0->Type() == DOUBLE)
return two_fun_template< DDoubleGDL>( p0);
else if( p0->Type() == FLOAT)
return two_fun_template< DFloatGDL>( p0);
else
{
return new DLongGDL( -1);
}
}
Использовал "Ubuntu 10.04.1 LTS" перед сборкой gdl.
$ gdl
GDL - GNU Data Language, Version 0.9
For basic information type HELP,/INFO
'GDL_STARTUP'/'IDL_STARTUP' environment variables both not set.
No startup file read.
GDL> linkimage,'TWO','./two.so',1,'two_fun'
GDL> print, "TWO Loaded"
GDL> print, two(1.0)
gdl: symbol lookup error: ./two.so: undefined symbol: _ZN4EnvT6NParamEj
Поэтому я решил, что проблема заключается в выполнении этой строки: SizeT nParam=e->NParam();
Затем я получил исходный код gld-0.9, произвел полную компиляцию с -Wl,- export-dynamic, и произошла та же ошибка.
Затем я выполнил полную компиляцию с флагом -m32 (сила 32 бита) и:
$ ../gdl32
GDL - GNU Data Language, Version 0.9
For basic information type HELP,/INFO
'GDL_STARTUP'/'IDL_STARTUP' environment variables both not set.
No startup file read.
GDL> linkimage,'TWO','./two.so',1,'two_fun'
GDL> print, "TWO Loaded"
GDL> print, two(1.0)
2.00000
GDL>
Так что, я думаю, это означает, что это проблема 64 бит, но почему? Я много искал в Интернете и не нашел ничего, кроме -Wl,- export-dynamic, может быть, я не знал, как выглядеть или что-то в этом роде. Кто-нибудь может помочь?
Кстати, это то, что я получаю при запуске утилиты "nm".
64бит:
$ nm two.so | grep NParam
U _ZN4EnvT6NParamEj
$ nm ../gdl64 | grep NParam
00000000006dc320 T _ZN4EnvT6NParamEy
32бит:
$ nm two.so | grep NParam
U _ZN4EnvT6NParamEj
$ nm ../gdl32 | grep NParam
0830a6a0 T _ZN4EnvT6NParamEj
3 ответа
_ZN4EnvT6NParamEj
является EnvT::NParam(unsigned int)
_ZN4EnvT6NParamEy
является EnvT::NParam(unsigned long long)
Итак, вы должны начать с рассмотрения того, как вы включаете декларацию EnvT
, Вам нужно посмотреть, какой тип аргумента у NParam, и найти, где он переопределен.
Я не знаю, можете ли вы по-прежнему использовать справку, но для компиляции двух и всех других функций для 64-битной системы вы должны добавить опцию -DHAVE_64BIT_OS к команде g ++. Таким образом, препроцессор устанавливает правильный тип для SizeT в typedefs.hpp. Так что компиляция будет
g++ -DHAVE_64BIT_OS -I/(путь к gdl src) -c two.cpp -fpic
Все остальные команды остаются прежними.
От nm
вывод это выглядит как типы разные - исполняемый файл имеет _ZN4EnvT6NParamEy
пока библиотека хочет _ZN4EnvT6NParamEj
, Как видите, последняя буква отличается.