加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

PERL XS tutorial

发布时间:2020-12-15 20:49:39 所属栏目:大数据 来源:网络整理
导读:XS: eXternal Subroutine,也叫做xsub. 它是perl代码中调用c或者c++ 子例程的接口。 在许多情形下,如一些CPU或内存密集型的任务,单纯使用PERL很难满足这些需求,这时,可以使用c或c++语言完成该任务,提供好接口后,通过XS接口可以直接被PERL 代码以module

XS: eXternal Subroutine,也叫做xsub. 它是perl代码中调用c或者c++ 子例程的接口。

在许多情形下,如一些CPU或内存密集型的任务,单纯使用PERL很难满足这些需求,这时,可以使用c或c++语言完成该任务,提供好接口后,通过XS接口可以直接被PERL 代码以module的形式调用。

环境:

OS :debian 5 lenny?? PERL: This is perl,v5.10.0 built for i486-linux-gnu-thread-multi

创建一个perl 扩展, 通过命令h2xs

h2xs –A –n Mytest

其中:-A 选项是 --omit-autoload , -n 选项用来指定新的module的名称,这里是Mytest。

生成文件的列表:

Changes: 记录新建扩展的修订日志。如果你使用版本管理工具,如cvs,svn,可以不关心这个文件。

MANIFEST:

Makefile.PL: 通过该文件可以生成Makefile。命令perl Makefile.PL

use 5.010000;
use ExtUtils::MakeMaker;
# See lib/ExtUtils/MakeMaker.pm for details of how to influence
# the contents of the Makefile that is written.
WriteMakefile(
??? NAME????????????? => 'Mytest',
??? VERSION_FROM????? => 'lib/Mytest.pm',# finds $VERSION
??? PREREQ_PM???????? => {},# e.g.,Module::Name => 1.1
??? ($] >= 5.005 ????? ## Add these new keywords supported since 5.005
????? (ABSTRACT_FROM? => 'lib/Mytest.pm',# retrieve abstract from module
?????? AUTHOR???????? => 'root ') : ()),
??? LIBS????????????? => ['-lm'],'-lm'
??? DEFINE??????????? => '','-DHAVE_SOMETHING'
??? INC?????????????? => '-I.','-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
);
@>

Mytest.xs

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

#include "ppport.h"

MODULE = Mytest???????? PACKAGE = Mytest

/**Manually added functions in XS macro language**/

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

ppport.h

README

t/ : 单元测试目录

lib/: perl 扩展module的目录, PM文件。

生成Makefile文件:

perl Makefile.PL

输出:

Checking if your kit is complete...
Looks good
Writing Makefile for Mytest

编译

make

输出:

cp lib/Mytest.pm blib/lib/Mytest.pm
/usr/bin/perl /usr/share/perl/5.10/ExtUtils/xsubpp? -typemap /usr/share/perl/5.10/ExtUtils/typemap? Mytest.xs > Mytest.xsc && mv Mytest.xsc Mytest.c
Please specify prototyping behavior for Mytest.xs (see perlxs manual)
cc -c? -I. -D_REENTRANT -D_GNU_SOURCE -DDEBIAN -fno-strict-aliasing -pipe -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -O2 -g?? -DVERSION=/"0.01/" -DXS_VERSION=/"0.01/" -fPIC "-I/usr/lib/perl/5.10/CORE"?? Mytest.c
Running Mkbootstrap for Mytest ()
chmod 644 Mytest.bs
rm -f blib/arch/auto/Mytest/Mytest.so
cc? -shared -O2 -g -L/usr/local/lib Mytest.o? -o blib/arch/auto/Mytest/Mytest.so??????? /
?????????? -lm????????? /

chmod 755 blib/arch/auto/Mytest/Mytest.so
cp Mytest.bs blib/arch/auto/Mytest/Mytest.bs
chmod 644 blib/arch/auto/Mytest/Mytest.bs
Manifying blib/man3/Mytest.3pm

编写Mytest Module 的单元测试文件 t/Mytest.t

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

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

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

use Test::More tests => 9;
BEGIN { use_ok('Mytest') };

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

# 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(&Mytest::is_even(0),1);
is(&Mytest::is_even(1),0);
is(&Mytest::is_even(2),1);

$i = -1.5 ; &Mytest::round($i); is($i,-2.0);
$i = -1.1 ; &Mytest::round($i); is($i,-1.0);
$i = 0.0 ; &Mytest::round($i); is($i,0.0);
$i = 0.5 ; &Mytest::round($i); is($i,1.0);
$i = 1.2 ; &Mytest::round($i); is($i,1.0);

执行测试:

make test

输出:

PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(0,'blib/lib','blib/arch')" t/*.t
t/Mytest....ok
All tests successful.
Files=1,Tests=9,? 0 wallclock secs ( 0.02 cusr +? 0.01 csys =? 0.03 CPU)

?

最后:

make install 来安装perl 扩展

?

根据c lib 的header file创建perl module

新建的module名称为Mytest3 建立目录结构

mkdir Mytest3

cd Mytest3

mkdir testlib

cd testlib

Mytest3完成后的目录结构:

Mytest3
?? ---> testlib

在testlib 下 创建你的testlib库,这里仅创建一个简单test.c 和它的header test.h,如下:

test.c

#include "test.h"
#include

int
foo(int a,int b)
{
??? printf("in foo(int,int)/n");
??? return a + b;
}

test.h

#ifndef TEST_H
#define TEST_H

extern int foo(int,int );
#endif

在testlib目录下创建一个Makefile.PL,如下:

use ExtUtils::MakeMaker;

$Verbose = 1;
WriteMakefile(
??? NAME => 'Mytest3::testlib',
??? SKIP => [qw(all static static_lib dynamic dynamic_lib)],
??? clean => {FILES => 'libtestlib$(LIB_EXT)'},
);

sub MY::top_targets {
'
all :: static

pure_all :: static

static :: libtestlib$(LIB_EXT)

libtestlib$(LIB_EXT) : $(O_FILES)
??????? $(AR) cr libtestlib$(LIB_EXT) $(O_FILES)
??????? $(RANLIB) libtestlib$(LIB_EXT)
';
}

perl Makefile.PL; make 生成libtestlib.a archive文件。

使用h2xs 生成perl module 框架:

cd到Mytest3的父目录,执行h2xs –O –n Mytest3 Mytest2/testlib/test.h,其中-O选项表示覆盖已经存在的extension 目录

完成后cd到Mytest3目录, 编辑刚刚自动生成的Makefile.PL :

use 5.010000;
use ExtUtils::MakeMaker;
# See lib/ExtUtils/MakeMaker.pm for details of how to influence
# the contents of the Makefile that is written.
WriteMakefile(
??? NAME????????????? => 'Mytest3',
??? VERSION_FROM????? => 'lib/Mytest3.pm',Module::Name => 1.1
??? ($] >= 5.005 ????? ## Add these new keywords supported since 5.005
????? (ABSTRACT_FROM? => 'lib/Mytest3.pm',# retrieve abstract from module
?????? AUTHOR???????? => 'root ') : ()),
??? LIBS????????????? => [''],'-lm'
??? DEFINE??????????? => '','-DHAVE_SOMETHING'
??? INC?????????????? => '-I.','-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
??? MYEXTLIB????????? => 'testlib/libtestlib$(LIB_EXT)',
);
if? (eval {require ExtUtils::Constant; 1}) {
? # If you edit these definitions to change the constants used by this module,
? # you will need to use the generated const-c.inc and const-xs.inc
? # files to replace their "fallback" counterparts before distributing your
? # changes.
? my @names = (qw());
? ExtUtils::Constant::WriteConstants(
???????????????????????????????????? NAME???????? => 'Mytest3',
???????????????????????????????????? NAMES??????? => /@names,
???????????????????????????????????? DEFAULT_TYPE => 'IV',
???????????????????????????????????? C_FILE?????? => 'const-c.inc',
???????????????????????????????????? XS_FILE????? => 'const-xs.inc',
????????????????????????????????? );
@>

}
else {
? use File::Copy;
? use File::Spec;
? foreach my $file ('const-c.inc','const-xs.inc') {
??? my $fallback = File::Spec->catfile('fallback',$file);
??? copy ($fallback,$file) or die "Can't copy $fallback to $file: $!";
? }
}

sub MY::postamble {
'
$(MYEXTLIB) : testlib/Makefile
??????? cd testlib && $(MAKE) $(PASSTHRU)
'
}

其中, 增加MYEXTLIB使得h2xs生成的Makefile.PL 可以找到这里的c lib: testlib

修改生成的Mytest3.xs 文件:

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

#include "ppport.h"

#include "testlib/test.h" //using the relative directory

#include "const-c.inc"

MODULE = Mytest3??????????????? PACKAGE = Mytest3

INCLUDE: const-xs.inc

int
foo(a,b)
??? int a
??? int b
OUTPUT:
??? RETVAL

定义PERL的xs接口,使得perl code可以调用testlib的foo函数。

?

.xs 代码文件的结构

如Mytest3.xs所示:

MODULE = Mytest3??????????????? PACKAGE = Mytest3 注意这一行。

在该行之前的代码片段将被xsubpp保存直接输出到最终的c source code当中。

在该行之后会被xsubpp根据perl API convention翻译成c souce code。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读