Callback to Perl interpreter in C--something simpler than XS?

Do you have a question? Post it now! No Registration Necessary.  Now with pictures!

Threaded View
I'm trying to implement a Perl interface to a subset of Apple's
AppleEvent framework, allowing a Perl app to respond to AppleScript
commands. CPAN has a module devoted to this, but it is part of a larger
framework that is suffering from bit-rot, has large swaths of deprecated
and obsolete API calls, and won't build under 64-bit.

I'm moving right along with the AppleEvent / C API stuff, but I'm not
quite clear on how to convert this vanilla C code into something that
Perl can interface with. What I want to do is to pass a subroutine name
as a string to the Perl interpreter that the interpreter can run.

Here's one example C function:

//Handler for AppleEvents
static OSErr AEScriptsAEHandler(const AppleEvent *theAppleEvent,
                AppleEvent *reply, long refCon) {
   OSErr err = noErr;
   AEDesc returnData;
   AEEventID   eventID;
   OSType    typeCode;
   AEDesc directParameter;
   char *script;

   //Read the AppleEvent
   err = AEGetParamDesc(theAppleEvent, keyDirectObject, typeUnicodeText,

   //get event ID to look up in CFDictionary
   err = AEGetAttributePtr(theAppleEvent, keyEventIDAttr, typeType,
NULL, &eventID, sizeof(eventID), NULL );

   //get direct parameter
   err = AEGetKeyDesc(theAppleEvent, keyDirectObject, typeType,

   CFStringRef scriptName;
   stringeventID = UTCreateStringForOSType(eventID);
   scriptName = CFDictionaryGetValue(aeDict, stringeventID);

   CFIndex length = CFStringGetLength(scriptName);
   CFIndex maxSize = CFStringGetMaximumSizeForEncoding(length,
   script = (char *)malloc(maxSize);
   CFStringGetCString(scriptName, script, maxSize, kCFStringEncodingUTF8);

   //actually run the script
   err = ExecuteScript(script, NULL);

What this code does is check a CFDictionary ref for a value that
corresponds to the ID of a specific Apple event ("script"), and my idea
is to pass the "script" string to a function called "ExecuteScript" that
would incorporate the Perl interpreter. Is there a simpler way to
implement this than wading through all the XSUB goo?

In Tcl's C API it's simple as initializing a Tcl interpreter:

static Tcl_Interp *myInterp;

and then calling this function:

Tcl_Eval(myInterp, script);

In looking at the XS bits, am I missing something simpler that might
serve my needs? The idea here is that I'm passing a single subroutine
call to the  Perl interpreter, then I'll be returning the subroutine's
output back to the AppleEvent C API as a string. There aren't a lot of
hooks or complex data structures that need to be addressed: I just want
to have this as a loadable module that can interact with the running

Thanks for any advice,

Kevin Walzer
Code by Kevin

Re: Callback to Perl interpreter in C--something simpler than XS?

Quoted text here. Click to load it
Quoted text here. Click to load it
Quoted text here. Click to load it

This sounds like you want to call Perl from C, not C from Perl. That
means you need to read perlembed and perlcall rather than perlxs.

What language is the 'main' part of your program written in?

Quoted text here. Click to load it

    static PerlInterpreter *my_perl;

(Obviously you then have to initialise it, which is 3 function calls.)

Quoted text here. Click to load it


    call_argv(script, G_VOID, NULL);

'script' here is assumed to be a (fully-qualified) subroutine name. If
you want it to be a piece of Perl code, you want eval_pv.

Quoted text here. Click to load it

...and now you've gone back to talking about extending perl again. I'm
confused. How does your program start? Do you want to start in Perl,
call into C, and then call back into Perl again? That's entirely
possible, but you have to use both the perlxs and perlcall facilities.

However, that C above looks to me as though it's a callback from some
Apple facility. How does that get invoked? If it gets called
asynchronously, while there is other Perl code being executed, you will
probably need to use the ithreads mechanism to prevent the two bits of
Perl from interfering with each other.


Re: Callback to Perl interpreter in C--something simpler than XS?

On 1/26/13 5:09 AM, Ben Morrow wrote
Quoted text here. Click to load it

OK, perhaps this is the way I need to go. I'm not embedding Perl; I'm
creating an AppleEvents wrapper that will be loaded into the Perl
interpreter as a package.

Quoted text here. Click to load it

The AppleEvent API is a form of IPC where an app can communicate with
another app via sending AppleEvents. The high-level interface is the
AppleScript language. Something like this:

tell app "Foo"
end tell

My Perl app will be the recipient of the "tell" command in this
instance. My C code is intended to register the Apple Events the app
will handle with the OS, which has to be done in C. But the actual
execution of the code has to be done at the Perl level by the running
interpreter. Does this make sense?

Tcl's C API allows for easy two-way communication between the running
interpreter and code at the C level, and it can be done so without
threads. Here's some similar code in Tcl's C API:

    char *data = ckalloc(size + 1);
    theErr = AEGetParamPtr(event, keyDirectObject, typeUTF8Text, NULL, data,
        size, NULL);
    if (theErr == noErr) {
        tclErr = Tcl_EvalEx(interp, data, size, TCL_EVAL_GLOBAL);

     if (tclErr >= 0) {
    int reslen;
    const char *result =
        Tcl_GetStringFromObj(Tcl_GetObjResult(interp), &reslen);

    if (tclErr == TCL_OK) {
        AEPutParamPtr(reply, keyDirectObject, typeChar, result, reslen);
    } else {
        AEPutParamPtr(reply, keyErrorString, typeChar, result, reslen);
        AEPutParamPtr(reply, keyErrorNumber, typeSInt32, (Ptr) &tclErr,

The TclEvalEx() call executes the Tcl script, and the output is obtained
at the C level by the Tcl_GetStringFromObj(Tcl_GetObjResult(interp),
&reslen) call, and then passed back along the AppleEvents mechanism

It seems that Perl has two separate API's for interacting with C, rather
than one.

I'll dig deeper into the XS API and see if I can make that dance the way
I want to. I don't want to start a separate Perl interpreter, but rather
use the main one I have. The callback part is what's leading me in this
direction; otherwise I'd just use SWIG.

Other suggestions, anything I've missed, are appreciated.


Kevin Walzer
Code by Kevin

Re: Callback to Perl interpreter in C--something simpler than XS?

Quoted text here. Click to load it

No, you've still missed a step. At what point does that C function you
posted get called? Are you trying to call it from Perl, or does the OS
call it automatically? If the latter, does this only happen when the
process is sitting in some sort of wait-for-events function you call
from Perl, or does it get called asynchronusly, either in a separate
thread or by hijacking the current thread (like signal delivery)?

Quoted text here. Click to load it

The Perl API ends up looking very similar to that, but you have to be
careful about reentrancy. If your API calls might end up being
asynchronous wrt other API calls made by the main Perl program, you need
to make them against a separate interpreter.

Quoted text here. Click to load it

No, not really, the high-level documentation is just split across three
documents (perlxs, perlembed, perlcall) for convenience. The detailed
documentation for the whole API is in perlapi. XS itself is not part of
the Perl API as such, it's just a preprocessor for generating the boring
bits of boilerplate. It's perfectly possible to write a perl extension
as a plain C file (and there are sometimes good reasons for doing so).

Quoted text here. Click to load it

I would recommend staying away from SWIG, at least for perl. I've never
seen a SWIG-generated perl extension that was anything other than
painful to use; IMHO it's trying too hard to provide a cross-interpreter
interface, and the various interpreters' APIs aren't really compatible
enough for that to work. A basic XS interface that doesn't do anything
clever is just a matter of going through and listing the functions


Re: Callback to Perl interpreter in C--something simpler than XS?

On 1/26/13 9:20 AM, Ben Morrow wrote:
Quoted text here. Click to load it

I think I'm going to take a different tack here: ActiveState's Tkx
module, which allows you to put a Tk interface on a Perl app, also
includes fairly complete integration with the Tcl interpreter. I have a
working Tcl AppleEvent implementation in my apps written in Tcl, and I
can probably access that from Perl, and even use Perl callbacks, via the
Tkx module. I had thought this would involve a lot of overhead and
wanted to see if I could get a Perl-native implementation going, but it
seems too convoluted for me. Thanks for your time.


Kevin Walzer
Code by Kevin

Re: Callback to Perl interpreter in C--something simpler than XS?

Quoted text here. Click to load it

Man2Doctor "When I hold my arm this way, I get an incredible pain"
Doctor2Man "Well, dont hold your arm that way"


Re: Callback to Perl interpreter in C--something simpler than XS?

Quoted text here. Click to load it

Son2Father: Whenever I try to stand up and walk, I fall down!
Father2Son: You're only seventeen, kid, and should really stay away
from this adult stuff for somewhat longer. While it won't help you
stay young, it might even make you feel as if you remained a happy
toddler for some years to come!

Re: Callback to Perl interpreter in C--something simpler than XS?

Quoted text here. Click to load it

That's IMHO an impression you mostly got because you were seeking for
the Tcl-interface you're familiar with in Perl --- but the Perl
interface is different. In the following, I'm going to assume that the
AppleScript event handler is registered with some Apple library and
then called from the library as part of some kind of 'event loop'
processing. If this is so, the way to integrate this with perl would

    - provide an initialization function callable from perl via
          XS which performs any initialization which may be necessary
          and enables the caller to register a Perl subroutine
          supposed to handle the events

    - provide a second perl-callable function which enters the
          event loop

The C event handler routine would then need to invoke the Perl
callback (=> perlcall) and pass the results back to the library after
the Perl program called the init rouine and entered the event loop.

That's not really difficult and while XS seems somewhat dauting at a
first glance, for simple cases, like the one you have here, declaring
the signatures of the Perl entry points should be sufficient. As a
contrived example and without the boilerplate, for the init routine,
this could look like this:

    SV * subref

which declares an XS routine returning an int to Perl and taking a
single argument which will be a pointer to a 'scalar value' (SV). The
actual code will then be generated by the xsubpp preprocessor. The
h2xs program is also very helpful to 'jumpstart' a new extension

Site Timeline