On Mon, 5 Mar 2001, Garrett Goebel wrote:
> It now works better. Well, the callback to the perl function when works
> once. The first time called, it gets valid arguments. The second time
> called, it looks like it is getting the stash followed by valid arguments.
Whenever you call Perl from C, it's a good idea to refresh yourself on the
basics. I still go back to the perlembed manpage whenever I need to call
Perl functions from C.
See below for specific comments.
> Any idea what's going wrong? Assumably something I'm failing to do.
>
> use Inline C => DATA => LIBS => '-luser32';
>
> Enum_Child_Windows(sub { print "foo(@_)\n" });
>
> __END__
> __C__
> #include <windows.h>
>
> static SV* coderef;
> void set_coderef(SV* cref) {
> coderef = cref;
> }
>
> BOOL FAR PASCAL Enum_Child_Proc (HWND hWnd, LPARAM Param) {
> Inline_Stack_Vars;
> I32 flags = 0;
> Inline_Stack_Reset;
> Inline_Stack_Push(newSViv(hWnd));
> Inline_Stack_Push(newSViv(Param));
> Inline_Stack_Done;
> call_sv(coderef, flags);
>
> return 1;
> }
There's the problem. You call a Perl function without cleaning up the
stack afterwards. When Perl calls a function, it pushes a bunch of
information on the Stack (similar to C). If you don't clean it up, it will
stay on the stack, ruining the state of the interpreter.
Here's a similar example from the perlembed manpage:
----8<----
static void
PerlPower(int a, int b)
{
dSP; /* initialize stack pointer */
ENTER; /* everything created after here */
SAVETMPS; /* ...is a temporary variable. */
PUSHMARK(SP); /* remember the stack pointer */
XPUSHs(sv_2mortal(newSViv(a))); /* push the base onto the stack */
XPUSHs(sv_2mortal(newSViv(b))); /* push the exponent onto stack */
PUTBACK; /* make local stack pointer global */
perl_call_pv("expo", G_SCALAR); /* call the function */
SPAGAIN; /* refresh stack pointer */
/* pop the return value from stack */
printf ("%d to the %dth power is %d.\n", a, b, POPi);
PUTBACK;
FREETMPS; /* free that return value */
LEAVE; /* ...and the XPUSHed "mortal" args.*/
}
----8<----
Notice the junk after the perl_call_sv().
Here's a handy phrase book for those unfamiliar with the XS macros:
dSP Inline_Stack_Vars
ENTER
SAVETMPS
PUSHMARK(SP)
XPUSHs Inline_Stack_Push
PUTBACK Inline_Stack_Done
SPAGAIN Inline_Stack_Reset
FREETMPS
LEAVE
As you can see, Inline is not yet mature enough to handle all those extra
XS macros. In your case, I would add these lines to your code and see if
everything starts working:
----8<----
Inline_Stack_Done;
call_sv(coderef, flags);
-
+ Inline_Stack_Reset;
+ Inline_Stack_Done;
return 1;
----8<----
If it does, great. If not, replace your Inline_* macros one-by-one with
the corresponding XS macros from the example. Then send Brian a patch :)
Later,
Neil
--
Vote for Your Favorite Perl & Python Programming
Accomplishments in the first Active Awards!
>> http://www.ActiveState.com/Awards <<