Я пытаюсь вызвать библиотеку C ++ из Perl на машине с AIX 5.1. Я создал очень простой тестовый проект, чтобы попробовать это.
Моя общая библиотека 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 вызывает дамп ядра (я пытался просто объявить std::vector
и std::stringstream
, оба результата приводят к дампу ядра). Я могу создать автономный исполняемый файл C ++, который использует STL без проблем, только когда он вызывается в моем общем объекте при загрузке из perl, я попадаю в проблему.
Я также пытался использовать xlc вместо gcc, но получаю тот же результат. Я думаю, что есть какой-то прикольный флаг компоновщика, который мне нужно передать, чтобы убедиться, что вся связь происходит правильно? Любые идеи приветствуются ...
Редактировать: Если я создаю ссылку, используя gcc
/ xlc
вместо прямого вызова компоновщика (ld
), я немедленно получаю ошибку сегментации. Похоже, что происходит сбой, когда Perl пытается просто загрузить общую библиотеку. Вызов ld
, как я описал выше, наиболее близок к тому, чтобы он работал, но я думаю, что мне не хватает некоторых библиотек или специальных флагов компоновщика AIX для библиотек C ++.
Edit2: Хорошо, у меня это работает. AIX очень хрупкая, когда дело доходит до ссылок. В итоге я пришел к следующей команде link, которая, кажется, работает правильно:
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
Библиотеки, с которыми я связан, являются наиболее актуальными. Оказывается, порядок, в котором упоминаются библиотеки, также очень важен (тьфу). Также обратите внимание, что это делается на Perl 5.6.0, который поставляется с AIX 5.1. Я пытался создать это же простое приложение для Perl 5.8.8, и оно не работает. Тем не менее, я уверен, что гораздо более вменяемый метод связывания (использующий прямой gcc
/ xlc
вместо прямого вызова ld
), кажется, работает лучше. Таким образом, эта проблема является ошибкой в дистрибутиве Perl или компоновщике или что-то в этом роде.
Надеюсь, это поможет проклятому душевнобольному человеку работать с AIX ...