Hello and perl question

View: New views
3 Messages — Rating Filter:   Alert me  

Hello and perl question

by Steve Chan-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi,
    I've been looking at using swig for getting a perl wrapper of a C
library and have come across a stumbling block - a check through the
archives didn't turn up the answer.

    The C library requires registering callbacks, which would be in
Perl. I've already written and tested the perl callbacks using an
embedded perl library, so the "hard" part of wrapping the library
seems to be done already. The only thing that remains is converting
this code from the perl embedding API to something that works with SWIG.

    The question is: How do I get the reference to the PerlInterpreter
that many of the embedding API macros use? In your typical embedded
perl application, you have the moral equivalent of this code:

#include <EXTERN.h>               /* from the Perl distribution     */
#include <perl.h>                 /* from the Perl distribution     */

static PerlInterpreter *my_perl;  /***    The Perl interpreter    ***/

int main(int argc, char **argv, char **env)
{
    my_perl = perl_alloc();
    perl_construct(my_perl);
    perl_parse(my_perl, NULL, argc, argv, (char **)NULL);

    /* do some stuff until we want to call the perl handler */
    dSP;
    ENTER;
    SAVETMPS;
    PUSHMARK(sp);

    /* push the params into the call stack */
    XPUSHs( sv_2mortal( sv1));
    ...
    XPUSHs( sv_2mortal( svN));
    PUTBACK;

    /* call the perl handler */
    n = perl_call_sv( handler, G_SCALAR);
    SPAGAIN;
    PUTBACK;
    FREETMPS;
    LEAVE;
    /* done calling the perl handler */

    perl_destruct(my_perl);
    perl_free(my_perl);
}

    Many of the macros from the dSP through to LEAVE make reference to
the static my_perl defined globally. My question is, will the same
code basically work within SWIG? And if so, then how do I get hold of
the handle to the static perl_interpreter that is running the wrapped
code?

    I figure the answer is either really easy, or really hard. I'm
hoping it is the former.

    Thanks in advance,
    Steve
-----BEGIN PGP SIGNATURE-----
Version: GnuPG/MacGPG2 v2.0.12 (Darwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAkrTrYAACgkQcVd2YI1BWAhT+gCeJwT8GqsL1cWNqcqtY7iJaEgq
c3oAn2aroyBydsMCQaQy/HjAthBwJwnJ
=E9DI
-----END PGP SIGNATURE-----


------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
Swig-user mailing list
Swig-user@...
https://lists.sourceforge.net/lists/listinfo/swig-user

Parent Message unknown Re: Hello and perl question

by Steve Chan-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi Sri,
    I got the callbacks working - it turns out that the code worked
pretty much as-is.

    Going back and looking at your email, it looks like you basically
had to do the same thing I did. It is relatively easy to get a
callback working so long as the perl code doesn't need to receive any
parameters. However, if you need to pass parameters back to the perl
callback, then you have to learn enough about the perl-c API in order
to unpack the callback parameters and push them onto the call stack as
perl objects. So, in your example, you would have to write a perl
callback wrapper that would be able to parse the contents of *p_data
and push a bunch of stuff onto the perl stack.

    Here's the slightly edited wrapper code I used, to give you an
idea of what is involved:

/* the callback signature takes has 3 params, a connection handle, a
void pointer to user specified data - assigned to "handler" here, and
a BroEvMeta pointer that has data destined for the callback function -
equivalent to p_data in your example */

static void call_handler( BroConn *conn,CV *handler, BroEvMeta *meta) {
  int i;
  int ok = TRUE;
  int rv = 0;
  SV *param;

  dSP;

  ENTER;
  SAVETMPS;
  PUSHMARK(sp);

  /* Push the name of the event in as the first element ev_name is the
event name field in the meta structure*/
  param = newSVpv( meta->ev_name, 0);
  XPUSHs(sv_2mortal(param));
  /* the ev_numargs and ev_args[] fields in meta are the # of args and
the respective contents, including type data */
  for (i = 0; i < meta->ev_numargs; ++i) {
    param = get_param( meta->ev_args[i]); /* get_param() is a custom
function and returns a perl SV reference that
                                                                     
is the perl internal representation of the data */
    if (param)
      XPUSHs(sv_2mortal(param));
    else {
      time_t t;
      t = time(NULL);
      fprintf(stderr, "Error in handling event type %s with %i
arguments at %s\n",
              meta->ev_name, meta->ev_numargs,ctime(&t));
      ok = FALSE;
      break;
    }
  }
  PUTBACK;
  /* Call the perl handler. Expect a single scalar value which should
     be 1 for success and 0 for failure/error. No return value is treated
     as a zero return value - we're not doing anything with the return
     value */
  if (ok)
    rv = perl_call_sv((SV *)handler,G_SCALAR);
  SPAGAIN;
  PUTBACK;
  if ( rv ) {
    rv = POPi;
  }
  FREETMPS;
  LEAVE;
  return;
}

    You would then either wrap a wrapper function that does some
validation on the input and then calls the actual callback registry,
or else write a typemap that does the equivalent. Here's the example
from my own project.
    The api for registering a callback is:
void bro_event_registry_add_compact(BroConn *bc, const char
*event_name, BroCompactEventFunc func,void *user_data);


    The wrapper code for the callback registry I use is pretty
straightforward:

int add_event_handler( BroConn *bc, char *event_name, SV *code_ref) {
  CV *handler;

  if (!SvROK(code_ref)) {
      fprintf( stderr, "Error: handler for event %s is not a
reference.\n",
               event_name);
      return(FALSE);
  } else if (SvTYPE(SvRV(code_ref)) != SVt_PVCV) {
      fprintf( stderr, "Error: handler for event %s is not a code
reference.\n",
              event_name);
      return(FALSE);
  }


  handler = (CV *)newSVsv(code_ref);

  bro_event_registry_add_compact(bc, event_name,
(BroCompactEventFunc)call_handler, (void *)handler);
  return( TRUE);
}

    I think the following typemap should work, but I am having trouble
with the code generation phase of gcc when I use it, it looks like a
gcc code generation bug, but maybe someone else can tell you if it is
the right typemap approach.

%typemap(in) (BroCompactEventFunc func, void *user_data) (CV *handler) {

  if (!SvROK($input)) {
    croak("Expected a reference.\n");
  } else if (SvTYPE(SvRV($input)) != SVt_PVCV) {
    croak("Expected a code reference.\n");
  }

  handler = (CV *)newSVsv($input);

  $1 = (BroCompactEventFunc)call_handler;
  $2 = (void *)handler;
}

    You would have to do things a little differently based on the API
you described, but you would have to come up with some way to get the
parameters into the Perl call stack before calling the perl handler.

    I hope that helps,
    Steve

Sri wrote:
> Hi,
>
> I unfortunately dont have expertise to help on your question.  However,
I was hoping to learn from your success so far.  Can you share any
pointers on how the embedded perl interpreter helped you invoke Perl
subroutines as callbacks from C code?  I'm stuck at this exact same
situation (see my post from a few days back).
>
> Sorry for contacting you directly.
>
> Thx
>
>
>      
-----BEGIN PGP SIGNATURE-----
Version: GnuPG/MacGPG2 v2.0.12 (Darwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAkrXXAAACgkQcVd2YI1BWAj29gCcC2h89swm2sPsjbD9GPYFOecV
UzMAoIj5r5F3Y2y+HW2J4PHbMs1oyXHm
=GhFN
-----END PGP SIGNATURE-----


------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
Swig-user mailing list
Swig-user@...
https://lists.sourceforge.net/lists/listinfo/swig-user

Parent Message unknown Re: Hello and perl question

by Steve Chan-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Sri wrote:
>
> btw, how did you get hold of the Perl interpreter instance created
> by SWIG (your original post).  I've yet not found documentation of
> the SWIG_ helper functions.
>

    It turns out that if your perl was built for single threaded
operation or without MULTIPLICITY, then you can just declare "extern
PerlInterpreter *y_perl", and the linking loader seems to resolve the
symbol. Which is what happened in the first platform I tried it on
(MacOS).

    But when tried it under Linux, my_perl turned out to be in an
inaccessible scope. After some digging around, it became clear that
the perl was built for multithreading, in which you you need to put
the dTHX macro at the start of every function that makes use of the
perlguts stuff. This macro expands into a declaration for my_perl
which is initialized with the perl interpreter context appropriate for
your thread of execution.
    I suspect that if MULTIPLICITY were defined in my perl instance,
the PERL_IMPLICIT_CONTEXT stuff would have kicked in, but I don't feel
motivated to build another perl jusy to try it - might come in handy
for you though.

    Good luck!
    Steve

-----BEGIN PGP SIGNATURE-----
Version: GnuPG/MacGPG2 v2.0.12 (Darwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAkrfNyYACgkQcVd2YI1BWAhEJwCeP79M/3MZjv2TOqCBGRlT9jxM
pSsAoJawjuL8yrCAhevnHXr39CKTQ3Rz
=WNZf
-----END PGP SIGNATURE-----


------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
Swig-user mailing list
Swig-user@...
https://lists.sourceforge.net/lists/listinfo/swig-user