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=MSGID_FROM_MTA_HEADER 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 53D40BC63 for ; Sun, 14 Jan 2007 00:10:55 +0100 (CET) Received: from alnrmhc12.comcast.net (alnrmhc12.comcast.net [204.127.225.92]) by discorde.inria.fr (8.13.6/8.13.6) with ESMTP id l0DNArug026315 for ; Sun, 14 Jan 2007 00:10:54 +0100 Message-Id: <200701132310.l0DNArug026315@discorde.inria.fr> Received: from monkey (c-24-3-185-40.hsd1.mn.comcast.net[24.3.185.40]) by comcast.net (alnrmhc12) with SMTP id <20070113231052b1200jmuo2e>; Sat, 13 Jan 2007 23:10:52 +0000 From: Bob Matcuk To: caml-list@yquem.inria.fr Date: Sat, 13 Jan 2007 19:18:49 -0500 Subject: va_arg values X-Mailer: Sylpheed version 2.2.9 (GTK+ 2.10.6; x86_64-pc-linux-gnu), randfrom v2.0.1 by Bob Matcuk Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit X-j-chkmail-Score: MSGID : 45A966FD.000 on discorde : j-chkmail score : X : 0/20 1 0.000 -> 1 X-Miltered: at discorde with ID 45A966FD.000 by Joe's j-chkmail (http://j-chkmail . ensmp . fr)! X-Spam: no; 0.00; camlparam:01 stack:01 stack:01 params:01 camlparam:01 sizeof:01 hash:01 failwith:01 camlreturn:01 arrays:01 pointers:01 gpg:01 char:01 exception:01 exception:01 I've been wondering what is the best way to write a C function that takes a variable number of value arguments. Lets say, for example, that I was writing a function that took an object, a string (specifying a method on the object), and a variable number of arguments to pass to the method. The function would then construct an array (with the object being the first element) from these arguments and pass it along to caml_callbackN. This function, of course, would only ever be called by other C functions. The thing that I guess I'm caught up on is the fact that I cannot directly apply CAMLparam to these variable arguments. Some calling conventions place all arguments on the stack, in which case CAMLparamN could be used (as long as you knew whether the stack was building up or down). However, some do not do this (the AMD64 calling convention, for example, puts the first 6 arguments in registers, the rest on the stack). I guess the real question is: is it even necessary to worry about this? The function, as I said, will only ever be called from other C functions (who have already designated these values as being params/local to themselves, assuming they are written correctly). I seem to recall reading somewhere that if you write a function that will only ever be called from other C functions that have already registered the values (via CAMLparam/CAMLlocal), then it's unnecessary to do it again. The function doesn't allocate any new values either, so it shouldn't trip the GC anyway, right? The function should, therefore, be something like this: value func(value obj, char *method, int n, ...) { va_list ap; int i; value *args = calloc(n + 1, sizeof(value)); value r; args[0] = obj; va_start(ap, n); for (i = 0; i < n; i++) args[i + 1] = va_arg(ap, value); va_end(ap); r = caml_callbackN(caml_get_public_method(obj, hash_variant(method)), n + 1, args); free(args); return r; } Should probably check calloc for success and maybe throw an exception if it failed... Which actually brings me to another quick question: if I throw an exception, say caml_failwith("..."), is it necessary to still call CAMLreturn after it? Or will the exception cause the function to exit? Is it an invalid assumption that it is unnecessary to bother with the CAMLparam/CAMLlocal stuff since there's nothing to trip the GC? If so, what is the best way to handle all the CAMLparam/CAMLlocal stuff? For example, CAMLlocalN(args, n + 1) is invalid because C does not allow you to declare dynamic arrays. Looping over the arguments with va_start/for loop/va_arg and calling CAMLparam on them is also invalid because it would be declaring the caml__root_##x variable within the for loop. I have typed up some code that should work if it is necessary, but it's messy and if CAMLparam is ever changed, it's likely I'll need to change my code too. I want to avoid that. One last quick question: is the line "args[i + 1] = va_arg(ap, value);" above legal? args[] is an array of value and va_arg(ap, value) will return a value. So, essentially, it's the same thing as the assignment in the following example: value func(value v1) { value v2 = v1; ... } I know values are just pointers so it is syntactically correct, but what I'm asking is: is it safe to do? Should I be using some function instead to create a copy of the value? Thanks in advance for any insight! -- Bob Matcuk http://www.Squeg.Net/ Explanation of My Return Address, GPG Key: http://www.Squeg.Net/returnAddr.php hamartiology - http://www.kokogiak.com/logolepsy/ow_h.html#hamartiology