【问题标题】:XS: Passing an external library's function a Perl XS callbackXS:向外部库的函数传递 Perl XS 回调
【发布时间】:2016-12-21 03:21:42
【问题描述】:

免责声明:在perlmonks 询问。

我希望我正确地描述和描述了我的问题...在 XS 中,我试图将回调发送到外部库的函数中,其中回调具有 Perl 特定的函数。 XSUB 作为函数指针传递给外部 C 函数。依次发送的 XSUB 回调回调 `main` perl 应用程序中的 sub:

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 工作,那么事情会继续进行而不会出现段错误。

【问题讨论】:

  • 从 ISR 调用 Perl 似乎是个坏主意。有很多事情可能会出错。例如:您是否在运行线程化 Perl 并且 ISR 是否从不同的线程调用?
  • @nwellnhof 我是中断处理的新手,也是一个 C 新手,所以这是一个很大的学习曲线 :) 你已经指出,在我继续之前我需要在这里做一些研究。谢谢!

标签: c perl callback xs


【解决方案1】:

刚刚遇到这个问题,我想我会给出自己的答案,因为我前段时间确实解决了它。

在设置 Perl 上下文以及在 C exec_perl_callback() 函数中,我缺少一些重要的部分。

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!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-03-24
    • 1970-01-01
    • 1970-01-01
    • 2017-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-31
    相关资源
    最近更新 更多