Mailing list for all users of the OCaml language and system.
 help / color / mirror / Atom feed
From: Bob Matcuk <Hamartiology@squeg.net>
To: caml-list@yquem.inria.fr
Subject: va_arg values
Date: Sat, 13 Jan 2007 19:18:49 -0500	[thread overview]
Message-ID: <200701132310.l0DNArug026315@discorde.inria.fr> (raw)

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


             reply	other threads:[~2007-01-13 23:10 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-01-14  0:18 Bob Matcuk [this message]
2007-01-15 10:44 ` [Caml-list] " Richard Jones
2007-01-15 23:46   ` Bob Matcuk
2007-01-16  4:18 ` Chris King
2007-01-16  7:50   ` Bob Matcuk
2007-01-16 10:47   ` Mattias Engdegård
2007-01-21 17:25 ` Xavier Leroy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200701132310.l0DNArug026315@discorde.inria.fr \
    --to=hamartiology@squeg.net \
    --cc=caml-list@yquem.inria.fr \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox