Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[Caml-list] Interfacing with C question...

17 views
Skip to first unread message

David Allsopp

unread,
Jan 24, 2007, 12:25:26 PM1/24/07
to OCaml List
Sorry if this an RADBOTFM case. Rule 2 in Chapter 18 of the manual states
that all local variables of type value must be declared using CAMLlocal
macros. However, later on when demonstrating caml_callback we get the
statements:

value* format_result_closure = caml_named_value("format_result");
return strdup(String_val(caml_callback(*format_result_closure, Val_int(n))))

(I've "simplified" the opening lines for clarity here - naturally it should
be static and once only!).

Two questions arise:

1. Presumably it's OK to cache values returned by caml_named_value without
declaring them in a CAMLlocal "call" or by using register_global_root?
2. The result of caml_callback is passed straight to String_val. Therefore,
if I expand the line to:

value result = caml_callback(*format_result_closure, Val_int(n)));
return strdup(String_val(result));

then does that work ok without using CAMLlocal1(result);

Ta!


David

_______________________________________________
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs

Remi Vanicat

unread,
Jan 25, 2007, 1:30:36 AM1/25/07
to OCaml List
2007/1/24, David Allsopp <dra-...@metastack.com>:

> Sorry if this an RADBOTFM case. Rule 2 in Chapter 18 of the manual states
> that all local variables of type value must be declared using CAMLlocal
> macros. However, later on when demonstrating caml_callback we get the
> statements:
>
> value* format_result_closure = caml_named_value("format_result");
> return strdup(String_val(caml_callback(*format_result_closure, Val_int(n))))
>
> (I've "simplified" the opening lines for clarity here - naturally it should
> be static and once only!).
>
> Two questions arise:
>
> 1. Presumably it's OK to cache values returned by caml_named_value without
> declaring them in a CAMLlocal "call" or by using register_global_root?

No, any C pointer to a caml value must be known to the caml GC,
because the caml GC might move the caml value. But you might no
declare such a pointer if you are sur that the GC won't be triger
between your affectation of the value to the C variable, and the use
of the C variable.*

In the given exemple, this is the case: nothing is done between the
affectation and the use.

By the way, when in doubt, or when you are a begginer not nowing well
how the GC work, you should always use the CAMLlocal call.

> 2. The result of caml_callback is passed straight to String_val. Therefore,
> if I expand the line to:
>
> value result = caml_callback(*format_result_closure, Val_int(n)));
> return strdup(String_val(result));
>
> then does that work ok without using CAMLlocal1(result);

Yes, for the same reason: you do nothing between the affectation of
the result function, and the use of the variable.

Hendrik Tews

unread,
Jan 25, 2007, 11:29:10 AM1/25/07
to caml...@yquem.inria.fr
"David Allsopp" <dra-...@metastack.com> writes:

Sorry if this an RADBOTFM case. Rule 2 in Chapter 18 of the manual states
that all local variables of type value must be declared using CAMLlocal
macros. However, later on when demonstrating caml_callback we get the
statements:

value* format_result_closure = caml_named_value("format_result");

Note the type! format_result_closure is not of type value, Rule 2
does not apply!

1. Presumably it's OK to cache values returned by caml_named_value without
declaring them in a CAMLlocal "call" or by using register_global_root?

Yes it is OK. And you cannot use CAMLlocal or
register_global_root, because they only deal with values and not
pointers to values. The manual guarantees that the value pointed
to by the result of caml_named_value doesn't move. Probably
caml_named_value allocates a value outside the heap, registers it
as a global root and gives you back its address.

value result = caml_callback(*format_result_closure, Val_int(n)));
return strdup(String_val(result));

then does that work ok without using CAMLlocal1(result);

Yes. You should think of values as pointers that point to data
that is moved around by the garbage collector. If there is any
chance that the garbage collector is called, then you must make
sure that it updates your pointer when it moves the data. Hence
you have to register the value.

If the garbage collector is not called under any circumstances
then the data will not move, the pointer doesn't need to get
updated and you don't have to register the value.

Furthermore, if your are sure Is_long(your_variable) is true
under any circumstances, you don't have to register
your_variable, because it is not a pointer.

Of course all that is strongly discouraged.

Bye,

Hendrik

skaller

unread,
Jan 25, 2007, 1:33:00 PM1/25/07
to Hendrik Tews
On Thu, 2007-01-25 at 17:26 +0100, Hendrik Tews wrote:
> "David Allsopp" <dra-...@metastack.com> writes:
>
> Sorry if this an RADBOTFM case.

> And you cannot use CAMLlocal or
> register_global_root,

FWIW: I encourage people not to just use the high level macros
like CAMLlocal: they hide what really happens.

Instead, read the section describing the lower level macros
and figure out how the gc *actually* works.

Roughly speaking the rules are:

(a) certain operations, including allocation, trigger the gc.

(b) you must ensure allocated store is initialised when
the gc is triggered (so it doesn't chase off into the wild
blue yonder)

(c) you may not retain copies of values in stores across
calls that trigger the gc because it may move blocks and
adjust pointers

(d) there are some exceptions: if the value is an integer
or unboxed float it won't change (obviously).

(e) Every allocated block you want to use must be reachable
from a root when the gc is triggered

The high level macros reduce thinking by making variables
a root and ensuring they're initialised, however they're
conservative and may incur a performance overhead by doing
this when it isn't necessary. For any kind of serious glue
logic you really need to understand the low level requirements,
in particular the fact stuff moves means you have to know
precisely when the gc is triggered anyhow -- since you can't
write C without temporary creation and sequence points
being considered.

It takes a bit of reading, thinking, and question asking
to figure the gc out, but it is worth it: it really isn't that
hard and IMHO the higher level macros just confuse things
by obscuring the real constraints.

[Once you know how it works .. *then* you can use the
higher level macros because you then know what they're
sugar for .. :]

--
John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net

Robert Roessler

unread,
Jan 25, 2007, 7:18:22 PM1/25/07
to caml...@yquem.inria.fr
skaller wrote:
> ...

> It takes a bit of reading, thinking, and question asking
> to figure the gc out, but it is worth it: it really isn't that
> hard and IMHO the higher level macros just confuse things
> by obscuring the real constraints.
>
> [Once you know how it works .. *then* you can use the
> higher level macros because you then know what they're
> sugar for .. :]

While understanding what is going on under the covers *is* important,
there is a key reason for using the macros: as the documented and
recommended interface to the OCaml GC machinery, their use gives you a
much better chance that your code will easily / automagically survive
changes to the GC mechanism in the future... like if direct support of
multi- cores and processors ever becomes a reality. ;)

Robert Roessler
roes...@rftp.com
http://www.rftp.com

0 new messages