【发布时间】:2011-05-15 21:31:00
【问题描述】:
我想在一个使用可执行符号的库上创建一个 dlopen。我正在 64 位系统上编译 gdl-0.9,并且正在构建 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
【问题讨论】:
-
看起来你的头文件不同意编译库关于
SizeTtypedef的大小。具体来说,该库似乎使用 64 位返回值,two.so需要 32 位。尝试运行从nm到c++filt的符号,看看j和y对应的确切类型。
标签: c++ linker 64-bit 32bit-64bit