caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* C interface style question
@ 2006-01-18 18:28 Thomas Fischbacher
  2006-01-18 19:18 ` [Caml-list] " Gerd Stolpmann
  2006-01-19  0:39 ` Jacques Garrigue
  0 siblings, 2 replies; 20+ messages in thread
From: Thomas Fischbacher @ 2006-01-18 18:28 UTC (permalink / raw)
  To: caml-list


value-type parameters to C functions exported to OCaml should be 
registered with CAMLparamX(...). Does this hold in general, or is it 
considered acceptable/appropriate to just ignore this for "immediate" 
values that do not hold pointers, but, say, int, bool etc. values?

-- 
regards,               tf@cip.physik.uni-muenchen.de              (o_
 Thomas Fischbacher -  http://www.cip.physik.uni-muenchen.de/~tf  //\
(lambda (n) ((lambda (p q r) (p p q r)) (lambda (g x y)           V_/_
(if (= x 0) y (g g (- x 1) (* x y)))) n 1))                  (Debian GNU)


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Caml-list] C interface style question
  2006-01-18 18:28 C interface style question Thomas Fischbacher
@ 2006-01-18 19:18 ` Gerd Stolpmann
  2006-01-18 20:32   ` Florent Monnier
  2006-01-19  0:39 ` Jacques Garrigue
  1 sibling, 1 reply; 20+ messages in thread
From: Gerd Stolpmann @ 2006-01-18 19:18 UTC (permalink / raw)
  To: Thomas Fischbacher; +Cc: caml-list

Am Mittwoch, den 18.01.2006, 19:28 +0100 schrieb Thomas Fischbacher:
> value-type parameters to C functions exported to OCaml should be 
> registered with CAMLparamX(...). Does this hold in general, or is it 
> considered acceptable/appropriate to just ignore this for "immediate" 
> values that do not hold pointers, but, say, int, bool etc. values?

If you don't allocate O'Caml memory you need not to register the
parameters.

Gerd
-- 
------------------------------------------------------------
Gerd Stolpmann * Viktoriastr. 45 * 64293 Darmstadt * Germany 
gerd@gerd-stolpmann.de          http://www.gerd-stolpmann.de
Telefon: 06151/153855                  Telefax: 06151/997714
------------------------------------------------------------


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Caml-list] C interface style question
  2006-01-18 19:18 ` [Caml-list] " Gerd Stolpmann
@ 2006-01-18 20:32   ` Florent Monnier
  2006-01-18 21:31     ` Gerd Stolpmann
  0 siblings, 1 reply; 20+ messages in thread
From: Florent Monnier @ 2006-01-18 20:32 UTC (permalink / raw)
  To: caml-list

> > value-type parameters to C functions exported to OCaml should be
> > registered with CAMLparamX(...). Does this hold in general, or is it
> > considered acceptable/appropriate to just ignore this for "immediate"
> > values that do not hold pointers, but, say, int, bool etc. values?
>
> If you don't allocate O'Caml memory you need not to register the
> parameters.

And in this case there's no need to use CAMLreturn(), return is enough,
is it right ?


-- 


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Caml-list] C interface style question
  2006-01-18 20:32   ` Florent Monnier
@ 2006-01-18 21:31     ` Gerd Stolpmann
  2006-01-18 23:21       ` Florent Monnier
  0 siblings, 1 reply; 20+ messages in thread
From: Gerd Stolpmann @ 2006-01-18 21:31 UTC (permalink / raw)
  To: Florent Monnier; +Cc: caml-list

Am Mittwoch, den 18.01.2006, 21:32 +0100 schrieb Florent Monnier:
> > > value-type parameters to C functions exported to OCaml should be
> > > registered with CAMLparamX(...). Does this hold in general, or is it
> > > considered acceptable/appropriate to just ignore this for "immediate"
> > > values that do not hold pointers, but, say, int, bool etc. values?
> >
> > If you don't allocate O'Caml memory you need not to register the
> > parameters.
> 
> And in this case there's no need to use CAMLreturn(), return is enough,
> is it right ?

That would not even compile without a CAMLparam.

Gerd
-- 
------------------------------------------------------------
Gerd Stolpmann * Viktoriastr. 45 * 64293 Darmstadt * Germany 
gerd@gerd-stolpmann.de          http://www.gerd-stolpmann.de
Telefon: 06151/153855                  Telefax: 06151/997714
------------------------------------------------------------


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Caml-list] C interface style question
  2006-01-18 21:31     ` Gerd Stolpmann
@ 2006-01-18 23:21       ` Florent Monnier
  2006-01-18 23:43         ` Robert Roessler
  0 siblings, 1 reply; 20+ messages in thread
From: Florent Monnier @ 2006-01-18 23:21 UTC (permalink / raw)
  To: caml-list

> > > > value-type parameters to C functions exported to OCaml should be
> > > > registered with CAMLparamX(...). Does this hold in general, or is it
> > > > considered acceptable/appropriate to just ignore this for "immediate"
> > > > values that do not hold pointers, but, say, int, bool etc. values?
> > >
> > > If you don't allocate O'Caml memory you need not to register the
> > > parameters.
> >
> > And in this case there's no need to use CAMLreturn(), return is enough,
> > is it right ?
>
> That would not even compile without a CAMLparam.

Most of the LablGL functions have no CAMLparam and no CAMLreturn.
Here is just an exemple:

CAMLprim value
ml_glDeleteTexture (value texture_id)
{
    GLuint id = Int32_val(texture_id);
    glDeleteTextures(1, &id);
    return Val_unit;
}

And I think the author does know his way around OCaml tricks

-- 
Regards


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Caml-list] C interface style question
  2006-01-18 23:21       ` Florent Monnier
@ 2006-01-18 23:43         ` Robert Roessler
  0 siblings, 0 replies; 20+ messages in thread
From: Robert Roessler @ 2006-01-18 23:43 UTC (permalink / raw)
  To: Caml-list

Florent Monnier wrote:
>>>>> value-type parameters to C functions exported to OCaml should be
>>>>> registered with CAMLparamX(...). Does this hold in general, or is it
>>>>> considered acceptable/appropriate to just ignore this for "immediate"
>>>>> values that do not hold pointers, but, say, int, bool etc. values?
>>>> If you don't allocate O'Caml memory you need not to register the
>>>> parameters.
>>> And in this case there's no need to use CAMLreturn(), return is enough,
>>> is it right ?
>> That would not even compile without a CAMLparam.
> 
> Most of the LablGL functions have no CAMLparam and no CAMLreturn.
> Here is just an exemple:
> 
> CAMLprim value
> ml_glDeleteTexture (value texture_id)
> {
>     GLuint id = Int32_val(texture_id);
>     glDeleteTextures(1, &id);
>     return Val_unit;
> }
> 
> And I think the author does know his way around OCaml tricks

I think Gerd's point was regarding the CAMLreturn... *that* will not 
compile without the function having a CAMLparam of some "arity" 
present. ;)

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


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Caml-list] C interface style question
  2006-01-18 18:28 C interface style question Thomas Fischbacher
  2006-01-18 19:18 ` [Caml-list] " Gerd Stolpmann
@ 2006-01-19  0:39 ` Jacques Garrigue
  2006-01-19  3:17   ` skaller
  2006-01-19 12:13   ` [Caml-list] C interface style question Thomas Fischbacher
  1 sibling, 2 replies; 20+ messages in thread
From: Jacques Garrigue @ 2006-01-19  0:39 UTC (permalink / raw)
  To: Thomas.Fischbacher; +Cc: caml-list

From: Thomas Fischbacher <Thomas.Fischbacher@Physik.Uni-Muenchen.DE>

> value-type parameters to C functions exported to OCaml should be 
> registered with CAMLparamX(...). Does this hold in general, or is it 
> considered acceptable/appropriate to just ignore this for "immediate" 
> values that do not hold pointers, but, say, int, bool etc. values?

Registration is required to have the GC properly update the values.
The GC may be called by any allocation.
So it is only safe not to register a parameter (or a variable) in any
of the following 4 cases.
1) you know that it can only hold a non-pointer value (int, bool, ...)
   (i.e. the GC has nothing to update)
2) there are no allocations in your function
3) the parameter is not accessed after the first allocation
4) for a new variable whose contents is returned, there is no
   allocation between the setting of the variable and return.

(1) and (2) are relatively easy to see, but (3) and (4) are a bit
trickier (particularly with side-effecting expressions), so
it is not a bad idea to register more parameters than strictly
necessary.

Jacques


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Caml-list] C interface style question
  2006-01-19  0:39 ` Jacques Garrigue
@ 2006-01-19  3:17   ` skaller
  2006-01-19 14:09     ` Damien Doligez
  2006-01-19 12:13   ` [Caml-list] C interface style question Thomas Fischbacher
  1 sibling, 1 reply; 20+ messages in thread
From: skaller @ 2006-01-19  3:17 UTC (permalink / raw)
  To: Jacques Garrigue; +Cc: Thomas.Fischbacher, caml-list

On Thu, 2006-01-19 at 09:39 +0900, Jacques Garrigue wrote:
> From: Thomas Fischbacher <Thomas.Fischbacher@Physik.Uni-Muenchen.DE>
> 
> > value-type parameters to C functions exported to OCaml should be 
> > registered with CAMLparamX(...). Does this hold in general, or is it 
> > considered acceptable/appropriate to just ignore this for "immediate" 
> > values that do not hold pointers, but, say, int, bool etc. values?
> 
> Registration is required to have the GC properly update the values.
> The GC may be called by any allocation.
> So it is only safe not to register a parameter (or a variable) in any
> of the following 4 cases.
> 1) you know that it can only hold a non-pointer value (int, bool, ...)
>    (i.e. the GC has nothing to update)
> 2) there are no allocations in your function
> 3) the parameter is not accessed after the first allocation
> 4) for a new variable whose contents is returned, there is no
>    allocation between the setting of the variable and return.
> 
> (1) and (2) are relatively easy to see, but (3) and (4) are a bit
> trickier (particularly with side-effecting expressions), so
> it is not a bad idea to register more parameters than strictly
> necessary.

Unless I'm mistaken, 'registration' with these macros 
is never required: these macros are simply a high level 
abstraction layer providing convenience and relative safety. 

The Ocaml manual explains all this fairly well IMHO,
the low level interface is well documented, Hendrik Tews 
version is cool:

http://wwwtcs.inf.tu-dresden.de/~tews/htmlman-3.09/manual032.html

See 18.5.2 -- IMHO the low level interface, whilst requiring
more work to apply, is actually easier to understand.

Just one 'BTW': I have seen some code using Field() macro
with incorrect C. You must NOT do this:

	MyType *p = ...
	(MyType*)Field(v,n) = p;

it isn't valid ISO C for *any* type MyType (not even 'value').
You would have to do it like this:

	*(MyType**)(void*)&Field(v,n) = p; // **

However I strongly recommend instead

	StoreField(v,n,(value)(void*)p);

The incorrect usage was not detected by older versions of gcc.
Gcc 4.x does detect this error. The workaround (**) is
the ONLY correct way to cast an lvalue in ISO C. This problem
arises in some larger codes where a macro has been used
to do the type conversion .. and it appeared to work
but was in fact invalid C. For example:

	#define MyThing(v) (MyType*)Field(v,2)

is not a good idea, since

	MyThing(v) = ...

is invalid ISO C but may not even produce a warning. You would
have to instead say:

	#define MyThing(v) (*(MyType**)(void*)&Field(v,2))

but it seems better to rewrite your code so values and
lvalues are distinguished by usage (eg 'get' and 'set' macros).
[The intention of the macros is usually to abstract away the
field number]

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


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Caml-list] C interface style question
  2006-01-19  0:39 ` Jacques Garrigue
  2006-01-19  3:17   ` skaller
@ 2006-01-19 12:13   ` Thomas Fischbacher
  2006-01-19 13:49     ` Jacques Garrigue
  1 sibling, 1 reply; 20+ messages in thread
From: Thomas Fischbacher @ 2006-01-19 12:13 UTC (permalink / raw)
  To: Jacques Garrigue; +Cc: caml-list


On Thu, 19 Jan 2006, Jacques Garrigue wrote:

> Registration is required to have the GC properly update the values.
> The GC may be called by any allocation.

Just by allocations in the local C code? Is this (and will this always 
be) a guaranteed property? How about future extensions and multithreading?

> So it is only safe not to register a parameter (or a variable) in any
> of the following 4 cases.
> 1) you know that it can only hold a non-pointer value (int, bool, ...)
>    (i.e. the GC has nothing to update)
> 2) there are no allocations in your function
> 3) the parameter is not accessed after the first allocation
> 4) for a new variable whose contents is returned, there is no
>    allocation between the setting of the variable and return.
> 
> (1) and (2) are relatively easy to see, but (3) and (4) are a bit
> trickier (particularly with side-effecting expressions), so
> it is not a bad idea to register more parameters than strictly
> necessary.

Can I take this as an official position of the OCaml team on the behaviour 
of the C interface?

-- 
regards,               tf@cip.physik.uni-muenchen.de              (o_
 Thomas Fischbacher -  http://www.cip.physik.uni-muenchen.de/~tf  //\
(lambda (n) ((lambda (p q r) (p p q r)) (lambda (g x y)           V_/_
(if (= x 0) y (g g (- x 1) (* x y)))) n 1))                  (Debian GNU)


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Caml-list] C interface style question
  2006-01-19 12:13   ` [Caml-list] C interface style question Thomas Fischbacher
@ 2006-01-19 13:49     ` Jacques Garrigue
  0 siblings, 0 replies; 20+ messages in thread
From: Jacques Garrigue @ 2006-01-19 13:49 UTC (permalink / raw)
  To: Thomas.Fischbacher; +Cc: caml-list

From: Thomas Fischbacher <Thomas.Fischbacher@Physik.Uni-Muenchen.DE>

> > Registration is required to have the GC properly update the values.
> > The GC may be called by any allocation.
> 
> Just by allocations in the local C code? Is this (and will this always 
> be) a guaranteed property? How about future extensions and multithreading?

This is the point of the global locking mechanism. Only one thread may
manipulate ocaml values (both access and allocation.)
I'm not sure about the eternal guarantee, but most libraries around
depend essentially on this property.

> > So it is only safe not to register a parameter (or a variable) in any
> > of the following 4 cases.
> > 1) you know that it can only hold a non-pointer value (int, bool, ...)
> >    (i.e. the GC has nothing to update)
> > 2) there are no allocations in your function
> > 3) the parameter is not accessed after the first allocation
> > 4) for a new variable whose contents is returned, there is no
> >    allocation between the setting of the variable and return.
> > 
> > (1) and (2) are relatively easy to see, but (3) and (4) are a bit
> > trickier (particularly with side-effecting expressions), so
> > it is not a bad idea to register more parameters than strictly
> > necessary.
> 
> Can I take this as an official position of the OCaml team on the behaviour 
> of the C interface?

For this you would have to ask Damien Doligez :-)
But this seems to be basic enough to be safe.
Rules about assignment are much more tricky!

      Jacques


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Caml-list] C interface style question
  2006-01-19  3:17   ` skaller
@ 2006-01-19 14:09     ` Damien Doligez
  2006-01-19 14:17       ` Thomas Fischbacher
                         ` (3 more replies)
  0 siblings, 4 replies; 20+ messages in thread
From: Damien Doligez @ 2006-01-19 14:09 UTC (permalink / raw)
  To: caml users


On Jan 19, 2006, at 04:17, skaller wrote:

> 	MyType *p = ...
> 	(MyType*)Field(v,n) = p;
>
> it isn't valid ISO C for *any* type MyType (not even 'value').

Indeed.  My K&R explicitely says: "a cast does not yield an l-value".


> You would have to do it like this:
>
> 	*(MyType**)(void*)&Field(v,n) = p; // **


You should only do this if you want strange GC bugs and random
crashes, because you are walking around the write barrier and
that's a bad idea.


> However I strongly recommend instead
>
> 	StoreField(v,n,(value)(void*)p);

This is the only way.  Always use Store_field, Store_double_field,
and Store_double_val.


On Jan 19, 2006, at 13:13, Thomas Fischbacher wrote:

> On Thu, 19 Jan 2006, Jacques Garrigue wrote:
>
>> Registration is required to have the GC properly update the values.
>> The GC may be called by any allocation.
>
> Just by allocations in the local C code? Is this (and will this always
> be) a guaranteed property? How about future extensions and  
> multithreading?

Any allocation performed during the execution of your code.  Including
context switches and signals, if you're doing begin_blocking_section.


>> So it is only safe not to register a parameter (or a variable) in any
>> of the following 4 cases.
>> 1) you know that it can only hold a non-pointer value (int,  
>> bool, ...)
>>    (i.e. the GC has nothing to update)
>> 2) there are no allocations in your function
>> 3) the parameter is not accessed after the first allocation
>> 4) for a new variable whose contents is returned, there is no
>>    allocation between the setting of the variable and return.
>>
>> [...]
>
> Can I take this as an official position of the OCaml team on the  
> behaviour
> of the C interface?

The official position is: none of these is guaranteed to hold in future
releases.  You should play it safe and register all your local  
variables.

If you really need all the speed you can get, you might use these tricks
in the two functions where your program spends all its time, but I'd  
still
advise against it.

-- Damien


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Caml-list] C interface style question
  2006-01-19 14:09     ` Damien Doligez
@ 2006-01-19 14:17       ` Thomas Fischbacher
  2006-01-19 14:24       ` Thomas Fischbacher
                         ` (2 subsequent siblings)
  3 siblings, 0 replies; 20+ messages in thread
From: Thomas Fischbacher @ 2006-01-19 14:17 UTC (permalink / raw)
  To: Damien Doligez; +Cc: caml users


On Thu, 19 Jan 2006, Damien Doligez wrote:

> The official position is: none of these is guaranteed to hold in future
> releases.  You should play it safe and register all your local variables.

That settles it. Thanks.

-- 
regards,               tf@cip.physik.uni-muenchen.de              (o_
 Thomas Fischbacher -  http://www.cip.physik.uni-muenchen.de/~tf  //\
(lambda (n) ((lambda (p q r) (p p q r)) (lambda (g x y)           V_/_
(if (= x 0) y (g g (- x 1) (* x y)))) n 1))                  (Debian GNU)


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Caml-list] C interface style question
  2006-01-19 14:09     ` Damien Doligez
  2006-01-19 14:17       ` Thomas Fischbacher
@ 2006-01-19 14:24       ` Thomas Fischbacher
  2006-01-19 14:52         ` Olivier Andrieu
  2006-01-19 15:15       ` Thomas Fischbacher
  2006-01-30 13:12       ` On Store_field() Thomas Fischbacher
  3 siblings, 1 reply; 20+ messages in thread
From: Thomas Fischbacher @ 2006-01-19 14:24 UTC (permalink / raw)
  To: Damien Doligez; +Cc: caml users


On Thu, 19 Jan 2006, Damien Doligez wrote:

> > StoreField(v,n,(value)(void*)p);
> 
> This is the only way.  Always use Store_field, Store_double_field,
> and Store_double_val.

One more question about this: can I interface a C function in such a way 
that it uses an OCaml float array to store its output data, i.e. pass 
&(Double_field(ml_output,0)) as a double* "output parameter"?

Of course, I could always go through a bigarray, or use intermediate 
storage. But is there a direct way to do this?

-- 
regards,               tf@cip.physik.uni-muenchen.de              (o_
 Thomas Fischbacher -  http://www.cip.physik.uni-muenchen.de/~tf  //\
(lambda (n) ((lambda (p q r) (p p q r)) (lambda (g x y)           V_/_
(if (= x 0) y (g g (- x 1) (* x y)))) n 1))                  (Debian GNU)


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Caml-list] C interface style question
  2006-01-19 14:24       ` Thomas Fischbacher
@ 2006-01-19 14:52         ` Olivier Andrieu
  2006-01-20 10:49           ` Damien Doligez
  0 siblings, 1 reply; 20+ messages in thread
From: Olivier Andrieu @ 2006-01-19 14:52 UTC (permalink / raw)
  To: Thomas Fischbacher; +Cc: caml-list

 Thomas Fischbacher [Thursday 19 January 2006] :
 >
 > 
 > On Thu, 19 Jan 2006, Damien Doligez wrote:
 > 
 > > > StoreField(v,n,(value)(void*)p);
 > > 
 > > This is the only way.  Always use Store_field,
 > > Store_double_field, and Store_double_val.
 > 
 > One more question about this: can I interface a C function in such
 > a way that it uses an OCaml float array to store its output data,
 > i.e. pass &(Double_field(ml_output,0)) as a double* "output
 > parameter"?

You can only do this on platform that accept doubles aligned on word
boundaries (such as x86). On those platforms, OCaml's config.h
undefines ARCH_ALIGN_DOUBLE. So your code might look like this :

,----
|   double *c_array;
| #ifdef ARCH_ALIGN_DOUBLE
|   c_array = /* allocate temporary storage and copy the caml float array */
| #else
|   c_array = (double *) ml_array;
| #endif
| 
|   /* use c_array */
| 
| #ifdef ARCH_ALIGN_DOUBLE
|   free (c_array);
| #endif
`----

(And the part that "uses c_array" must not make any (caml) allocation)

-- 
   Olivier


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Caml-list] C interface style question
  2006-01-19 14:09     ` Damien Doligez
  2006-01-19 14:17       ` Thomas Fischbacher
  2006-01-19 14:24       ` Thomas Fischbacher
@ 2006-01-19 15:15       ` Thomas Fischbacher
  2006-01-30 13:12       ` On Store_field() Thomas Fischbacher
  3 siblings, 0 replies; 20+ messages in thread
From: Thomas Fischbacher @ 2006-01-19 15:15 UTC (permalink / raw)
  Cc: caml users


Sorry if I annoy you, but I have one more question:

Is it (= will it always be) permissible to nest Field / Store_field 
macros?

-- 
regards,               tf@cip.physik.uni-muenchen.de              (o_
 Thomas Fischbacher -  http://www.cip.physik.uni-muenchen.de/~tf  //\
(lambda (n) ((lambda (p q r) (p p q r)) (lambda (g x y)           V_/_
(if (= x 0) y (g g (- x 1) (* x y)))) n 1))                  (Debian GNU)


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Caml-list] C interface style question
  2006-01-19 14:52         ` Olivier Andrieu
@ 2006-01-20 10:49           ` Damien Doligez
  2006-02-12 20:40             ` Olivier Andrieu
  0 siblings, 1 reply; 20+ messages in thread
From: Damien Doligez @ 2006-01-20 10:49 UTC (permalink / raw)
  To: caml users

On Jan 19, 2006, at 15:52, Olivier Andrieu wrote:

>  Thomas Fischbacher [Thursday 19 January 2006] :
>> One more question about this: can I interface a C function in such
>> a way that it uses an OCaml float array to store its output data,
>> i.e. pass &(Double_field(ml_output,0)) as a double* "output
>> parameter"?
>
> You can only do this on platform that accept doubles aligned on word
> boundaries (such as x86). On those platforms, OCaml's config.h
> undefines ARCH_ALIGN_DOUBLE. So your code might look like this :
>
> ,----
> |   double *c_array;
> | #ifdef ARCH_ALIGN_DOUBLE
> |   c_array = /* allocate temporary storage and copy the caml float  
> array */
> | #else
> |   c_array = (double *) ml_array;
> | #endif
> |
> |   /* use c_array */
> |
> | #ifdef ARCH_ALIGN_DOUBLE
> |   free (c_array);
> | #endif
> `----

This is correct, except for the way you get the pointer.  You should  
do it
properly with &(Double_field(ml_array,0)).  There is no guarantee that
the value ml_array points to the first element of the array.

Thomas wanted an "out" parameter, and the above code is for an "in"
parameter, but it should work if you make the obvious changes.


On Jan 19, 2006, at 16:15, Thomas Fischbacher wrote:

> Is it (= will it always be) permissible to nest Field / Store_field
> macros?

If you are not doing some strange things, the Store_field will always
be outermost, and some Fields will be nested inside it.  In that case,
it is safe.  Otherwise, you're using C macros with arguments that have
side-effects, and your program will never work anyway :-)

-- Damien


^ permalink raw reply	[flat|nested] 20+ messages in thread

* On Store_field()
  2006-01-19 14:09     ` Damien Doligez
                         ` (2 preceding siblings ...)
  2006-01-19 15:15       ` Thomas Fischbacher
@ 2006-01-30 13:12       ` Thomas Fischbacher
  2006-01-30 14:05         ` [Caml-list] " Olivier Andrieu
  3 siblings, 1 reply; 20+ messages in thread
From: Thomas Fischbacher @ 2006-01-30 13:12 UTC (permalink / raw)
  To: Damien Doligez; +Cc: caml users


On Thu, 19 Jan 2006, Damien Doligez wrote:

> >However I strongly recommend instead
> >
> > StoreField(v,n,(value)(void*)p);
> 
> This is the only way.  Always use Store_field, Store_double_field,
> and Store_double_val.

What you *actually* forgot to tell people is that OCaml unfortunately 
lacks a macro with which one can store C pointers to alloc_final 
allocated blocks. If one writes to those using e.g.

  ml_vector = alloc_final(2, finalize_vector, 1, 10);
  Store_field(ml_vector, 1,(value)vector);

with vector being a C pointer to a structure, this may or may not lead to 
random crashes at very unexpected places - because (as I think now) the 
Store_field macro will be over-eager trying to tell the GC about the 
value stored - which it should just ignore in this particular case!

Indeed, this has been discussed before, I think:

http://groups.google.de/group/fa.caml/msg/60ace9405fcf60c0?dmode=source&hl=de

So, I would strongly suggest introducing a macro that behaves like this:

#define Store_c_field(block,offset,x) (Field(block,offset)=(value)x)

so that one could then use

  Store_c_field(ml_vector, 1,vector);

I actually just spent a full week tracking down precisely this issue in a 
not particularly trivial C library interface I am building right now. 
After looking in the weirdest places, ensuring it's not an issue with the 
library wrapped, or the trickier pieces of my own code, I even started 
patching debugging code into the OCaml bytecode's GC and rebuilding...

So, *please* do the world a great favour and tell people about that issue 
in the C interface documentation!

-- 
Thomas Fischbacher
tf@cip.physik.uni-muenchen.de
(Yes, grumpy. Did not sleep over the weekend due to this issue...)


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Caml-list] On Store_field()
  2006-01-30 13:12       ` On Store_field() Thomas Fischbacher
@ 2006-01-30 14:05         ` Olivier Andrieu
  0 siblings, 0 replies; 20+ messages in thread
From: Olivier Andrieu @ 2006-01-30 14:05 UTC (permalink / raw)
  To: Thomas Fischbacher; +Cc: caml users

 Thomas Fischbacher [Monday 30 January 2006] :
 >
 > 
 > On Thu, 19 Jan 2006, Damien Doligez wrote:
 > 
 > > >However I strongly recommend instead
 > > >
 > > > StoreField(v,n,(value)(void*)p);
 > > 
 > > This is the only way.  Always use Store_field, Store_double_field,
 > > and Store_double_val.
 > 
 > What you *actually* forgot to tell people is that OCaml
 > unfortunately lacks a macro with which one can store C pointers to
 > alloc_final allocated blocks. If one writes to those using e.g.
 > 
 >   ml_vector = alloc_final(2, finalize_vector, 1, 10);
 >   Store_field(ml_vector, 1,(value)vector);
 > 
 > with vector being a C pointer to a structure, this may or may not
 > lead to random crashes at very unexpected places - because (as I
 > think now) the Store_field macro will be over-eager trying to tell
 > the GC about the value stored - which it should just ignore in this
 > particular case!
 > 
 > Indeed, this has been discussed before, I think:
 > 
 > http://groups.google.de/group/fa.caml/msg/60ace9405fcf60c0?dmode=source&hl=de
 > 
 > So, I would strongly suggest introducing a macro that behaves like this:
 > 
 > #define Store_c_field(block,offset,x) (Field(block,offset)=(value)x)
 > 
 > so that one could then use
 > 
 >   Store_c_field(ml_vector, 1,vector);
 > 
 > I actually just spent a full week tracking down precisely this
 > issue in a not particularly trivial C library interface I am
 > building right now.  After looking in the weirdest places, ensuring
 > it's not an issue with the library wrapped, or the trickier pieces
 > of my own code, I even started patching debugging code into the
 > OCaml bytecode's GC and rebuilding...
 > 
 > So, *please* do the world a great favour and tell people about that
 > issue in the C interface documentation!

Well, it already does:
,----
| Rule 3   Assignments to the fields of structured blocks must be done
| with the Store_field macro (for normal blocks) or Store_double_field
| macro (for arrays and records of floating-point numbers). Other
| assignments must not use Store_field nor Store_double_field. 
`----
Final (aka custom) blocks are not structured blocks but raw blocks
(not traced by the GC), so assignements to those blocks falls in the
"other assignments" category.

A good way to deal with custom blocks in the C code is to create a
small struct type and access the content of the block through this type.

struct custom_foo_bar {
  foo *pointer1;
  bar *pointer3;
};

value alloc_foo_bar (foo *f, bar *b)
{
  value v;
  struct custom_foo_bar *s;
  v = alloc_custom (&foo_bar_ops, sizeof struct custom_foo_bar, 1, 10);
  s = Data_custom_val (v);
  s->p1 = f;
  s->p2 = b;
  return v;
}

-- 
   Olivier


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Caml-list] C interface style question
  2006-01-20 10:49           ` Damien Doligez
@ 2006-02-12 20:40             ` Olivier Andrieu
  2006-02-13  9:45               ` Damien Doligez
  0 siblings, 1 reply; 20+ messages in thread
From: Olivier Andrieu @ 2006-02-12 20:40 UTC (permalink / raw)
  To: Damien Doligez; +Cc: caml users

Replying to a somehow old message here ...

 Damien Doligez [Friday 20 January 2006] :
 >
 > On Jan 19, 2006, at 15:52, Olivier Andrieu wrote:
 > 
 > >  Thomas Fischbacher [Thursday 19 January 2006] :
 > >> One more question about this: can I interface a C function in such
 > >> a way that it uses an OCaml float array to store its output data,
 > >> i.e. pass &(Double_field(ml_output,0)) as a double* "output
 > >> parameter"?
 > >
 > > You can only do this on platform that accept doubles aligned on word
 > > boundaries (such as x86). On those platforms, OCaml's config.h
 > > undefines ARCH_ALIGN_DOUBLE. So your code might look like this :
 > >
 > > ,----
 > > |   double *c_array;
 > > | #ifdef ARCH_ALIGN_DOUBLE
 > > |   c_array = /* allocate temporary storage and copy the caml float  
 > > array */
 > > | #else
 > > |   c_array = (double *) ml_array;
 > > | #endif
 > > |
 > > |   /* use c_array */
 > > |
 > > | #ifdef ARCH_ALIGN_DOUBLE
 > > |   free (c_array);
 > > | #endif
 > > `----
 > 
 > This is correct, except for the way you get the pointer.  You should  
 > do it
 > properly with &(Double_field(ml_array,0)).  There is no guarantee that
 > the value ml_array points to the first element of the array.

Err... I don't get it.

in mlvalues.h, I have (with ARCH_ALIGN_DOUBLE undefined) :

  #define Double_val(v) (* (double *)(v))
  #define Double_field(v,i) Double_val((value)((double *)(v) + (i)))

so &(Double_field(ml_array, 0)) looks pretty equivalent to a simple
cast to double*, no ? 

Also how would it happen that ml_array does not point to first element
of the array ?

-- 
   Olivier


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Caml-list] C interface style question
  2006-02-12 20:40             ` Olivier Andrieu
@ 2006-02-13  9:45               ` Damien Doligez
  0 siblings, 0 replies; 20+ messages in thread
From: Damien Doligez @ 2006-02-13  9:45 UTC (permalink / raw)
  To: caml users


On Feb 12, 2006, at 21:40, Olivier Andrieu wrote:

>> This is correct, except for the way you get the pointer.  You should
>> do it
>> properly with &(Double_field(ml_array,0)).  There is no guarantee  
>> that
>> the value ml_array points to the first element of the array.

> in mlvalues.h, I have (with ARCH_ALIGN_DOUBLE undefined) :
>
>   #define Double_val(v) (* (double *)(v))
>   #define Double_field(v,i) Double_val((value)((double *)(v) + (i)))
>
> so &(Double_field(ml_array, 0)) looks pretty equivalent to a simple
> cast to double*, no ?

You should treat those definitions as abstract.  It is purely for
efficiency reasons that they are defined as macros.

If we decide to change the representation of Caml values (admittedly
a pretty remote possibility at this point), the pointer might not
point to the first field of the array anymore.  For example. it could
point to the header, or to the second byte of the contents.

-- Damien


^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2006-02-13  9:45 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-01-18 18:28 C interface style question Thomas Fischbacher
2006-01-18 19:18 ` [Caml-list] " Gerd Stolpmann
2006-01-18 20:32   ` Florent Monnier
2006-01-18 21:31     ` Gerd Stolpmann
2006-01-18 23:21       ` Florent Monnier
2006-01-18 23:43         ` Robert Roessler
2006-01-19  0:39 ` Jacques Garrigue
2006-01-19  3:17   ` skaller
2006-01-19 14:09     ` Damien Doligez
2006-01-19 14:17       ` Thomas Fischbacher
2006-01-19 14:24       ` Thomas Fischbacher
2006-01-19 14:52         ` Olivier Andrieu
2006-01-20 10:49           ` Damien Doligez
2006-02-12 20:40             ` Olivier Andrieu
2006-02-13  9:45               ` Damien Doligez
2006-01-19 15:15       ` Thomas Fischbacher
2006-01-30 13:12       ` On Store_field() Thomas Fischbacher
2006-01-30 14:05         ` [Caml-list] " Olivier Andrieu
2006-01-19 12:13   ` [Caml-list] C interface style question Thomas Fischbacher
2006-01-19 13:49     ` Jacques Garrigue

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).