Re: wrapping C functions

new topic     » goto parent     » topic index » view thread      » older message » newer message
jimcbrown said...

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

new topic     » goto parent     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu