in reply to Re^2: XS: Passing an external library's function a Perl XS callback
in thread SOLVED: XS: Passing an external library's function a Perl XS callback

Under threads, perl code needs the appropriate context. If you callback to code referenced from one thread whilst running under another, you will have the wrong context and crash.

Read down from here, it may help. There is lots of good information, but it evolves out over a long back&forth thread.


With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority". I knew I was on the right track :)
In the absence of evidence, opinion is indistinguishable from prejudice.
  • Comment on Re^3: XS: Passing an external library's function a Perl XS callback

Replies are listed 'Best First'.
Re^4: (SOLVED) XS: Passing an external library's function a Perl XS callback
by stevieb (Canon) on Aug 15, 2016 at 21:33 UTC

    Thanks BrowserUK!!!!! That's it!!

    Just before I came back and checked here, I was finding that it was the instance of the interpreter so I was just about to head down that path. You made it extraordinarily easy for me. I just had to add two lines (the PerlInterpreter line and the PERL_SET_CONTEXT line. Here's the working pthread test script. After I clean up my original code that started this thread, I'll update the thread.

    use warnings; use strict; use Inline (C => 'DATA', libs => '-lpthread'); create_thread('blah'); sub blah { print "perl callback\n"; } __DATA__ __C__ #include <stdio.h> #include <pthread.h> PerlInterpreter *saved; void wrapper(void *sub_name_ptr){ char *sub_name = (char *)sub_name_ptr; PERL_SET_CONTEXT(saved); printf("threaded ok, sub: %s\n", sub_name); dSP; PUSHMARK(SP); PUTBACK; call_pv(sub_name, G_DISCARD|G_NOARGS); FREETMPS; LEAVE; return NULL; } int create_thread(char *subname){ pthread_t sub_thread; if(pthread_create(&sub_thread, NULL, wrapper, subname)) { fprintf(stderr, "Error creating thread\n"); return 1; } if(pthread_join(sub_thread, NULL)) { fprintf(stderr, "Error joining thread\n"); return 2; } return 0; }
        So to the top add #define PERL_NO_GET_CONTEXT

        PERL_NO_GET_CONTEXT doesn't work with Inline::C.
        You can do pre_head => '#define PERL_NO_GET_CONTEXT 1', and that will get the directive inserted at the very beginning of the generated XS file (where it needs to be).
        But Inline::C is not presently capable of generating XS code that meets the requirements of having PERL_NO_GET_CONTEXT defined.
        I filed a bug report about this some time back.

        InlineX::C2XS contains a rather flakey, fragile, sub-standard hack that does accommodate PERL_NO_GET_CONTEXT.
        It's functional enough for my purposes, but it does impose some limitations on the way one formats one's C code.

        Cheers,
        Rob