4

我试图在 AIX 5.1 机器上从 Perl 调用 C++ 库。我创建了一个非常简单的测试项目来尝试执行此操作。

我的 C++ 共享库 ( test.cpp):

#include <stdio.h>
#include <iostream>

void myfunc()
{
    printf("in myfunc()\n");
    std::cout << "in myfunc() also" << std::endl;
}

我的 SWIG 接口文件(test.i):

%module test
%{
void myfunc();
%}
void myfunc();

然后我像这样构建共享对象:

swig -c++ -perl test.i
g++ -c test_wrap.cxx -I/usr/opt/perl5/lib/5.6.0/aix/CORE -o test_wrap.o
g++ -c test.cpp -o test.o
ld -G -bI:/usr/opt/perl5/lib/5.6.0/aix/CORE/perl.exp -bnoentry -bexpall -lc_r test.o test_wrap.o -o test.so

此时,我有一个test.so应该可以在 perl 中加载的共享对象(通过生成的 SWIG test.pm)。我有一个非常简单的 perl 脚本来尝试加载共享对象并调用我正在导出的一个函数(test.pl):

#!/usr/bin/perl
use test;
test::myfunc();

当我运行时test.pl,我得到以下输出:

在 myfunc()
非法指令(核心转储)

如果我注释掉 中的std::cout用法myfunc,它可以正常工作。似乎在 C++ STL 中使用任何东西都会导致核心转储(我尝试只声明 a std::vectorand std::stringstream,两者都会导致核心转储)。我可以创建一个使用 STL 而没有任何问题的独立 C++ 可执行文件,只有在从 perl 加载时在我的共享对象中调用时,我才会遇到麻烦。

我也尝试过使用 xlc 而不是 gcc,但我得到了相同的结果。我在想我需要传递一些时髦的链接器标志以确保所有链接都正确发生?欢迎任何想法...

编辑:如果我使用gcc/链接xlc而不是直接调用链接器 ( ld),我会立即遇到分段错误。当 perl 试图简单地加载共享库时,它看起来像崩溃了。像上面那样调用ld是最接近工作的方法,但我认为我可能缺少一些库或 C++ 库的特殊 AIX 链接器标志。

Edit2:好的,我已经开始工作了。AIX 在链接方面非常脆弱。我最终想出了以下似乎工作正常的链接命令:

ld -G -bI:/usr/opt/perl5/lib/5.6.0/aix/CORE/perl.exp -bnoentry -bexpall -lC -lc -ldl test.o test_wrap.o -o test.so

我链接的库是最相关的。事实证明,提到库的顺序也非常重要(呃)。另请注意,这是针对 AIX 5.1 附带的 Perl 5.6.0 构建的。我已经尝试针对 Perl 5.8.8 构建同样简单的应用程序,但它不起作用。但是,我很确定更理智的链接方法(使用直接gcc/xlc而不是直接调用ld)似乎效果更好。所以这个问题似乎是 Perl 发行版或链接器或其他东西中的错误。

希望这将帮助一些被诅咒不得不使用 AIX 的可怜的灵魂......

4

2 回答 2

4

你不只是将你的 libstdc++ 添加到你的 ld 命令中吗?例如,-lstdc++

复制您的问题后,我在 Linux 上所做的是:

gcc -g -lstdc++ -shared test*.o -o test.so

然后问题就消失了。

(试图为 ld 获得正确的库列表是太多的工作,所以我只是告诉 gcc 为我做这件事。)

于 2008-10-08T22:10:19.950 回答
0

我对 SWIG 一无所知,但您可能还想检查它是否需要使用 cdecl(而不是 pascal、fastcall 或其他一些调用约定)的函数。在工具之间使用错误的工具可能会导致“坏事发生”(据我所知,通常是堆栈损坏)。

于 2008-10-08T23:53:53.390 回答