使用perl XS链接到C共享库 [英] linking to a C shared library using perl XS

查看:126
本文介绍了使用perl XS链接到C共享库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是PERL XS的新手,并且有一个关于调用用Ansi C编写的共享库(.so)的问题.我似乎找不到任何好的示例来确切地说明如何执行此操作.我浏览了该指南以开始使用(Hello World等),这里位于:

http://www.lemoda.net/xs/perlxstut/

我想对其进行修改,以在C共享库中调用名为cpro_supported的函数.

libpmap.so:

extern  int cpro_supported(int);

以下是一些基本知识:

Makefile.PL:

use 5.008005;
use ExtUtils::MakeMaker;
# See lib/ExtUtils/MakeMaker.pm for details of how to influence
# the contents of the Makefile that is written.
WriteMakefile(
    NAME              => 'test',
    VERSION_FROM      => 'lib/test.pm', # finds $VERSION
    PREREQ_PM         => {}, # e.g., Module::Name => 1.1
    ($] >= 5.005 ?     ## Add these new keywords supported since 5.005
      (ABSTRACT_FROM  => 'lib/test.pm', # retrieve abstract from module
       AUTHOR         => 'A. U. Thor <johnm@localdomain>') : ()),
    LIBS              => ['-lm'], # e.g., '-lm'
    DEFINE            => '', # e.g., '-DHAVE_SOMETHING'
    INC               => '-I.', # e.g., '-I. -I/usr/include/other'
# Un-comment this if you add C files to link with later:
    #OBJECT      => '$(O_FILES)' # link all the C files too
);

将LIBS parm修改为"-L到.so文件的路径",但这似乎无济于事.

test.xs:

#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

#include "ppport.h"


MODULE = test       PACKAGE = test      

int
cpro_it(monitor)
    int monitor
CODE:
    RETVAL = cpro_supported(monitor);
OUTPUT:
    RETVAL

void hello()
CODE:
printf("Hello, World!\n");

int
is_even(input)
    int input
CODE:
    RETVAL = (input % 2 == 0);
OUTPUT:
    RETVAL

void
round(arg)
    double  arg
CODE:
    if (arg > 0.0) {
        arg = floor(arg + 0.5);
    } else if (arg < 0.0) {
        arg = ceil(arg - 0.5);
    } else {
        arg = 0.0;
    }
OUTPUT:
    arg

test.t:

# Before `make install' is performed this script should be runnable with
# `make test'. After `make install' it should work as `perl test.t'

#########################

# change 'tests => 1' to 'tests => last_test_to_print';

use Test::More tests => 10;
use test;
BEGIN { use_ok('test') };

#########################

# Insert your test code below, the Test::More module is use()ed here so read
# its man page ( perldoc Test::More ) for help writing this test script.

is (test::is_even(0), 1);
is (test::is_even(1), 0);
is (test::is_even(2), 1);
my $i;
$i = -1.5; test::round($i); is( $i, -2.0 );
$i = -1.1; test::round($i); is( $i, -1.0 );
$i = 0.0; test::round($i);  is( $i,  0.0 );
$i = 0.5; test::round($i);  is( $i,  1.0 );
$i = 1.2; test::round($i);  is( $i,  1.0 );
my $mon;
$mon = test::cpro_it(23); is($mon,1);

运行make test时,出现以下错误:

PERL_DL_NONLAZY = 1/usr/bin/perl"-MExtUtils :: Command :: MM""-e""test_harness(0,'blib/lib','blib/arch')" t/*.t t/test ....

无法加载'/home/johnm/tmp/test/blib/arch/auto/test/test.so'进行模块测试:/home/johnm/tmp/test/blib/arch/auto/test/test.so:未定义符号:cpro_support在/usr/lib/perl5/5.8.5/i386-linux-thread-multi/DynaLoader.pm第230行. 在t/test.t第9行

在t/test.t第9行的要求中,编译失败.

BEGIN失败-在t/test.t第9行中,编译中止. 看起来您的测试在无法输出任何内容之前就已死亡. t/test ....可疑 测试返回的状态为255(wstat 65280,0xff00) 死了失败的测试1-10 10/10测试失败,0.00%可以

失败的测试统计信息Wstat总失败失败列表失败

t/test.t 255 65280 10 20 200.00%1-10 1/1测试脚本失败,0.00%可以. 10/10子测试失败,还可以0.00%.

make: * [test_dynamic]错误2

关于这里缺少什么的任何想法吗?

谢谢!

解决方案

您尚未告诉它链接到包含cpro_supported的库. (一个-L选项只是告诉链接器在哪里可以找到库;它实际上并没有告诉它与任何其他库的 link .您需要一个-l选项.)

MYEXTLIB适用于在模块构建过程中构建的C库,而不是系统上安装的库.尝试以下方法:

LIBS => ['-L/home/johnm/lib -lpmap -lmap -llang -ldispatch -led -lm -lncurses'],

I am new to PERL XS and have a question about calling a shared library (.so) written in Ansi C. I can't seem to find any good examples showing exactly how to do this. I went though the tutorial to get started (Hello World and all that) located here:

http://www.lemoda.net/xs/perlxstut/

I would like to modify it to call a function named cpro_supported in a C shared libarary.

libpmap.so:

extern  int cpro_supported(int);

Here are some basics:

Makefile.PL:

use 5.008005;
use ExtUtils::MakeMaker;
# See lib/ExtUtils/MakeMaker.pm for details of how to influence
# the contents of the Makefile that is written.
WriteMakefile(
    NAME              => 'test',
    VERSION_FROM      => 'lib/test.pm', # finds $VERSION
    PREREQ_PM         => {}, # e.g., Module::Name => 1.1
    ($] >= 5.005 ?     ## Add these new keywords supported since 5.005
      (ABSTRACT_FROM  => 'lib/test.pm', # retrieve abstract from module
       AUTHOR         => 'A. U. Thor <johnm@localdomain>') : ()),
    LIBS              => ['-lm'], # e.g., '-lm'
    DEFINE            => '', # e.g., '-DHAVE_SOMETHING'
    INC               => '-I.', # e.g., '-I. -I/usr/include/other'
# Un-comment this if you add C files to link with later:
    #OBJECT      => '$(O_FILES)' # link all the C files too
);

Modified the LIBS parm with '-L path to .so file' but this didn't seem to help.

test.xs:

#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

#include "ppport.h"


MODULE = test       PACKAGE = test      

int
cpro_it(monitor)
    int monitor
CODE:
    RETVAL = cpro_supported(monitor);
OUTPUT:
    RETVAL

void hello()
CODE:
printf("Hello, World!\n");

int
is_even(input)
    int input
CODE:
    RETVAL = (input % 2 == 0);
OUTPUT:
    RETVAL

void
round(arg)
    double  arg
CODE:
    if (arg > 0.0) {
        arg = floor(arg + 0.5);
    } else if (arg < 0.0) {
        arg = ceil(arg - 0.5);
    } else {
        arg = 0.0;
    }
OUTPUT:
    arg

test.t:

# Before `make install' is performed this script should be runnable with
# `make test'. After `make install' it should work as `perl test.t'

#########################

# change 'tests => 1' to 'tests => last_test_to_print';

use Test::More tests => 10;
use test;
BEGIN { use_ok('test') };

#########################

# Insert your test code below, the Test::More module is use()ed here so read
# its man page ( perldoc Test::More ) for help writing this test script.

is (test::is_even(0), 1);
is (test::is_even(1), 0);
is (test::is_even(2), 1);
my $i;
$i = -1.5; test::round($i); is( $i, -2.0 );
$i = -1.1; test::round($i); is( $i, -1.0 );
$i = 0.0; test::round($i);  is( $i,  0.0 );
$i = 0.5; test::round($i);  is( $i,  1.0 );
$i = 1.2; test::round($i);  is( $i,  1.0 );
my $mon;
$mon = test::cpro_it(23); is($mon,1);

When I run make test I receive the following error:

PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(0, 'blib/lib', 'blib/arch')" t/*.t t/test....

Can't load '/home/johnm/tmp/test/blib/arch/auto/test/test.so' for module test: /home/johnm/tmp/test/blib/arch/auto/test/test.so: undefined symbol: cpro_supported at /usr/lib/perl5/5.8.5/i386-linux-thread-multi/DynaLoader.pm line 230. at t/test.t line 9

Compilation failed in require at t/test.t line 9.

BEGIN failed--compilation aborted at t/test.t line 9. Looks like your test died before it could output anything. t/test....dubious Test returned status 255 (wstat 65280, 0xff00) DIED. FAILED tests 1-10 Failed 10/10 tests, 0.00% okay

Failed Test Stat Wstat Total Fail Failed List of Failed

t/test.t 255 65280 10 20 200.00% 1-10 Failed 1/1 test scripts, 0.00% okay. 10/10 subtests failed, 0.00% okay.

make: * [test_dynamic] Error 2

Any ideas on what is missing here??

Thx!!

解决方案

You haven't told it to link with the library that contains cpro_supported. (A -L option just tells the linker where it can find libraries; it doesn't actually tell it to link with any additional libraries. You need a -l option for that.)

MYEXTLIB is intended for C libraries that are built as part of the module's build process, not libraries installed on the system. Try this instead:

LIBS => ['-L/home/johnm/lib -lpmap -lmap -llang -ldispatch -led -lm -lncurses'],

这篇关于使用perl XS链接到C共享库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆