in reply to Re^2: perl->c->perl
in thread perl->c->perl

Inline::C lets you write plain C functions too, and to callback from C to Perl you need a plain C function that calls one of the "call into Perl" subroutines. So callbacks from C to Perl are just as possible (and easier to write) with Inline::C instead of XS.

The trick is getting at context. If you are lucky, then the callback interface allows you to have a context indicator passed to the callback. If not, then things get ratherr complicated...

Unfortunately, I've run out of time for now...

- tye        

Replies are listed 'Best First'.
Re^4: perl->c->perl (Inline::C)
by jpollack (Novice) on Dec 27, 2005 at 03:02 UTC
    Thanks for the advice.

    I tried using Inline::C, but it's still not quite working. The wrappers around a few of the library routines (initialization, for example) do appear to be working correctly, however, it crashes whenever running the C callback function. In the C callback function, what it should be doing is copying the necessary data to perl variables, doing a "perl_call_sv" to call the user specified perl callback function, then copying the data back from perl variables. What's happening though is that the program crashes whenever I try to do anything in the C language callback function.

    No matter what code I put in the C callback, I get ``unhandled exception...: access violation reading location...''

    I can confirm that the callback function is actually being called because I've made a counter variable that increments each time its run. Upon close, I have the program print the contents, and it looks like its being run the right number of times. However, anything more complicated than that and it crashes.

    Any thoughts?

      Any thoughts?

      Show your code? You can also use a C debugger to try to determine where the problem is. You could also look at FFI in case its source code is of some help.

      - tye        

        Sure,
        #!/ASPerl/bin/perl use strict; use Inline 'INFO'; use Inline (C => 'DATA', DIRECTORY => '/tmp', FORCE_BUILD => 1, CLEAN_AFTER_BUILD => 1, CCFLAGS => '-GF -MDd -Zi /W3 -DWIN32 -D_CONSOLE -DNO_STRICT -D +_DEBUG' . ' -DHAVE_DES_FCRYPT -DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_ +SYS' . ' -DUSE_PERLIO -DPERL_MSVCRT_READFIX', LIBS => 'winmm.lib PAStaticWMMED.lib', ); sub my_simpcb { my $in = shift; my $out = $in; return $out; } registercb (\&my_simpcb); portinit (44100, 256); portstart (); pasleep (3000); portstop (); portclose (); exit (0); __DATA__ __C__ #include <portaudio.h> #include <memory.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <sys/types.h> static int pacback (void *, void *, unsigned long, PaTimestamp, void * +); static PortAudioStream *pa_stream; typedef struct { SV *isv; SV *cbfn; int runcount; } mybundle; mybundle bundle; void portinit (double sps, int buflen) { bundle.isv = newSVpvn (NULL, buflen); sv_setpvn (bundle.isv, "foo", 3); Pa_Initialize (); Pa_OpenDefaultStream (&pa_stream, 1, 1, paUInt8, sps, buflen, 0, pacback, &bundle); } void registercb (SV *cbfname) { bundle.cbfn = newSVsv (cbfname); } SV * whatiscb () { return bundle.cbfn; } void pasleep (int milisec) { Pa_Sleep (milisec); } void portstart () { bundle.runcount = 0; Pa_StartStream (pa_stream); } void portstop () { warn ("runcount == %d\n", bundle.runcount); Pa_StopStream (pa_stream); } void portclose () { Pa_CloseStream (pa_stream); Pa_Terminate (); } static int pacback (void *invoid, void *outvoid, unsigned long nsamps, PaTimestamp outTime, void *user) { mybundle *intbundle = (mybundle *)user; intbundle->runcount += nsamps; if (!invoid) return 0; sv_setpvn (intbundle->isv, (unsigned char *) invoid, nsamps); memcpy ((unsigned char *)outvoid, (unsigned char *)invoid, nsamps) +; return 0; }
        I've further narrowed it down to not reading from the variables is what crashes it, but the "sv_setpvn" that _writes_ to the perl variable is what doesn't work. I verified this by adding a sv_setpvn (intbundle->isv, "foo", 3); to it, which also caused it to crash with the "access violation reading..." error.

        I've uploaded the portaudio libraries I link against as well as winmm.lib (which is from the platform sdk) to http://web.mit.edu/fustflum/etcetera/portaudio, incase you care to look.

        Thanks for any insights you might have.