From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.1.3 (2006-06-01) on yquem.inria.fr X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=AWL autolearn=disabled version=3.1.3 Received: from discorde.inria.fr (discorde.inria.fr [192.93.2.38]) by yquem.inria.fr (Postfix) with ESMTP id C7239BC6B for ; Fri, 7 Sep 2007 04:34:58 +0200 (CEST) Received: from ipmail02.adl2.internode.on.net (ipmail02.adl2.internode.on.net [203.16.214.141]) by discorde.inria.fr (8.13.6/8.13.6) with ESMTP id l872YtnD023781 for ; Fri, 7 Sep 2007 04:34:57 +0200 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AgAAANNT4EZ5LFL5/2dsb2JhbAAM X-IronPort-AV: E=Sophos;i="4.20,219,1186324200"; d="scan'208";a="183176898" Received: from ppp121-44-82-249.lns10.syd6.internode.on.net (HELO [192.168.1.201]) ([121.44.82.249]) by ipmail02.adl2.internode.on.net with ESMTP; 07 Sep 2007 12:04:28 +0930 Subject: Re: [Caml-list] Wrapping a C function that takes a variable number of arguments From: skaller To: Joel Reymont Cc: Caml List In-Reply-To: <6A9B2713-FD3C-4E27-89B1-002A05DA2D26@gmail.com> References: <6A9B2713-FD3C-4E27-89B1-002A05DA2D26@gmail.com> Content-Type: text/plain Date: Fri, 07 Sep 2007 12:34:26 +1000 Message-Id: <1189132466.6596.16.camel@rosella.wigram> Mime-Version: 1.0 X-Mailer: Evolution 2.10.1 Content-Transfer-Encoding: 7bit X-Miltered: at discorde with ID 46E0B8D0.000 by Joe's j-chkmail (http://j-chkmail . ensmp . fr)! X-Spam: no; 0.00; 0100,:01 fprintf:01 variants:01 gcc:01 compiler:01 gcc:01 implements:01 varargs:01 2.0:98 fmt:01 fmt:01 sourceforge:01 wrote:01 integer:01 caml-list:01 On Fri, 2007-09-07 at 00:24 +0100, Joel Reymont wrote: > I'm trying to figure out how to wrap Cocoa's NSLog [1]. > > It's basically just like fprintf in that the signature looks like this > > void NSLog(NSString *format, ...); > > There must be an idiomatic way of creating a wrapper for such a > function, probably with a bit of dark magic. Would someone please > show me how? Variants. In Caml you pass NSLog(fmt, [Int 1; Double 2.0]) The wrapper can then decode the 'fmt' and check that the corresonding variant has a suitable type. It is not possible, however, to call the C function in a conforming way. Instead you have to cheat. If there is a vNSLog(fmt, va_args) function you're cool, the cheat is easy. If you're using gcc as your C compiler, read up on __builtin_va_list and how gcc implements varargs. The best cheat is this one: scan the fmt, and break it into separate %codes like: "Hello %s today %d\n" will be (say) Str.split on % to give "Hello " "s today " "d\n" Now call NSLog 3 times, adding the % back to the second and third strings: NSLog("Hello "); NSLog("%s today ",vs); NSLog("%d\n",vi); in a loop, obviously, which sets vs if the variant is a string, vi if it is an integer, vd if it is a double, etc etc. Note this will NOT work if NSLog isn't functorial, that is: NSLog (x ^ y) = NSLog (x); NSlog (y) eg if it adds an 'end of line' or 'date and time stamp' to the log message, then this technique won't work so well. -- John Skaller Felix, successor to C++: http://felix.sf.net