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'], # 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
);

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', # finds $VERSION
    PREREQ_PM         => {}, # e.g., 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              => [''], # 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
    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。

PERL XS tutorial相关推荐

  1. 如何运行Perl和查看帮助

    *[Perl入门]如何运行Perl和获得帮助 by endo@kyxk.net **如何运行Perl 本来单独写这一章的主要目的是介绍Windows下运行Perl的配置,不过既然上面版大已经 给出了一 ...

  2. google的开源工程,真多

    http://blog.drhack.net/google-open-source-projects-you-knew-that/这个页面介绍了google的开源工程,真多,也很实用. Text Fi ...

  3. 一系列用于Fuzzing学习的资源汇总

    本文主要是向大家推荐一系列,用于fuzzing和Exploit开发初始阶段学习的资源合集,其中将包括相关的书籍,课程 – 免费或收费的,视频,工具,教程,以及一些供大家练习使用的靶机应用. fuzzi ...

  4. LAMP平台下构建Postfix邮件服务器

    前言: 本人之前已经做过这个实验,只是版本不同,今天本来想用全新版本的源码包做实验,但是以httpd-2.4.2.tar.gz的源码包在配置虚拟主机这一块我不知道如何配置,按照以前的配置总是报错:AH ...

  5. 柯志亨老师-- NS2 教學手冊

    感谢柯志亨老师! NS2教學手冊( NS2 Learning Guide) [快速連結區] My works中文影音教學區Q&A for my worksMy BookMy TalksForu ...

  6. SWIG入门文档(翻译自官方网站)

    SWIG简要文档 因为项目需要使用python来调用C/C++函数,经过调研发现swig是合适的方案,为了记录下学习的过程,所以有了这个文档. 我仅将里面的重要部分翻译了,章节序号对应原文档. 原文档 ...

  7. Geo Location 地理位置信息小结

    周末调研了一下Geo Location 地理位置信息方面的内容,自己小结一下. 一.通过 IP 地址获得用户的地理位置信息 也就是根据用户的IP,通过IP数据库查询获得信息.一般IP数据库中, 每条记 ...

  8. 计算机类免费电子书共享

    列表最早来自stackoverflow上的一个问题:List of freely available programming books 现在在github上进行维护:free-programming ...

  9. perlretut - Perl regular expressions tutorial ---- 中文版

    简单的单词匹配 最简单的正则就是一个单词,或者更通用一点,一个字符序列.一个仅包含某个单词的正则可以匹配包含那个单词的任意字符串: "Hello World" =~ /World/ ...

最新文章

  1. dropdown.js
  2. 交换机软件IOS升级更简化了
  3. 国睿驰120gb固态硬盘测试软件,系统盘首选 国睿驰120GB固态硬盘测试
  4. Qt Creator自定义构建过程
  5. java x锁_基于Java名称的锁?
  6. python requests 代理超时_python requests 超时与重试
  7. yum 找不到程序,yum更换国内阿里源
  8. Java Web学习总结(43)—— Restful API 版本控制
  9. android ListView和GridView拖拽移位具体实现及拓展
  10. PLSQL DEVELOPER编辑器的自动替换文件
  11. 每天多采一半油!中东联手中国阿里云的研究有望降低国际油价
  12. 项目初始阶段、项目立项
  13. 中国的KNX 智能家居系统,将实现最高级别的安全保障!
  14. Sybase ASE 12.5.4数据库安装备份还原操作步骤
  15. 大数据时代下的企业管理创新
  16. Win10更新补丁错误代码0x80070643解决方法
  17. 韩顺平老师讲解13个自学编程的坑
  18. 计算机音乐谱童话镇,《童话镇》歌曲简谱
  19. 原生JS写《像素鸟》的小游戏(下落的小鸟)
  20. Android实习周记:第一周,井底之蛙上岸

热门文章

  1. 如何使用 JavaScript 创建水平和垂直标签?
  2. 谷歌浏览器的用户安利一个非常好用的插件
  3. 网络安全控制网管解决方案
  4. 张艾迪(创始人): 辍学的互联网天才
  5. 黑暗背景(所有暗主题cobalt,dracula...)Rstudio查看对象窗口viewer没有滚动条,白亮背景就有(所有白主题chrome,cloud)。R版本[64-bit] R-3.6.0
  6. 市审计局充分利用大数据助力扶贫和“十个全覆盖”审计工作
  7. 分享点22年计算机考研经验(反面)
  8. 计算机网络:P3.1-数据链路层(上)
  9. 计算机网络-数据链路层功能概述
  10. MySQL的默认用户名和密码的什么?