* [Caml-list] Binding C libraries which use variable arguments (stdarg.h) @ 2009-10-28 22:07 Adrien 2009-10-28 22:45 ` Basile STARYNKEVITCH 0 siblings, 1 reply; 14+ messages in thread From: Adrien @ 2009-10-28 22:07 UTC (permalink / raw) To: Caml Mailing List 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 found camlidl didn't support idl's "vararg" keyword and pidl (p stands for perl) didn't either. I was told to try libffi but it doesn't support varargs unfortunately. I also thought about doing it by hand but that's not the best idea for portability. Any other idea? Hint^WPointer? (sorry for the bad joke ;-) ) Thanks. PS: I was also told I was toast --- Adrien Nader ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Caml-list] Binding C libraries which use variable arguments (stdarg.h) 2009-10-28 22:07 [Caml-list] Binding C libraries which use variable arguments (stdarg.h) Adrien @ 2009-10-28 22:45 ` Basile STARYNKEVITCH 2009-10-29 8:55 ` Goswin von Brederlow 2009-10-29 21:18 ` Adrien 0 siblings, 2 replies; 14+ messages in thread From: Basile STARYNKEVITCH @ 2009-10-28 22:45 UTC (permalink / raw) To: Adrien; +Cc: Caml Mailing List 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! -- Basile STARYNKEVITCH http://starynkevitch.net/Basile/ email: basile<at>starynkevitch<dot>net mobile: +33 6 8501 2359 8, rue de la Faiencerie, 92340 Bourg La Reine, France *** opinions {are only mines, sont seulement les miennes} *** ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Caml-list] Binding C libraries which use variable arguments (stdarg.h) 2009-10-28 22:45 ` Basile STARYNKEVITCH @ 2009-10-29 8:55 ` Goswin von Brederlow 2009-10-29 21:37 ` Adrien 2009-10-29 21:18 ` Adrien 1 sibling, 1 reply; 14+ messages in thread From: Goswin von Brederlow @ 2009-10-29 8:55 UTC (permalink / raw) To: Basile STARYNKEVITCH; +Cc: Adrien, Caml Mailing List 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. MfG Goswin ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Caml-list] Binding C libraries which use variable arguments (stdarg.h) 2009-10-29 8:55 ` Goswin von Brederlow @ 2009-10-29 21:37 ` Adrien 2009-10-29 23:31 ` Goswin von Brederlow 0 siblings, 1 reply; 14+ messages in thread From: Adrien @ 2009-10-29 21:37 UTC (permalink / raw) To: Caml Mailing List 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. 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? --- Adrien Nader ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Caml-list] Binding C libraries which use variable arguments (stdarg.h) 2009-10-29 21:37 ` Adrien @ 2009-10-29 23:31 ` Goswin von Brederlow 0 siblings, 0 replies; 14+ messages in thread From: Goswin von Brederlow @ 2009-10-29 23:31 UTC (permalink / raw) To: Adrien; +Cc: Caml Mailing List 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 ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Caml-list] Binding C libraries which use variable arguments (stdarg.h) 2009-10-28 22:45 ` Basile STARYNKEVITCH 2009-10-29 8:55 ` Goswin von Brederlow @ 2009-10-29 21:18 ` Adrien 2009-10-30 9:35 ` Xavier Leroy 1 sibling, 1 reply; 14+ messages in thread From: Adrien @ 2009-10-29 21:18 UTC (permalink / raw) To: Caml Mailing List On 28/10/2009, Basile STARYNKEVITCH <basile@starynkevitch.net> wrote: > 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) Well, actually the only reason was that stdarg.h needs at least one non-variable argument (as opposed to varargs.h). ;-) Anyway, that doesn't change anything. >> 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 I'll probably go for that. The API won't be as nice as it could but at least, it's going to be safe and checked at compile-time. > 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. That could make a nicer API. Maybe for ocaml-gir 3 or 4. :-) > 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. On linux and x86, I could probably use an array where I would move by sizeof(some_type). I really want portability however (I want to use these bindings at least on windows too). > Time to go to bed. I am saying lot of non-sense. > > Bye! Thanks. :-) --- Adrien Nader ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Caml-list] Binding C libraries which use variable arguments (stdarg.h) 2009-10-29 21:18 ` Adrien @ 2009-10-30 9:35 ` Xavier Leroy 2009-11-01 9:31 ` Adrien 0 siblings, 1 reply; 14+ messages in thread From: Xavier Leroy @ 2009-10-30 9:35 UTC (permalink / raw) To: Adrien; +Cc: Caml Mailing List [Invoking a variadic C argument from OCaml] >> 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. > > On linux and x86, I could probably use an array where I would move by > sizeof(some_type). I really want portability however (I want to use > these bindings at least on windows too). It might be worth investigating the "libffi" library. If I guess correctly, it lets you synthesize calls to native C functions when the number and type of arguments are statically unknown. - Xavier Leroy ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Caml-list] Binding C libraries which use variable arguments (stdarg.h) 2009-10-30 9:35 ` Xavier Leroy @ 2009-11-01 9:31 ` Adrien 2009-11-01 11:07 ` Florian Weimer 0 siblings, 1 reply; 14+ messages in thread From: Adrien @ 2009-11-01 9:31 UTC (permalink / raw) To: Caml Mailing List On 30/10/2009, Xavier Leroy <Xavier.Leroy@inria.fr> wrote: > [Invoking a variadic C argument from OCaml] > >>> 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. >> >> On linux and x86, I could probably use an array where I would move by >> sizeof(some_type). I really want portability however (I want to use >> these bindings at least on windows too). > > It might be worth investigating the "libffi" library. If I guess > correctly, it lets you synthesize calls to native C functions when the > number and type of arguments are statically unknown. I had checked libffi but its readme (from gcc-4.3) stated variable arguments weren't supported. After some time I had doubts about the relevance of the documentation (the last change mentionned was from 98) and tried anyway. It turned out it worked on linux x86_32, linux x86_64, netbsd sparc64 with 32-bit userland, debian's kfreebsd amd64 and ppc32. There's windows which I haven't checked yet though. I posted my test code on vpaste.net[1]. I think it's good enough to actually check libffi works with variable arguments but it could probably be made better. Any comment welcome. I also asked on the libffi mailing-list and was told by someone it should work almost everywhere except on really exotic architectures. That means I'll probably go the libffi way. :-) [1] http://vpaste.net/6vPst? --- Adrien Nader ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Caml-list] Binding C libraries which use variable arguments (stdarg.h) 2009-11-01 9:31 ` Adrien @ 2009-11-01 11:07 ` Florian Weimer 2009-11-01 12:12 ` Adrien 0 siblings, 1 reply; 14+ messages in thread From: Florian Weimer @ 2009-11-01 11:07 UTC (permalink / raw) To: Adrien; +Cc: Caml Mailing List * Adrien: > It turned out it worked on linux x86_32, linux x86_64, netbsd sparc64 > with 32-bit userland, debian's kfreebsd amd64 and ppc32. There's > windows which I haven't checked yet though. x86_64 has different calling conventions for varargs and non-varargs functions. If it works for you, it's only by accident (e.g. because you aren't passing floating-point arguments). ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Caml-list] Binding C libraries which use variable arguments (stdarg.h) 2009-11-01 11:07 ` Florian Weimer @ 2009-11-01 12:12 ` Adrien 2009-11-01 12:16 ` Florian Weimer 0 siblings, 1 reply; 14+ messages in thread From: Adrien @ 2009-11-01 12:12 UTC (permalink / raw) To: Florian Weimer; +Cc: Caml Mailing List On 01/11/2009, Florian Weimer <fw@deneb.enyo.de> wrote: > * Adrien: > >> It turned out it worked on linux x86_32, linux x86_64, netbsd sparc64 >> with 32-bit userland, debian's kfreebsd amd64 and ppc32. There's >> windows which I haven't checked yet though. > > x86_64 has different calling conventions for varargs and non-varargs > functions. If it works for you, it's only by accident (e.g. because > you aren't passing floating-point arguments). > I tried a few things with "double" at first since I'm on x86_64 and got no warning and no problem whatsoever. The situation was a bit different with "float" however : > a.c:16: warning: ‘float’ is promoted to ‘double’ when passed through ‘...’ > a.c:16: note: (so you should pass ‘double’ not ‘float’ to ‘va_arg’) > a.c:16: note: if this code is reached, the program will abort Running the program yields a nice: "illegal hardware instruction ./a.out". :) The problem is the same on x86_32 however, and APIs are probably correct with regard to that. I'll see if I can add checks in ocaml-gir nonetheless. Thanks. --- Adrien Nader ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Caml-list] Binding C libraries which use variable arguments (stdarg.h) 2009-11-01 12:12 ` Adrien @ 2009-11-01 12:16 ` Florian Weimer 2009-11-01 14:58 ` Adrien 0 siblings, 1 reply; 14+ messages in thread From: Florian Weimer @ 2009-11-01 12:16 UTC (permalink / raw) To: Adrien; +Cc: Caml Mailing List * Adrien: > On 01/11/2009, Florian Weimer <fw@deneb.enyo.de> wrote: >> * Adrien: >> >>> It turned out it worked on linux x86_32, linux x86_64, netbsd sparc64 >>> with 32-bit userland, debian's kfreebsd amd64 and ppc32. There's >>> windows which I haven't checked yet though. >> >> x86_64 has different calling conventions for varargs and non-varargs >> functions. If it works for you, it's only by accident (e.g. because >> you aren't passing floating-point arguments). >> > > I tried a few things with "double" at first since I'm on x86_64 and > got no warning and no problem whatsoever. Could you check if libffi sets the %rax register to the number of floating-point arguments? (I've seen this working by mere chance in many cases.) ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Caml-list] Binding C libraries which use variable arguments (stdarg.h) 2009-11-01 12:16 ` Florian Weimer @ 2009-11-01 14:58 ` Adrien 2009-11-01 20:06 ` Richard Jones 2009-11-03 19:33 ` Florian Weimer 0 siblings, 2 replies; 14+ messages in thread From: Adrien @ 2009-11-01 14:58 UTC (permalink / raw) To: Florian Weimer; +Cc: Caml Mailing List On 01/11/2009, Florian Weimer <fw@deneb.enyo.de> wrote: > * Adrien: > >> On 01/11/2009, Florian Weimer <fw@deneb.enyo.de> wrote: >>> * Adrien: >>> >>>> It turned out it worked on linux x86_32, linux x86_64, netbsd sparc64 >>>> with 32-bit userland, debian's kfreebsd amd64 and ppc32. There's >>>> windows which I haven't checked yet though. >>> >>> x86_64 has different calling conventions for varargs and non-varargs >>> functions. If it works for you, it's only by accident (e.g. because >>> you aren't passing floating-point arguments). >>> >> >> I tried a few things with "double" at first since I'm on x86_64 and >> got no warning and no problem whatsoever. > > Could you check if libffi sets the %rax register to the number of > floating-point arguments? (I've seen this working by mere chance in > many cases.) > Unfortunately I don't know much about asm, I tried to check but failed (couldn't find what "leaq" meant). I found a few references indicating that libffi was properly doing that however. --- Adrien Nader ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Caml-list] Binding C libraries which use variable arguments (stdarg.h) 2009-11-01 14:58 ` Adrien @ 2009-11-01 20:06 ` Richard Jones 2009-11-03 19:33 ` Florian Weimer 1 sibling, 0 replies; 14+ messages in thread From: Richard Jones @ 2009-11-01 20:06 UTC (permalink / raw) To: Adrien; +Cc: Caml Mailing List On Sun, Nov 01, 2009 at 03:58:47PM +0100, Adrien wrote: > Unfortunately I don't know much about asm, I tried to check but failed > (couldn't find what "leaq" meant). The 'q' just means it's a Long Mode instruction (ie. x86-64's 64 bit mode). The instruction itself is "Load Effective Address" - it means it does an address calculation as if you were going to load/store something at that address, but instead puts the address itself (result of that calculation) in the target register. If I remember my rusty x86 assembler correctly, then: movl 4(%ebx),%eax ; load 4 bytes of data from address %ebx + 4, put in %eax lea 4(%ebx),%eax ; add %ebx + 4 and put that in %eax Rich. -- Richard Jones Red Hat ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Caml-list] Binding C libraries which use variable arguments (stdarg.h) 2009-11-01 14:58 ` Adrien 2009-11-01 20:06 ` Richard Jones @ 2009-11-03 19:33 ` Florian Weimer 1 sibling, 0 replies; 14+ messages in thread From: Florian Weimer @ 2009-11-03 19:33 UTC (permalink / raw) To: Adrien; +Cc: Caml Mailing List * Adrien: > I found a few references indicating that libffi was properly doing > that however. I looked at the assembly, and it is doing the right thing, but for the wrong reason. The "only load sse registers if ssecount non-zero" change in 2005 happens to put the SSE register count in the correct register, but this wasn't the intent of the change based on the ChangeLog entry. 8-) ^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2009-11-03 19:33 UTC | newest] Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2009-10-28 22:07 [Caml-list] Binding C libraries which use variable arguments (stdarg.h) Adrien 2009-10-28 22:45 ` Basile STARYNKEVITCH 2009-10-29 8:55 ` Goswin von Brederlow 2009-10-29 21:37 ` Adrien 2009-10-29 23:31 ` Goswin von Brederlow 2009-10-29 21:18 ` Adrien 2009-10-30 9:35 ` Xavier Leroy 2009-11-01 9:31 ` Adrien 2009-11-01 11:07 ` Florian Weimer 2009-11-01 12:12 ` Adrien 2009-11-01 12:16 ` Florian Weimer 2009-11-01 14:58 ` Adrien 2009-11-01 20:06 ` Richard Jones 2009-11-03 19:33 ` Florian Weimer
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox