Разоблачение функции c на Perl с использованием XS

У меня есть несколько функций c в этом формате:

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

где int тип возвращаемого значения;

result[] содержит строку, которую заполняет функция

что лучше всего написать такую ​​функцию как XS и выставить ее на Perl:

  1. получить возвращаемое значение функции

  2. получить значение char [] для perl

Я попробовал ниже, но ниже только вернуть возвращаемое значение

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

Любая помощь будет оценена?

3 ответа

Решение

Создайте новый каталог и скопируйте в него следующие файлы:

./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

Программа h2xs может быть использован для создания модуля perl/XS, который действует как обертка вокруг вашего C-кода. Я думаю, что вы захотите создать заголовочный файл с прототипами ваших функций.

Прочитайте справочные страницы для h2xs для деталей. Кроме того, посмотрите здесь

Функция perl (также функция XS) может возвращать более одного значения.
Вам нужно будет использовать PPCODE вместо CODE и поместить несколько переменных в стек в качестве результата. см. документацию perlxs для PPCODE, например.

Другие вопросы по тегам