2009-11-24 17 views
5

DÜZENLEME: Bunun için bir seçenek üzerinde verileri olan bir ticket oluşturdum.XS'de Geri Çağırma geri çağırma oluşturma

Gcxt, ileti dizisi boyunca saklanmadığından MY_CXT'nin geri çağrısını kullanma girişiminde updated the code var. Ancak bu segfaults, ENTER.

#include "EXTERN.h" 
#include "perl.h" 
#include "XSUB.h" 

#ifndef aTHX_ 
#define aTHX_ 
#endif 

#ifdef USE_THREADS 
#define HAVE_TLS_CONTEXT 
#endif 

/* For windows */ 
#ifndef SDL_PERL_DEFINES_H 
#define SDL_PERL_DEFINES_H 

#ifdef HAVE_TLS_CONTEXT 
PerlInterpreter *parent_perl = NULL; 
extern PerlInterpreter *parent_perl; 
#define GET_TLS_CONTEXT parent_perl = PERL_GET_CONTEXT; 
#define ENTER_TLS_CONTEXT \ 
     PerlInterpreter *current_perl = PERL_GET_CONTEXT; \ 
      PERL_SET_CONTEXT(parent_perl); { \ 
           PerlInterpreter *my_perl = parent_perl; 
#define LEAVE_TLS_CONTEXT \ 
             } PERL_SET_CONTEXT(current_perl); 
#else 
#define GET_TLS_CONTEXT   /* TLS context not enabled */ 
#define ENTER_TLS_CONTEXT  /* TLS context not enabled */ 
#define LEAVE_TLS_CONTEXT  /* TLS context not enabled */ 
#endif 

#endif 


#include <SDL.h> 

#define MY_CXT_KEY "SDL::Time::_guts" XS_VERSION 


typedef struct { 
void* data; 
SV* callback; 
Uint32 retval; 
} my_cxt_t; 

static my_cxt_t gcxt; 

START_MY_CXT 


static Uint32 add_timer_cb (Uint32 interval, void* param) 
{ 

     ENTER_TLS_CONTEXT 
     dMY_CXT; 
     dSP; 
     int back; 
     ENTER; //SEGFAULTS RIGHT HERE! 
     SAVETMPS; 
     PUSHMARK(SP); 
     XPUSHs(sv_2mortal(newSViv(interval))); 
     PUTBACK; 

     if (0 != (back = call_sv(MY_CXT.callback,G_SCALAR))) { 
     SPAGAIN; 
     if (back != 1) Perl_croak (aTHX_ "Timer Callback failed!"); 
     MY_CXT.retval = POPi;  
     } else { 
     Perl_croak(aTHX_ "Timer Callback failed!"); 
     } 

     FREETMPS; 
     LEAVE; 

     LEAVE_TLS_CONTEXT 
     dMY_CXT; 
     return MY_CXT.retval; 

} 

MODULE = SDL::Time PACKAGE = SDL::Time PREFIX = time_ 

BOOT: 
{ 
    MY_CXT_INIT; 
} 


SDL_TimerID 
time_add_timer (interval, cmd) 
    Uint32 interval 
    void *cmd 
    PREINIT: 
     dMY_CXT; 
    CODE: 
     MY_CXT.callback=cmd;  
     gcxt = MY_CXT; 
     RETVAL = SDL_AddTimer(interval,add_timer_cb,(void *)cmd);  
    OUTPUT: 
     RETVAL 

void 
CLONE(...) 
    CODE: 
    MY_CXT_CLONE; 

Geri arama için ENTER'a girer girmez bu segment hataları. değişkenin ayrı kopyaları ile aksi perl eserleri -

use SDL; 
use SDL::Time; 

SDL::init(SDL_INIT_TIMER); 
my $time = 0; 
SDL::Timer::add_timer(100, sub { $time++; return $_[0]}); 
sleep(10); 
print "Never Prints"; 

Çıktı

$ 

o $ sefer paylaşılan bir değişken olması gerekir

$ Never Prints 
+0

orada zamanlayıcı ayarlama ve $ zaman baskı arasında bir "uyku" olması gerekmez mi? – tsee

+1

Programınız engellenmiyor, ancak yalnızca kabuğu geri atlıyorsa, bu bir sert çökme gibi gözüküyor ya da aksi takdirde perl tamamen kontrolden çıkmaz. Bir hata ayıklama perl deneyin ve gdb içinde şeyler koşma. – tsee

+0

Tamam Bunu deniyorum ama hiçbir şey bana tamamen farklı bir fikir verdi. Bu soruya bileti ekledim. – kthakore

cevap

-1

Perl interpreter thread ve threads :: shared kullanarak bir çözüm bulduk. Bu

Time.xs

Ayrıca burada bu kodu kullanarak bir komut dosyası örneğidir bakınız.

TestTimer.pl

0

olmalıdır olduğunu.

+0

um ... Ne demek istediğine dair hiçbir fikrim yok. Bazı kodları koymak ister misin? – kthakore

+0

Sonunda 200 uyku ekleyin ve herhangi bir çıktı görüp görmediğinize bakın. – weismat

+0

hayır yok. Uyumaz bile. :( – kthakore

4

Hızlı yorumlar:

  • bir Perl yorumlayıcı nesne bağlamı dışında Perl yapılar (SV, AV, HV, ...) kullanmayın. Yani C-seviyesi statik veri olarak kullanmayın. Bir iş parçacığı içeriğinde patlayacak. Güven bana, orada bulundum.
  • perlxs manpage'deki "XS'deki Statik Verilerin Güvenli Olarak Depolanması" bölümüne bakın.
  • Yaptığınız şeylerden bazıları, perlapi'nin bakış açısından çok genel olmayan bir şekilde görünüyor. Yine de emin değilim.
+0

lütfen güncellemeye bakın – kthakore

0

Bunun için tercih ettiğim yol, verileri PL_modglobal karma dosyasında saklamaktır. Mevcut tercümana otomatik olarak bağlanır.