1. RE: Callback problem
- Posted by Andy Serpa <ac at onehorseshy.com> Oct 12, 2002
- 380 views
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...
2. RE: Callback problem
- Posted by Andy Serpa <ac at onehorseshy.com> Oct 13, 2002
- 360 views
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!
3. RE: Callback problem
- Posted by Andy Serpa <ac at onehorseshy.com> Oct 13, 2002
- 365 views
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...