1. undefine_c_func (was: memory profiling)
- Posted by Michael J. Sabal <m_sabal at yahoo.com> Nov 19, 2006
- 644 views
- Last edited Nov 20, 2006
Thank you, Rob, for your response. I'll see if I have the latest version of Matt's ODBC lib first, since he's already fixed a few leaks. Then I'll try recompiling the interpreter if the problem gets too bad. Now for the next question (unrelated): I'm currently in the process of updating EuGTK. GTK 2.6 has a procedure that allows for a variable number of arguments, similar to the way printf does. define_c_proc does not allow for this. My next thought was to simply define the procedure with the correct number of arguments each time it's needed. Except, without a matching undefine to free the memory, we introduce a leak into the library. If the routine is only called once or twice, that's not a big problem. But if the routine is needed a few thousand times, that's an issue. There is the option of completely rewriting the function in Euphoria terms instead of using the API call, but I'd prefer a simpler answer if it exists. Thoughts? Michael Sabal
2. Re: undefine_c_func (was: memory profiling)
- Posted by Ray Smith <ray at RaymondSmith.com> Nov 20, 2006
- 611 views
Michael J. Sabal wrote: [snip] > Now for the next question (unrelated): > I'm currently in the process of updating EuGTK. > GTK 2.6 has a procedure that allows for a variable number of arguments, > similar to the way printf does. define_c_proc does not allow for this. My > next thought was to simply define the procedure with the correct number of > arguments each time it's needed. Except, without a matching undefine to > free the memory, we introduce a leak into the library. If the routine is only > called once or twice, that's not a big problem. But if the routine is needed > a few thousand times, that's an issue. There is the option of completely > rewriting the function in Euphoria terms instead of using the API call, but > I'd prefer a simpler answer if it exists. > > Thoughts? > > Michael Sabal Hi Michael, I had the same issue with Euallegro. I made the Euphoria version pass a sequence of parameters (the same way the builtin Euphoria printf works) and in my wrapper routine I call sprintf() and pass the results of this to the C routines. E.g: C definition: void allegro_message(const char *text_format, ...); Eu routine:
constant my_allegro_message = link_proc(AllegroLib, "allegro_message", {C_POINTER}) global procedure allegro_message(sequence msg, sequence parms) atom msg_ptr sequence tmp tmp = sprintf(msg, parms) msg_ptr = allocate_string(tmp) c_proc(my_allegro_message, {msg_ptr}) free(msg_ptr) end procedure
Usage:
integer dummy1, dummy2 dummy1=123 dummy2=456 allegro_message( "This is a Test %d %d", {dummy1, dummy2})
Regards, Ray Smith http://RaymondSmith.com
3. Re: undefine_c_func (was: memory profiling)
- Posted by Chris Bensler <bensler at nt.net> Nov 20, 2006
- 596 views
Try passing the parameters as an array of INTs IIRC, varg uses the first element for argc, the remaining elements of the array are argv. I use that technique in mambo for dll function prototypes so I only need to have one proto instead of one for every number of args passed. I'll see if I can find the code I use in mambo. Chris Bensler ~ The difference between ordinary and extraordinary is that little extra ~ http://empire.iwireweb.com - Empire for Euphoria
4. Re: undefine_c_func (was: memory profiling)
- Posted by Pete Lomax <petelomax at blueyonder.co.uk> Nov 20, 2006
- 634 views
On Sun, 19 Nov 2006 15:25:53 -0800, "Michael J. Sabal" <guest at RapidEuphoria.com> wrote: >GTK 2.6 has a procedure that allows for a variable number of arguments, >similar to the way printf does. define_c_proc does not allow for this. My >next thought was to simply define the procedure with the correct number of >arguments each time it's needed. Except, without a matching undefine to >free the memory, we introduce a leak into the library. Why not just store results from define_c_proc in a sequence? Eg:
object xXxxx xXxxx = 0 global procedure Eu_xXxxx(sequence params) integer l atom p l = length(params) if atom(xXxxx) then xXxxx=repeat(0,l) elsif l>length(xXxxx) then xXxxx&=repeat(0,l-length(xXxxx)) end if p = xXxxx[l] if p=0 then p = define_c_proc(lib,"Xxxx",repeat(C_POINTER,l),C_INT) xXxxx[l] = p end if c_proc(p,params) end procedure
Regards, Pete
5. Re: undefine_c_func (was: memory profiling)
- Posted by Chris Bensler <bensler at nt.net> Nov 20, 2006
- 674 views
Pete Lomax wrote: > > On Sun, 19 Nov 2006 15:25:53 -0800, "Michael J. Sabal" > <guest at RapidEuphoria.com> wrote: > > >GTK 2.6 has a procedure that allows for a variable number of arguments, > >similar to the way printf does. define_c_proc does not allow for this. My > >next thought was to simply define the procedure with the correct number of > >arguments each time it's needed. Except, without a matching undefine to > >free the memory, we introduce a leak into the library. > Why not just store results from define_c_proc in a sequence? > Eg: > }}} <eucode> > object xXxxx > xXxxx = 0 > > global procedure Eu_xXxxx(sequence params) > integer l > atom p > l = length(params) > if atom(xXxxx) then > xXxxx=repeat(0,l) > elsif l>length(xXxxx) then > xXxxx&=repeat(0,l-length(xXxxx)) > end if > p = xXxxx[l] > if p=0 then > p = define_c_proc(lib,"Xxxx",repeat(C_POINTER,l),C_INT) > xXxxx[l] = p > end if > c_proc(p,params) > end procedure > </eucode> {{{ > > Regards, > Pete There is no need for these kinds of hacks, variadic functions are fairly simple to interface with once you know how. I'm mostly going from memory and a lack of available informaton, but.. All the params are stored as an array of INT's or DOUBLES, depending on the actual type of the argument. Types are promoted, so char/short -> INT and float -> DOUBLE It is the function's responsibility to know what the types of the arguments are supposed to be and how many. Eg printf's first argument is a format string which inherently specifies the types of the variable arguments via the format flags. Other functions typically will just expect a certain type for a given argument. Eg, a list of string pointers All variadic functions in C have to have at least one named argument, the last of which is the first element of the variadic array. To denote how many args are passed, 0-terminate the array. Some functions will determine the number of arguments from one of the arguments (normally a named argument or the first variadic or implicitly), but it will never hurt to 0-terminate the array. Here is a code example to give you an idea (untested/pseudo code, I doubt it will actually work, you will likely need to experiment a bit as I have not dealt with variadic functions much or in a long time)
constant xcprintf = define_c_proc(DLL,"printf",{UINT}) procedure cprintf(object format, sequence args) atom lpargs,lp args = {format} & args lpargs = allocate(8*(length(args)+1)) -- allocate maximum size.. +1 for NULL terminator lp = lpargs for i = 1 to length(args) do if sequence(args[i]) then poke4(lp, allocate_string(args[i])) lp += 4 elsif (args[i] < #100000000) and (floor(args[i]) = args[i]) then -- int poke4(lp,args[i]) lp += 4 else -- float poke(atom_to_float64(args[i])) lp += 8 end if end for c_proc(cprintf,{lpargs}) lp = lpargs for i = 1 to length(args) do if sequence(args[i]) then free(lp) lp += 4 elsif (args[i] < #100000000) and (floor(args[i]) = args[i]) then -- int lp += 4 else -- float lp += 8 end if end for free(lpargs) end procedure
HTH Chris Bensler ~ The difference between ordinary and extraordinary is that little extra ~ http://empire.iwireweb.com - Empire for Euphoria
6. Re: undefine_c_func (was: memory profiling)
- Posted by Chris Bensler <bensler at nt.net> Nov 20, 2006
- 634 views
Chris Bensler wrote: > > Pete Lomax wrote: > > > > On Sun, 19 Nov 2006 15:25:53 -0800, "Michael J. Sabal" > > <guest at RapidEuphoria.com> wrote: > > > > >GTK 2.6 has a procedure that allows for a variable number of arguments, > > >similar to the way printf does. define_c_proc does not allow for this. My > > >next thought was to simply define the procedure with the correct number of > > >arguments each time it's needed. Except, without a matching undefine to > > >free the memory, we introduce a leak into the library. > > Why not just store results from define_c_proc in a sequence? > > Eg: > > }}} <eucode> > > object xXxxx > > xXxxx = 0 > > > > global procedure Eu_xXxxx(sequence params) > > integer l > > atom p > > l = length(params) > > if atom(xXxxx) then > > xXxxx=repeat(0,l) > > elsif l>length(xXxxx) then > > xXxxx&=repeat(0,l-length(xXxxx)) > > end if > > p = xXxxx[l] > > if p=0 then > > p = define_c_proc(lib,"Xxxx",repeat(C_POINTER,l),C_INT) > > xXxxx[l] = p > > end if > > c_proc(p,params) > > end procedure > > </eucode> {{{ > > > > Regards, > > Pete > > There is no need for these kinds of hacks, variadic functions are fairly > simple > to interface with once you know how. > I'm mostly going from memory and a lack of available informaton, but.. > > All the params are stored as an array of INT's or DOUBLES, depending on the > actual > type of the argument. Types are promoted, so char/short -> INT and float -> > DOUBLE > > It is the function's responsibility to know what the types of the arguments > are supposed to be and how many. > > Eg printf's first argument is a format string which inherently specifies the > types of the variable arguments via the format flags. > > Other functions typically will just expect a certain type for a given > argument. > Eg, a list of string pointers > > All variadic functions in C have to have at least one named argument, the last > of which is the first element of the variadic array. To denote how many args > are passed, 0-terminate the array. Some functions will determine the number > of arguments from one of the arguments (normally a named argument or the first > variadic or implicitly), but it will never hurt to 0-terminate the array. > > Here is a code example to give you an idea > (untested/pseudo code, I doubt it will actually work, you will likely need to > experiment a bit as I have not dealt with variadic functions much or in a long > time) > > }}} <eucode> > constant xcprintf = define_c_proc(DLL,"printf",{UINT}) > procedure cprintf(object format, sequence args) > atom lpargs,lp > args = {format} & args > lpargs = allocate(8*(length(args)+1)) -- allocate maximum size.. +1 for NULL > terminator > lp = lpargs > for i = 1 to length(args) do > if sequence(args[i]) then > poke4(lp, allocate_string(args[i])) > lp += 4 > elsif (args[i] < #100000000) and (floor(args[i]) = args[i]) then -- int > poke4(lp,args[i]) > lp += 4 > else -- float > poke(atom_to_float64(args[i])) > lp += 8 > end if > end for > c_proc(cprintf,{lpargs}) > lp = lpargs > for i = 1 to length(args) do > if sequence(args[i]) then > free(lp) > lp += 4 > elsif (args[i] < #100000000) and (floor(args[i]) = args[i]) then -- int > lp += 4 > else -- float > lp += 8 > end if > end for > free(lpargs) > end procedure > </eucode> {{{ > > HTH > > Chris Bensler > ~ The difference between ordinary and extraordinary is that little extra ~ > <a href="http://empire.iwireweb.com">http://empire.iwireweb.com</a> - Empire > for Euphoria Oops, I missed poking the null terminator (not needed for printf anyway) And I also didn't declare printf as cdecl "+printf" (all variadic functions are cdecl) Chris Bensler ~ The difference between ordinary and extraordinary is that little extra ~ http://empire.iwireweb.com - Empire for Euphoria
7. Re: undefine_c_func (was: memory profiling)
- Posted by Pete Lomax <petelomax at blueyonder.co.uk> Nov 21, 2006
- 621 views
On Mon, 20 Nov 2006 05:32:34 -0800, Chris Bensler <guest at RapidEuphoria.com> wrote: >There is no need for these kinds of hacks, Oh/Uh? >variadic functions are fairly simple to interface with once you know how. >I'm mostly going from memory and a lack of available informaton, but.. OK, I'm listening... > >All the params are stored as an array of INT's or DOUBLES, depending on the >actual type of the argument. Types are promoted, so char/short -> INT and float >-> DOUBLE That is not at all what I was taught.[1] > >It is the function's responsibility to know what the types of the arguments are >supposed to be and how many. Nor that[2] > >Eg printf's first argument is a format string which inherently specifies the >types of the variable arguments via the format flags. Nor that[3] > <snip> > >Here is a code example to give you an idea >(untested/pseudo code, I doubt it will actually work, OK, gauntlet down. Make it work. I claim you will not be able to. I'll accept a reasonable forfeit should you prove me wrong, of course /only/ if you can do so with /less/ "hacks" than the wee sequence of define_c_proc results I proposed, and keep say 60% of the code you posted? Regards, Pete [1] Far as I know, in most languages (not Eu, of course), parameters are pushed onto the stack, and the stack is kept machine-word aligned by default. There's no "array" involved, though they do end up next to each other by the time the function sees them. [2] It is NOT a mandate that a (C) function must crash when passed arguments of the wrong type. Any "responsibility" clearly lies with the caller, not the callee. [3] Clearly printf will print rubbish, and/or ignore excess arguments. Inherently it has /no/ type checking abilities. Quite how one might print 0 when you 0-terminate this fictional array is a mystery to me.
8. Re: undefine_c_func (was: memory profiling)
- Posted by Michael J. Sabal <m_sabal at yahoo.com> Nov 21, 2006
- 634 views
Chris Bensler wrote: > > Oops, I missed poking the null terminator (not needed for printf anyway) > And I also didn't declare printf as cdecl "+printf" (all variadic functions > are cdecl) > I tried running your code with these modifications under 2 scenarios: define_c_proc("","+printf",{C_UINT}) and define_c_proc(open_dll("libc.so"), "+printf",{C_UINT}). Neither was able to link to the C function, not even when I changed C_UINT to C_POINTER. I gave up and just recoded the GTK routine I was after in Euphoria. I'm sure there are other variadics out there that I won't be able to cheat so easily, so it's important for the community that we find a way to prove that it works without rewriting the functions in Euphoria. If we can't (and so far we're 0 for 2), we may need a source mod to enable that functionality. Michael Sabal
9. Re: undefine_c_func (was: memory profiling)
- Posted by Matt Lewis <matthewwalkerlewis at gmail.com> Nov 21, 2006
- 601 views
Michael J. Sabal wrote: > > Chris Bensler wrote: > > > > Oops, I missed poking the null terminator (not needed for printf anyway) > > And I also didn't declare printf as cdecl "+printf" (all variadic functions > > are cdecl) > > > > I tried running your code with these modifications under 2 scenarios: > define_c_proc("","+printf",{C_UINT}) and define_c_proc(open_dll("libc.so"), > "+printf",{C_UINT}). Neither was able to link to the C function, not even > when I changed C_UINT to C_POINTER. I gave up and just recoded the GTK > routine I was after in Euphoria. I'm sure there are other variadics out there > that I won't be able to cheat so easily, so it's important for the community > that we find a way to prove that it works without rewriting the functions in > Euphoria. If we can't (and so far we're 0 for 2), we may need a source > mod to enable that functionality. You might need to import as "+_printf", since that's what compilers usually do with cdecl exports. You could also use fptr.e (in the archives) which uses assembly to push the args. You can use define_c_var to simply get the address of the exported function. The easier solution is probably Pete's, however. Matt
10. Re: undefine_c_func (was: memory profiling)
- Posted by Chris Bensler <bensler at nt.net> Nov 22, 2006
- 619 views
Pete Lomax wrote: > > On Mon, 20 Nov 2006 05:32:34 -0800, Chris Bensler > <guest at RapidEuphoria.com> wrote: > > >There is no need for these kinds of hacks, > Oh/Uh? Sorry Pete, I didn't mean it to offend. My perception of a hack is any code that 'cheats' it's way around a problem. Not necessarily a bad solution, just not the best one. > >variadic functions are fairly simple to interface with once you know how. > >I'm mostly going from memory and a lack of available informaton, but.. > OK, I'm listening... > > <SNIP> All of the information I gave was derived directly from online research the day I wrote the post to confirm my memory, just so ya know I'm not talking through my hat ;) I'm quite sure it will work. I'll figure it out and get back to you guys. <snip> > [1] Far as I know, in most languages (not Eu, of course), parameters > are pushed onto the stack, and the stack is kept machine-word aligned > by default. There's no "array" involved, though they do end up next to > each other by the time the function sees them. Yes they are pushed onto the stack. Which reminds me, the array may need to be reversed. Yes the array/stack is machine-word aligned. On a 64-bit machine I suppose all types would be promoted to doubles. On 32-bit x86, a word is a 4 byte INT and a DOUBLE would still be aligned. > [2] It is NOT a mandate that a (C) function must crash when passed > arguments of the wrong type. Any "responsibility" clearly lies with > the caller, not the callee. No it's not a mandate, it's a trait. All vararg handling is done within the function. Not done by the caller. The types and sizes of the args are determined by the caller, by an undefined means. Yes this is kinda backwards, but it was a design compromise, so that a programmer doesn't have to do all the dirty work everytime a variadic is called. > [3] Clearly printf will print rubbish, and/or ignore excess arguments. > Inherently it has /no/ type checking abilities. Quite how one might > print 0 when you 0-terminate this fictional array is a mystery to me. printf does have type checking abilities. It uses the string formatting flags to determine how many and what types the args should be. Terminating the array is not nessecary for printf(), the number of args for printf is implicit in the string format. How do you print 0 with a 0-terminated string? :) Same thing just INTs instead of CHARs I should have said null-terminated, not 0-terminated. If the designer of the function wanted to allow NULL to be a valid argument then they would probably require the argument count to be passed as the last named parameter. Chris Bensler ~ The difference between ordinary and extraordinary is that little extra ~ http://empire.iwireweb.com - Empire for Euphoria
11. Re: undefine_c_func (was: memory profiling)
- Posted by Chris Bensler <bensler at nt.net> Nov 22, 2006
- 615 views
Chris Bensler wrote: > No it's not a mandate, it's a trait. > All vararg handling is done within the function. Not done by the caller. > The types and sizes of the args are determined by the caller, by an undefined > means. I mean defined by the 'callee' :S I shoulda stuck with 'function' :P Chris Bensler ~ The difference between ordinary and extraordinary is that little extra ~ http://empire.iwireweb.com - Empire for Euphoria