[OSC_dev] advice for callback (oscit)
salsaman at xs4all.nl
salsaman at xs4all.nl
Sat Dec 27 16:07:44 PST 2008
On Sat, December 27, 2008 14:20, Jamie Bullock wrote:
> On Fri, 2008-12-26 at 17:43 +0100, Gaspard Bucher wrote:
>> Hi list !
>>
>> I started extracting the library from rubyk but I jump on a difficult
>> problem: in rubyk all values passed between objects and used in OSC
>> calls are sub-classes of Value (a smart pointer with reference
>> counting). This means every function has the type:
>>
>> const Value method_name (const Value& param)
>>
>> A "Value" can be a Number, a Hash, a Matrix, a String or just Nil
>> (Array coming soon).
>>
>> All this is fine in a C++ environment but I do not see how we could
>> easily use the "value" stuff in a plain C interface.
>>
>> ========= oscit C interface ========
>>
>> The values will be replaced by an array of union [float / int / string
>> / xxx]. So the signature of registering methods will be (C interface)
>> :
>>
>> void my_function(OscVal * ret, const OscVal * arg)
>>
>> You register the function with something like:
>>
>> register_method("/some/url", my_function, "ffi")
>>
>> Inside "my_function", values are simply retrieved with:
>>
>> arg[0]->f = float
>> arg[1]->i = int
>> etc.
>>
>> Type checking is done by "oscit",
>
> Sorry to be pedantic, but could we refer to the protocol a 'oscit' and
> the the implementation as 'liboscit'? Otherwise I can see people quickly
> becoming confused.
>
>> the only verification should be (arg
>> == NULL) because methods can either receive the correct signature or
>> Nil.
>>
>> The storage space for return values is also prepared and the function
>> should just write:
>>
>> ret[0]->f = ...
>> ret[1]->i = ...
>> etc
>>
>> This setting has the following advantages:
>>
>> 1. fast to parse
>> 2. no dynamic memory allocation during runtime (done once on
>> registration for "ret" and "arg")
>>
>> The drawbacks are:
>>
>> 1. fixed type signature
>> 2. same type signature for argument and return value
>
> You could overcome this by wrapping the union in a struct which holds a
> 'type identifier' for the Value. For a small computational efficiency
> cost, you get get a relatively large gain in flexibility and
> maintainability:
>
> typedef enum OscType_ {
> FLOAT,
> INT,
> DOUBLE,
> STRING
> } OscType
>
> typedef struct Value_ {
> OscType type;
> union ctype_ {
> char *s;
> float f;
> double d;
> int i;
> void *r;
> } ctype;
> } Value;
>
>> Does this seem ok for the "C" users out there ?
>
> I'm fine with your original suggestion, it's simple and efficient, but I
> thought i'd suggest the above as a possible alternative.
>
> Jamie
>
> --
> www.postlude.co.uk
> http://www.linkedin.com/in/jamiebullock
If you have an enum type, then you don't need a union. You can just use a
void * and a size_t length, e.g.
typedef struct {
int type;
size_t len;
void *data;
} my_data_t;
or if you want arrays:
typedef struct {
size_t len;
void *data;
} my_ldata_t;
typedef struct {
int type;
int nelems;
my_ldata_t *data;
} my_array_data_t;
LiVES uses something like the latter in its libraries (libweed).
In fact you might want to use it, although it is a bit heavyweight for
what you are doing:
http://lives.cvs.sourceforge.net/viewvc/lives/lives/libweed/weed.h
Gabriel.
More information about the OSC_dev
mailing list