* 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 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: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
* 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
* 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
* 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-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
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