Re: wrapping C functions
- Posted by ghaberek (admin) Feb 21, 2013
- 1543 views
That's not exactly right. serialPrintf is a vardic function, which isn't directly supported in Euphoria. Though you could do:
You'd need a new definition for each variation of serialPrintf() that you wanted to handle, though.
Ugh. I hate having to deal with variadic functions in Euphoria. Luckily most C libraries also include statically-defined functions that Euphoria can wrap over for variadic purposes. (e.g. just call the static function for each argument in a list)
However, there is hope! I've recently concocted this method for passing a variable number of arguments to C functions by declaring the function on-the-fly and then caching the result. The code below is from memory but should work just fine. This could be simplified for functions that take n-number of a single type by simply calling repeat( C_TYPE, count ), etc.
include "std/dll.e" include "std/machine.e" include "std/map.e" map serialPrintf_ids = map:new() procedure serialPrintf( integer fd, sequence message, object args ) -- ensure that 'args' is always a sequence of arguments if atom( args ) then args = {args} end if -- declare the base argument types sequence arg_types = {C_INT,C_POINTER} -- append the variadic argument types for i = 1 to length( args ) do if sequence( args[i] ) then -- replace the argument with a pointer to the string... args[i] = allocate_string( args[i], 1 ) -- (1 = clean up automatically) arg_types = append( arg_types, C_POINTER ) elsif integer( args[i] ) then arg_types = append( arg_types, C_INT ) else -- atom (float? could be anything depending on your function) arg_types = append( arg_types, C_FLOAT ) end if end for -- lookup this pattern of argument types in the cache integer id = map:get( serialPrintf_ids, arg_types, -1 ) if id = -1 then -- not found! -- declare this new pattern... id = link_c_proc( dll_ptr, "serialPrintf", arg_types ) -- ...and store it in the cache map:put( serialPrintf_ids, arg_types, id ) end if -- store the message argument in memory atom message_ptr = allocate_string( message, 1 ) -- call the function with our arguments c_proc( id, {fd,message_ptr} & args ) end procedure
-Greg