gpt4 book ai didi

perl - 在 XS 中创建线程回调

转载 作者:行者123 更新时间:2023-12-03 13:00:59 25 4
gpt4 key购买 nike

编辑:我创建了一个 ticket为此,它有关于这种做事方式的替代方法的数据。

我有 updated the code试图使用 MY_CXT 的回调,因为 gcxt 没有跨线程存储。但是,这在 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;

一旦我进入 ENTER 进行回调,这个段错误就会发生。
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";

输出是
$

它应该是
$ Never Prints

最佳答案

快速评论:

  • 不要在 Perl 解释器对象的上下文之外使用 Perl 结构(SV、AV、HV...)。 IE。不要将其用作 C 级静态数据。它会在线程上下文中爆炸。相信我,我去过那里。
  • 查看 perlxs 中的“在 XS 中安全存储静态数据”部分联机帮助页。
  • 从 perlapi 的角度来看,你正在做的一些事情看起来相当不公开。不过,我不太确定。
  • 关于perl - 在 XS 中创建线程回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1791114/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com