in reply to Re^3: perl->c->perl (Inline::C)
in thread perl->c->perl

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?

Replies are listed 'Best First'.
Re^5: perl->c->perl (Inline::C)
by tye (Sage) on Dec 27, 2005 at 04:08 UTC
    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.

        Thanks for posting that code.

        This is mostly just a courtesy note to let you know that I won't have an answer for you, sorry (and I hope it might also increase the visibility of your node, having two "late" replies not just one -- if you get no response within a few days, I'd post a new root node).

        The reason I won't have an answer is that I don't do OO in XS and I'm pretty sure that I never will. OO in XS is quite against my philosophy of XS "best practices".

        So I have very little idea what bundle.isv actually means under the covers. Though, to be honest, I'm not too surprised that this is the source of your problem (well, that's my conclusion, anyway).

        If I were writing this, I'd do all of the OO (and just about anything else I could) in the Perl code (in the *.pm file) and have the XS interfaces be very vanilla C-friendly interfaces (except that some arguments might be of type SV* for the sake of dealing with Perl's total refusal to reasonably deal with memory buffers that it didn't allocate itself).

        - tye