2015-03-16 3 views
2

У меня есть библиотека Perl, написанная на C и внутри файла XS. Я объявлял функцию обратного вызова для вызова функций Perl из кода C. Когда эта функция вызывается из кода C (многопоточная):Вызов функции Perl из C сбоя продукта

char * 
callbackfunc(void *fun, char **args) 
{ 
    dSP; 

    int count,i; 
    char *s; 

    ENTER; 
    SAVETMPS; 

    PUSHMARK(SP); 
    for(i=0;args[i];++i) { 
    XPUSHs(sv_2mortal(newSVpv(args[i],0))); 
    } 
    PUTBACK; 

    count = call_sv(fun,G_SCALAR|G_EVAL); 

    SPAGAIN; 

    s = NULL; 
    if(count > 1) 
    croak("callback may return only single value\n"); 
    if(count==1) { 
    s = strdup(POPp); 
    } 

    PUTBACK; 
    FREETMPS; 
    LEAVE;  
    return s; 
} 

я получаю аварии на ЦОС макросъемки:

#0 callbackfunc (fun=0x2416a58, args=0x7f3a0cfa9a10) at MyLibrary.xs:24 
24 dSP; 

В дизассемблере это похоже на какой-нить конкретных данных не найдены:

push %r15 
push %r14 
mov %rdi,%r14 
push %r13 
mov %rsi,%r13 
push %r12 
push %rbp 
push %rbx 
sub $0x8,%rsp 
mov 0x2015dd(%rip),%rbx 
mov (%rbx),%edi 
callq 0x7f3a0e37f550 <[email protected]> 
mov (%rbx),%esi 
mov (%rax),%r15 // here is crash because %rax is 0x0 
+0

Эта строка очень подозрительна: 'for (i = 0; args [i]; ++ i)', вы имеете в виду 'for (i = 0; i

+0

@AlterMann, возможно, вы правы, но в настоящее время он не попал в него, потому что он разбился очень рано. –

+0

Hooray для использования '++ i' вместо' i ++ ' – Borodin

ответ

2

Вы, вероятно, забыли рассказать о своей теме о текущем интерпретаторе Perl. perlembed man page говорит:

PERL_SET_CONTEXT (с интерполяцией) также следует называть всякий раз, когда интерполяция используется потоком, который не создал его (с помощью perl_alloc() или более эзотерической perl_clone()).

Также обратите внимание, что вызов Perl из C не является потокобезопасным. Убедитесь, что правильная фиксация установлена.

EDIT: Если вы не создавали переводчику самостоятельно, вы можете получить void * к интерпретатору с помощью макроса PERL_GET_CONTEXT. Если вы используете только один интерпретатор, вы можете добавить код в раздел загрузки XS, чтобы сохранить это значение в глобальном. Если у вас несколько интерпретаторов (или хотите поддерживать fork в Windows), вам необходимо отслеживать текущий интерпретатор при регистрации обратного вызова.

+0

Я добавил некоторые подробности: этот код объявлен внутри библиотеки Perl. Поэтому я сам не создаю интерпретатор, он уже создан. Как я мог установить этот контекст для такого случая? –

+0

@JohnTracid Посмотреть мою правку. – nwellnhof

Смежные вопросы