1. RE: Callback problem

kbochert at copper.net wrote:
> 
> >From: Andy Serpa <renegade at earthling.net>
> >To: EUforum <EUforum at topica.com>
> >Date: 10/11/02  10:29:11 PM
> >Subject: RE: Wrapping C - Callback troubles
> 
> 
> Bernie Ryan wrote:
> >
> > Andy Serpa wrote:
> > > Here's another problem.  I'm making the Berkeley DB wrapper which
> allows
> > > for certain callback functions to be used.  One particular one
> I'm
> > > trying to set up is supposed to be a void function.  The callback
> works
> > > (my function is called), but when it returns a value (any value)
> it
> > > crashes.  (Callback functions are required to return something.)
> 
> >But that's not the problem.  Setting the callback function is no
> >problem, and my Euphoria function is being called with the correct
> >args.
>  >The problem is when my function exits (returns a value) the whole
> >thing
> >crashes with an exception.  I was just wondering is that because it
> >is a
> >supposed to be void function?  (It seems like I should be able to
> >return
> >anything in that case, but maybe it wants me to return nothing?)
> >Anybody know anything about that?
> 
> This sounds like the cdecl-stdcall problem. Many packages that come
> from the unix world expect the callback function to be cdecl rather
> than the windows standard stdcall. If the callback is of the wrong
> variety, the stack gets messed up.
> 
> I modified Bach to accept cdecl callbacks -- under Euphoria I think
> the easiest option is to modify the calling convention in the source
> and re-compile the package.
> 
> There probably is a way to fix it by poking assembly.
> 

See the "Matt Lewis Help!" post -- I'm doing all this in cdecl now.  
Still doesn't work on the void function and then there is also that odd 
thing with the extra parameter in the other function.

I don't know a thing about ASM so I couldn't possibly tell if maybe the 
fptr.e stuff isn't quite right -- hopefully Matt or someone else can.  I 
am at the limits of my knowledge...

new topic     » topic index » view message » categorize

2. RE: Callback problem

stabmaster_ at hotmail.com wrote:
> >This sounds like the cdecl-stdcall problem.
> >...
> >There probably is a way to fix it by poking assembly.
> >
> >Karl Bochert
> 
> 
> I did just that in Glue, my GLUT wrapper for Euphoria. In glue.e there 
> is a 
> function called cdecl_callback that takes a routine_id and a sequence of 
> 
> parameter sizes (in bytes). E.g. if you have a function foo that takes 3 
> 
> integer parameters, you'd do something like:
> 
> atom my_callback
> my_callback = cdecl_callback(routine_id("foo"),{4,4,4,4})
> 
> Note that i passed 4 4's, this is intentionally. You see, there's a 
> small 
> problem: Since EIP is pushed on the stack after the parameters, you'll 
> get 
> the return address in the first parameter of your function. To get 
> around 
> this you must prepend a dummy argument to your function. I.e. if you 
> had:
> 
> function foo(integer a,integer b,integer c)
> 
> You'd have to change it to:
> 
> function foo(integer dummy,integer a,integer b,integer b)
> 
> 

It works!

Here is the basic assembler your routine generates:

    #B8,#00,#00,#00,#00,    --    0: mov eax,callback (1)
    #FF,#D0,                --    5: call near eax
    #83,#EC,#00,            --    7: sub esp, 0
    #C3                     --    A: ret


So, you replace the "#00,#00,#00,#00" with the 4-byte call_back() 
address of your routine, and then replace the #00 in line 7 with the 
number of args * 4 (dummy argument included).

Works like a charm!

new topic     » goto parent     » topic index » view message » categorize

3. RE: Callback problem

Andy Serpa wrote:
> 
> stabmaster_ at hotmail.com wrote:
> > >This sounds like the cdecl-stdcall problem.

> > 
> > I did just that in Glue, my GLUT wrapper for Euphoria. In glue.e there 
> > is a 
> > function called cdecl_callback that takes a routine_id and a sequence of 
> > 
> > 

Here's a little cleaner version of the function, without the need for 
asm.e.  I guess this way you are still limited to a less than 9 args:


constant cdecl_asm =
{
    #B8,#00,#00,#00,#00,    --    0: mov eax,callback (1)
    #FF,#D0,                --    5: call near eax
    #83,#EC,#00,            --    7: sub esp, [num args * 4] (9)
    #C3                     --    A: ret
}

function cdecl_callback(atom r_id, integer args)
-- your callback function must use an extra dummy arg
-- before the real args
atom addr

	addr = allocate(11)
	poke(addr,cdecl_asm)
	poke4(addr+1,call_back(r_id))
	poke(addr+9,args * 4)

	return addr
end function


Then, get your callback address like this:

my_callback_addr = cdecl_callback(routine_id("my routine"),num_args)

& don't forget your dummy arg...

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu