簡體   English   中英

符號查找錯誤:在64位上組合可執行文件和庫

[英]Symbol Lookup Error: Combining Executable and Library on 64bits

我想在使用可執行文件符號的庫上創建dlopen。 我正在64位系統上編譯gdl-0.9,並且正在構建一個庫,該庫將使用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);
    }
}

使用gdl的“ Ubuntu 10.04.1 LTS”預構建版本。

$ 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

_ZN4EnvT6NParamEjEnvT::NParam(unsigned int)
_ZN4EnvT6NParamEyEnvT::NParam(unsigned long long)

因此,您應該首先查看如何包括EnvT聲明。 您需要查看NParam參數的類型,並找到在何處重新定義。

我不知道您是否仍然可以使用該幫助,但是要為64位編譯這兩個函數和所有其他函數,應在g ++命令中添加-DHAVE_64BIT_OS選項。 這樣,預處理器可以在typedefs.hpp中為SizeT設置正確的類型。 所以編譯將

g ++ -DHAVE_64BIT_OS -I /(gdl src的路徑)-c two.cpp -fpic

所有其他命令保持不變。

nm輸出看起來好像類型不同-可執行文件具有_ZN4EnvT6NParamEy而庫需要_ZN4EnvT6NParamEj 如您所見,最后一個字母有所不同。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM