【问题标题】:exposing c function on perl using XS使用 XS 在 perl 上公开 c 函数
【发布时间】:2014-07-18 20:07:52
【问题描述】:

我有多个这种格式的 c 函数:

int function(const char* input, size_t len, char result[]) ;

其中int 是返回类型;

result[] 包含函数填充的字符串

写XS这样的函数并在perl上公开它的最佳方法是:

  1. 获取函数的返回值

  2. 在 perl 上获取 char result[] 值

我尝试了下面但下面只返回返回值

int
my_function(a,b,c)
    const char *  a
    long            b
    const char *    c
    CODE:
    RETVAL =function(a,b,c)
    OUTPUT:
    RETVAL

任何帮助将不胜感激?

【问题讨论】:

    标签: perl xs


    【解决方案1】:

    创建一个新目录,并将以下文件复制到其中:

    ./Example.xs

    #include "EXTERN.h"
    #include "perl.h"
    #include "XSUB.h"
    #include "ppport.h"    
    #include "const-c.inc"
    
    int my_function(const char* input, size_t len, char result[])
    {
        strcpy(result, "the answer");
        return 42;
    }
    
    MODULE = Acme::XS::Example        PACKAGE = Acme::XS::Example
    
    INCLUDE: const-xs.inc
    PROTOTYPES: DISABLE
    
    void
    my_xsub (input, len)
        char *input
        int len
    PPCODE:
    {
        char result[10];
        int got = my_function(input, len, result);
    
        /* create a new scalar from an int, and push onto stack */
        PUSHs( newSViv(got) );
        /* create a new scalar from a string, and push onto stack */
        PUSHs( newSVpv(result, 0) );
    
        XSRETURN(2);  /* two items returned */
    }
    

    ./lib/Acme/XS/Example.pm

    use 5.010001;
    use strict;
    use warnings;
    use XSLoader ();
    
    package Acme::XS::Example;
    our $VERSION   = '0.001';
    __PACKAGE__->XSLoader::load($VERSION);
    1;
    

    ./t/basic.t

    use strict;
    use warnings;
    use Test::More;
    
    use_ok('Acme::XS::Example');
    
    my @results = Acme::XS::Example::my_xsub("Hello world", 666);
    
    is_deeply(
        \@results,
        [ 42, "the answer" ],
        "got expected results",
    ) or diag explain(\@results);
    
    done_testing;
    

    ./Makefile.PL

    use strict;
    use Devel::PPPort;
    use ExtUtils::MakeMaker 6.6303;
    use ExtUtils::Constant;
    
    Devel::PPPort::WriteFile();
    
    ExtUtils::Constant::WriteConstants(
        NAME         => 'Acme::XS::Example',
        NAMES        => [],
        DEFAULT_TYPE => 'IV',
        C_FILE       => 'const-c.inc',
        XS_FILE      => 'const-xs.inc',
    );
    
    WriteMakefile(
        NAME       => 'Acme::XS::Example',
        DISTNAME   => 'Acme-XS-Example',
        VERSION    => '0.001',
        ABSTRACT   => 'an example XS thingy',
        AUTHOR     => ['Toby Inkster <tobyink@cpan.org>'],
        LICENSE    => 'perl_5',
        MIN_PERL_VERSION  => '5.010001',
        PREREQ_PM  => {
            'XSLoader'             => 0,
        },
        TEST_REQUIRES => {
            'Test::More'           => '0.96',
        },
        CONFIGURE_REQUIRES => {
            'Devel::PPPort'        => 0,
            'ExtUtils::Constant'   => 0,
            'ExtUtils::MakeMaker'  => '6.6303',
        },
        LIBS       => [''],
        DEFINE     => '',
        INC        => '-I.',
        test       => { TESTS => "t/*.t" },
        clean      => { FILES => 'const-c.inc const-xs.inc ppport.h' },
    );
    

    有你的骨架可以玩。 :-)

    构建和测试它:

    perl Makefile.PL
    make
    make test
    

    【讨论】:

      【解决方案2】:

      程序h2xs 可用于创建一个perl/XS 模块,该模块充当C 代码的包装器。我认为您需要创建一个包含函数原型的头文件。

      阅读h2xs 的手册页了解详情。另外,看看here

      【讨论】:

        【解决方案3】:

        perl 函数(也是 XS 函数)可以返回多个值。
        您将需要使用 PPCODE 而不是 CODE,并将多个变量作为结果压入堆栈。例如,请参阅 PPCODE 的 perlxs 文档。

        【讨论】:

          猜你喜欢
          • 2018-03-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-12-21
          • 1970-01-01
          • 1970-01-01
          • 2014-08-25
          • 1970-01-01
          相关资源
          最近更新 更多