符号查找错误:在 64 位上组合可执行文件和库

发布于 2024-10-04 06:45:02 字数 2505 浏览 1 评论 0原文

我想在使用可执行文件符号的库上创建 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

I want to make a dlopen on a library that uses executable's symbols. I'm compiling gdl-0.9 on a 64bits system and I'm building a library that gdl will use dlopen. The problem is that the library uses gdl code which will be at the executable and, even though I used the -Wl,--export-dynamic flag, the program crashes and prints:
gdl: symbol lookup error: ./two.so: undefined symbol: _ZN4EnvT6NParamEj

Here is how I've done things:

Compiled two.cpp as the shared lib 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);
    }
}

Used "Ubuntu 10.04.1 LTS" pre-build of 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

So I figured the problem was upon executing this line: SizeT nParam=e->NParam();

Next I got the gld-0.9 source code, did the whole compilation with -Wl,--export-dynamic and the same error occurred.

Next I did the whole compilation with -m32 flag (force 32bits) and:

$ ../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>

So I guess this means its a 64bit problem, but why? I've searched a lot in the web and didn't find anything other then the -Wl,--export-dynamic, maybe I didn't know how to look or something. Can anyone help?

Btw, this is what I get when running the "nm" util.

64bits:

$ 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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

小忆控 2024-10-11 06:45:02

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

因此,您应该首先查看如何包含 EnvT 声明。您需要查看 NParam 参数的类型并找到它被重新定义的位置。

_ZN4EnvT6NParamEj is EnvT::NParam(unsigned int)
_ZN4EnvT6NParamEy is EnvT::NParam(unsigned long long)

So you should start with looking at how you include declaration of EnvT. You need to look at what type of an argument of NParam and find where it's redefined.

香橙ぽ 2024-10-11 06:45:02

我不知道您是否仍然可以使用帮助,但是为了编译这两个函数以及所有其他 64 位函数,您应该在 g++ 命令中添加 -DHAVE_64BIT_OS 选项。这样,预处理器就可以在 typedefs.hpp 中为 SizeT 设置正确的类型。
因此编译将是

g++ -DHAVE_64BIT_OS -I/(path to gdl src) -c Two.cpp -fpic

所有其他命令保持不变。

I don't know if you still can use the help, but for compiling the the two function and all the others for 64 bit you should add -DHAVE_64BIT_OS option to the g++ command. This way the preprocessor sets the right type for SizeT in typedefs.hpp.
So compiling will be

g++ -DHAVE_64BIT_OS -I/(path to gdl src) -c two.cpp -fpic

All the other commands stay the same.

最丧也最甜 2024-10-11 06:45:02

nm 输出看来,类型不同 - 可执行文件具有 _ZN4EnvT6NParamEy,而库需要 _ZN4EnvT6NParamEj。正如您所看到的,最后一个字母有所不同。

From the nm output it looks like the types are different - the executable has _ZN4EnvT6NParamEy while the library wants _ZN4EnvT6NParamEj. As you can see the last letter differs.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文