2016-08-14 56 views
4

聲明:通過perlmonks詢問。XS:將外部庫的函數傳遞給Perl XS回調

我希望我正確地描述和描述我的問題......在XS中,我試圖將回調發送到外部庫的函數中,其中回調函數具有Perl特定功能。 XSUB作爲函數指針傳遞給外部C函數。反過來發送的XSUB回調回調子在`main` 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作品,事情沒有segfault就會繼續。

+2

調用轉換爲Perl從ISR似乎是一個壞主意。有很多事情可能會出錯。例如:你是否正在運行一個線程化的Perl,並且是從另一個線程調用的ISR? – nwellnhof

+0

@nwellnhof我是全新的中斷處理,也是一個C newb,所以這是一個很大的學習曲線:)你已經指出,我需要在這裏做一些研究之前,我繼續。謝謝! – stevieb

回答

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!