我想在使用可执行文件符号的库上进行dlopen。我正在64位系统上编译gdl-0.9,我正在构建一个gdl将使用dlopen的库。问题是该库使用的gdl代码将位于可执行文件中,即使我使用 -Wl, - export-dynamic 标志,程序也会崩溃并且打印: gdl:符号查找错误:./ twwo.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-&gt; 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
答案 0 :(得分:3)
_ZN4EnvT6NParamEj
是EnvT::NParam(unsigned int)
_ZN4EnvT6NParamEy
为EnvT::NParam(unsigned long long)
因此,您应该首先看看如何包含EnvT
的声明。您需要查看NParam的参数类型,并找到重新定义的位置。
答案 1 :(得分:1)
我不知道您是否仍然可以使用帮助,但是为了编译这两个函数以及64位的所有其他函数,您应该在g ++命令中添加-DHAVE_64BIT_OS选项。这样预处理器就可以在typedefs.hpp中为SizeT设置正确的类型。 所以编译将是
g ++ -DHAVE_64BIT_OS -I /(gdl src的路径)-c two.cpp -fpic
所有其他命令保持不变。
答案 2 :(得分:0)
从nm
输出看起来类型不同 - 可执行文件有_ZN4EnvT6NParamEy
,而库需要_ZN4EnvT6NParamEj
。如你所见,最后一个字母不同。