Ошибка поиска символа: объединение исполняемого файла и библиотеки на 64 бита - PullRequest
2 голосов
/ 25 ноября 2010

Я хочу сделать 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".

64bit:

$ nm two.so | grep NParam
                 U _ZN4EnvT6NParamEj
$ nm ../gdl64 | grep NParam
00000000006dc320 T _ZN4EnvT6NParamEy

32bits:

$ nm two.so | grep NParam
         U _ZN4EnvT6NParamEj
$ nm ../gdl32 | grep NParam
0830a6a0 T _ZN4EnvT6NParamEj

Ответы [ 3 ]

3 голосов
/ 25 ноября 2010

_ZN4EnvT6NParamEj равно EnvT::NParam(unsigned int)
_ZN4EnvT6NParamEy равно EnvT::NParam(unsigned long long)

Итак, вам следует начать с рассмотрения того, как вы включаете объявление EnvT.Вам нужно посмотреть, какой тип аргумента у NParam, и найти, где он переопределен.

1 голос
/ 25 января 2011

Я не знаю, можете ли вы по-прежнему использовать справку, но для компиляции двух и всех других функций для 64-битной системы вы должны добавить опцию -DHAVE_64BIT_OS к команде g ++.Таким образом, препроцессор устанавливает правильный тип для SizeT в typedefs.hpp.Поэтому компиляция будет

g ++ -DHAVE_64BIT_OS -I / (путь к gdl src) -c two.cpp -fpic

Все остальные команды остаются прежними.

0 голосов
/ 25 ноября 2010

Из вывода nm похоже, что типы различаются - исполняемый файл имеет _ZN4EnvT6NParamEy, а библиотека хочет _ZN4EnvT6NParamEj. Как видите, последняя буква отличается.

...