4

免責事項: perlmonksに問い合わせてください。

私の問題を適切に説明し、描写していることを願っています... XS では、コールバックに Perl 固有の関数がある外部ライブラリの関数にコールバックを送信しようとしています。XSUB は、外部 C 関数への関数ポインタとして渡されます。送信された XSUB コールバックは、次に「メイン」perl アプリケーションのサブにコールバックします。

void callback(){
    dSP;
    PUSHMARK(SP);
    call_pv("p_callback", G_DISCARD|G_NOARGS);
}

// example extern call

externFunc(&callback);

このセグメンテーション違反。外部ライブラリが呼び出されている perl 関数を理解していないためだと思います。ただし、C の `callback()` 関数を直接呼び出すと問題なく動作します。

外部ライブラリが Perl C 関数を「見る」ようにするためにできる魔法はありますか、それとも何か間違っていますか?

私がテストしているコードは次のとおりです。

use warnings;
use strict;

use Inline ('C' => 'DATA', libs => '-lwiringPi');

init();
setInterrupt(27, 3);

# direct call

callback();

# on() triggers the external function and sends
# it the callback

on(27);

sub p_callback {
    print "in perl callback\n";
}

__DATA__
__C__

#include <stdlib.h>
#include <stdio.h>
#include <wiringPi.h>

void init();
void on(int pin);
void off(int pin);
void setInterrupt(int pin, int edge);
void callback();

void init(){
    printf("in init\n");
    wiringPiSetup();
}
void on(int pin){
    pinMode(pin, 1);
    digitalWrite(pin, 1);
}

void off(int pin){
    digitalWrite(pin, 0);
    pinMode(pin, 0);
}

void setInterrupt(int pin, int edge){
    wiringPiISR(pin, edge, &callback);
}

void callback(){
    dSP;
    PUSHMARK(SP);
    call_pv("p_callback", G_DISCARD|G_NOARGS);
}

出力:

in init
in perl callback
Segmentation fault

コールバック内から perl 固有の C 呼び出しを削除し、「printf()」またはその他の純粋な C 作業を実行すると、セグメンテーション違反なしで処理が続行されます。

4

1 に答える 1

1

この質問に出くわしたばかりで、少し前に解決したので、自分の答えを出すと思いました。

exec_perl_callback()C関数内だけでなく、Perl コンテキストを設定するために欠落していた重要なビットがいくつかありました。

use warnings;
use strict;

use Inline 'C';
use Inline 'NoClean';

sub p_callback {
    print "hello, world from perl!\n";
}

exec_perl_callback('p_callback');

__END__
__C__

#define PERL_NO_GET_CONTEXT

PerlInterpreter * mine;

void callback(char* perl_callback){
    PERL_SET_CONTEXT(mine);

    dSP;
    ENTER;
    SAVETMPS;
    PUSHMARK(SP);
    PUTBACK;

    exec_perl_callback(perl_callback, G_DISCARD|G_NOARGS);

    FREETMPS;
    LEAVE;
}

出力:

hello world, from perl!
于 2017-06-06T19:23:27.150 に答える