From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Original-To: caml-list@yquem.inria.fr Delivered-To: caml-list@yquem.inria.fr Received: from mail1-relais-roc.national.inria.fr (mail1-relais-roc.national.inria.fr [192.134.164.82]) by yquem.inria.fr (Postfix) with ESMTP id B67D8BC37 for ; Fri, 30 Oct 2009 00:31:43 +0100 (CET) X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AvkBAM7C6UrZSMDdi2dsb2JhbACBT5l7AQEBCgsKBxEFwzWEPQQ X-IronPort-AV: E=Sophos;i="4.44,649,1249250400"; d="scan'208";a="39197739" Received: from fmmailgate01.web.de ([217.72.192.221]) by mail1-smtp-roc.national.inria.fr with ESMTP; 30 Oct 2009 00:31:43 +0100 Received: from smtp06.web.de (fmsmtp06.dlan.cinetic.de [172.20.5.172]) by fmmailgate01.web.de (Postfix) with ESMTP id B873F13485E5F; Fri, 30 Oct 2009 00:31:42 +0100 (CET) Received: from [95.208.117.111] (helo=frosties.localdomain) by smtp06.web.de with asmtp (TLSv1:AES256-SHA:256) (WEB.DE 4.110 #314) id 1N3eT0-0005Gp-00; Fri, 30 Oct 2009 00:31:42 +0100 Received: from mrvn by frosties.localdomain with local (Exim 4.69) (envelope-from ) id 1N3eSz-0005lF-Qa; Fri, 30 Oct 2009 00:31:41 +0100 From: Goswin von Brederlow To: Adrien Cc: Caml Mailing List Subject: Re: [Caml-list] Binding C libraries which use variable arguments (stdarg.h) References: <666572260910281507q74cb1c1at157c9e3c86070c69@mail.gmail.com> <4AE8C987.8020100@starynkevitch.net> <877huewpdc.fsf@frosties.localdomain> <666572260910291437w38283b27s1244f39f68a86b3e@mail.gmail.com> Date: Fri, 30 Oct 2009 00:31:41 +0100 In-Reply-To: <666572260910291437w38283b27s1244f39f68a86b3e@mail.gmail.com> (Adrien's message of "Thu, 29 Oct 2009 22:37:15 +0100") Message-ID: <87zl793hgi.fsf@frosties.localdomain> User-Agent: Gnus/5.110006 (No Gnus v0.6) XEmacs/21.4.22 (linux) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Sender: goswin-v-b@web.de X-Sender: goswin-v-b@web.de X-Provags-ID: V01U2FsdGVkX1/KIjz+evQL9YNj1FbogxoL6E6vK9tDtbNgmGnR LqKGscr8acwLz6x9xM5H08NupoXaufnSmkLZKnIPBjN+kwMk+l FIMJzS1Fw= X-Spam: no; 0.00; basile:01 basile:01 foo:01 stub:01 foo:01 ocaml:01 failwith:01 ocaml:01 variants:01 varargs:01 weis:01 printf:01 stub:01 varargs:01 compiler:01 Adrien writes: > On 29/10/2009, Goswin von Brederlow wrote: >> Basile STARYNKEVITCH 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