Browse thread
[Caml-list] Binding C libraries which use variable arguments (stdarg.h)
[
Home
]
[ Index:
by date
|
by threads
]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: | 2009-10-29 (23:31) |
From: | Goswin von Brederlow <goswin-v-b@w...> |
Subject: | Re: [Caml-list] Binding C libraries which use variable arguments (stdarg.h) |
Adrien <camaradetux@gmail.com> writes: > On 29/10/2009, Goswin von Brederlow <goswin-v-b@web.de> wrote: >> Basile STARYNKEVITCH <basile@starynkevitch.net> writes: >> >>> Adrien wrote: >>>> Hi, >>>> >>>> I am currently trying to bind a C function that takes variables >>>> arguments, like foo(int a, ...). I can't find how to make a C stub for >>>> that function. >>> >>> I am assuming that the a is the number of actual arguments, so you call >>> foo(3, x, y, z) >>> foo(5, t, t+1, t+3, 0, 4) >>> foo(0) >>> >>>> >>>> Any other idea? Hint^WPointer? (sorry for the bad joke ;-) ) >>> >>> First, you could suppose that the a has a reasonable limit, say 100. >>> >>> Then you could generate the glue code for each value of the argument >>> a. I mean generate ocaml code like >>> >>> external f0: void -> uit = "f_0" >>> external f1: int -> unit = "f_1" >>> external f2: int -> int -> unit = "f_2" >>> external f3: int -> int -> int -> unit = "f_3" >>> >>> let f a = match Array.length a with >>> 0 -> f0 () >>> | 1 -> f1 a.[0] >>> | 2 -> f2 a.[0] a.[1] >>> | 3 -> f3 a.[0] a.[1] a.[2] >>> .... >>> | _ -> failwith "too many components for f" >>> >>> and generate C code for each of f_0 f_1 ... >>> >>> and call f with an array ... >>> >>> The specialized code generator is reasonably written in Ocaml >>> >>> There are more crazy variants, including >>> >>> try Ocaml varargs like Pierre Weis did in printf.ml. For plain mortals >>> like me this is white magic. >>> >>> Assuming a Linux system, you could lazily generate the glue code and >>> invoke dynamic linker on it. So the general case would be to call the >>> code generator. >>> >>> Time to go to bed. I am saying lot of non-sense. >>> >>> Bye! >> >> Since ocaml functions with more than 5 args use an array you only do >> that in ocaml for a few arguments and then you need to do this in >> C. So do it in C for all. The stub takes an array and then switches on >> the lentgh to call the real function. >> >> Unfortunately you can not convert an array or list into a va_list. You >> need to specifically catch each length and call foo(4, a[0], a[1], >> a[2], a[3]) for each length. > > Well, my problem is more when calling the C function since I can chose > the interface of the caml functions. If you can't change the C function to use something other than varargs and you can't limit the number of args and implement a case for each number then the only option left is to create the varargs from an array. That will be really ugly and architecture and compiler dependent. So lots of #ifdef cases in your C code. Something you really do not want to do. > There's something I've not been sure and would like to ask however: > for the sake of consitency, I've been giving both a native and > bytecode function every time no matter the number of arguments. Could > that be a problem? No. With >= 5 args you just need 2 functions, one for native and one for bytecode. The docs have an example on how to do that. The problem is calling the actual C function. MfG Goswin