* [Caml-list] Val_int vs caml_copy_nativeint @ 2011-08-08 3:15 Erik de Castro Lopo 2011-08-08 3:48 ` Romain Beauxis ` (2 more replies) 0 siblings, 3 replies; 19+ messages in thread From: Erik de Castro Lopo @ 2011-08-08 3:15 UTC (permalink / raw) To: caml-list Hi all, I'm writing a C stub function to allow the calling of a C library function from ocaml. The return from the stub is a tuple and I'm doing this: /* Package up the result as a tuple. */ v_response = caml_alloc_tuple (3) ; Store_field (v_response, 0, Val_int (width)) ; Store_field (v_response, 1, Val_int (height)) ; Store_field (v_response, 2, caml_copy_string (code)) ; CAMLreturn (v_response) ; The above works now, but didn't work when I was using caml_copy_nativeint() instead of Val_int() and I'd like to know why. I found it especially confusing because caml_copy_string() worked and was obvioulsy the right thing to do. Cheers, Erik -- ---------------------------------------------------------------------- Erik de Castro Lopo http://www.mega-nerd.com/ ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [Caml-list] Val_int vs caml_copy_nativeint 2011-08-08 3:15 [Caml-list] Val_int vs caml_copy_nativeint Erik de Castro Lopo @ 2011-08-08 3:48 ` Romain Beauxis 2011-08-08 3:59 ` Guillaume Yziquel 2011-08-08 3:53 ` Guillaume Yziquel 2011-08-08 5:20 ` malc 2 siblings, 1 reply; 19+ messages in thread From: Romain Beauxis @ 2011-08-08 3:48 UTC (permalink / raw) To: caml-list 2011/8/7 Erik de Castro Lopo <mle+ocaml@mega-nerd.com>: > Hi all, Hi, > I'm writing a C stub function to allow the calling of a C library > function from ocaml. The return from the stub is a tuple and I'm > doing this: > > /* Package up the result as a tuple. */ > v_response = caml_alloc_tuple (3) ; > > Store_field (v_response, 0, Val_int (width)) ; > Store_field (v_response, 1, Val_int (height)) ; > Store_field (v_response, 2, caml_copy_string (code)) ; > > CAMLreturn (v_response) ; > > The above works now, but didn't work when I was using > caml_copy_nativeint() instead of Val_int() and I'd like to know > why. I found it especially confusing because caml_copy_string() > worked and was obvioulsy the right thing to do. Reading very briefly the headers. is seems to me that intnat = value = long. Could it be that on the arch you're using sizeof(int) < sizeof(long) ? Romain ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [Caml-list] Val_int vs caml_copy_nativeint 2011-08-08 3:48 ` Romain Beauxis @ 2011-08-08 3:59 ` Guillaume Yziquel 2011-08-08 7:49 ` Erik de Castro Lopo 0 siblings, 1 reply; 19+ messages in thread From: Guillaume Yziquel @ 2011-08-08 3:59 UTC (permalink / raw) To: Romain Beauxis; +Cc: caml-list Le Sunday 07 Aug 2011 à 22:48:08 (-0500), Romain Beauxis a écrit : > 2011/8/7 Erik de Castro Lopo <mle+ocaml@mega-nerd.com>: > > Hi all, > > Hi, > > > I'm writing a C stub function to allow the calling of a C library > > function from ocaml. The return from the stub is a tuple and I'm > > doing this: > > > > /* Package up the result as a tuple. */ > > v_response = caml_alloc_tuple (3) ; > > > > Store_field (v_response, 0, Val_int (width)) ; > > Store_field (v_response, 1, Val_int (height)) ; > > Store_field (v_response, 2, caml_copy_string (code)) ; > > > > CAMLreturn (v_response) ; > > > > The above works now, but didn't work when I was using > > caml_copy_nativeint() instead of Val_int() and I'd like to know > > why. I found it especially confusing because caml_copy_string() > > worked and was obvioulsy the right thing to do. > > Reading very briefly the headers. is seems to me that intnat = value = > long. Could it be that on the arch you're using sizeof(int) < > sizeof(long) ? > > Romain Given that Val_int is Val_long (in mlvalues.h): #define Val_int(x) Val_long(x) it's not an issue with this piece of code. But depending on what "doesn't work" means and on the declarations of width and height, then sizeof(int) < sizeof(long) may explain the issue. -- Guillaume Yziquel ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [Caml-list] Val_int vs caml_copy_nativeint 2011-08-08 3:59 ` Guillaume Yziquel @ 2011-08-08 7:49 ` Erik de Castro Lopo 0 siblings, 0 replies; 19+ messages in thread From: Erik de Castro Lopo @ 2011-08-08 7:49 UTC (permalink / raw) To: caml-list Guillaume Yziquel wrote: > Given that Val_int is Val_long (in mlvalues.h): > > #define Val_int(x) Val_long(x) > > it's not an issue with this piece of code. > > But depending on what "doesn't work" means and on the declarations of > width and height, then sizeof(int) < sizeof(long) may explain the issue. The width and height variables are both defined as int and I'm working on 32 bit Linux. Doesn't work means I don't get the value I think I should (small integers in the range [16, 144]) but rather gte values that look more like pointers. Erik -- ---------------------------------------------------------------------- Erik de Castro Lopo http://www.mega-nerd.com/ ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [Caml-list] Val_int vs caml_copy_nativeint 2011-08-08 3:15 [Caml-list] Val_int vs caml_copy_nativeint Erik de Castro Lopo 2011-08-08 3:48 ` Romain Beauxis @ 2011-08-08 3:53 ` Guillaume Yziquel 2011-08-08 7:46 ` Erik de Castro Lopo 2011-08-08 5:20 ` malc 2 siblings, 1 reply; 19+ messages in thread From: Guillaume Yziquel @ 2011-08-08 3:53 UTC (permalink / raw) To: caml-list Le Monday 08 Aug 2011 à 13:15:04 (+1000), Erik de Castro Lopo a écrit : > Hi all, > > I'm writing a C stub function to allow the calling of a C library > function from ocaml. The return from the stub is a tuple and I'm > doing this: > > /* Package up the result as a tuple. */ > v_response = caml_alloc_tuple (3) ; > > Store_field (v_response, 0, Val_int (width)) ; > Store_field (v_response, 1, Val_int (height)) ; > Store_field (v_response, 2, caml_copy_string (code)) ; > > CAMLreturn (v_response) ; > > The above works now, but didn't work when I was using > caml_copy_nativeint() instead of Val_int() and I'd like to know > why. I found it especially confusing because caml_copy_string() > worked and was obvioulsy the right thing to do. Did you use CAMLlocal on v_response? Why don't you use some intermediate variable to store the result of caml_copy_nativeint beforehand and then use Store_field (or even a Field () = assignment with caml_alloc_small this case)? Judging by the code of caml_copy_nativeint in ints.c: CAMLexport value caml_copy_nativeint(intnat i) { value res = caml_alloc_custom(&caml_nativeint_ops, sizeof(intnat), 0, 1); Nativeint_val(res) = i; return res; } and of Store_field in memory.h #define Store_field(block, offset, val) do{ \ mlsize_t caml__temp_offset = (offset); \ value caml__temp_val = (val); \ caml_modify (&Field ((block), caml__temp_offset), caml__temp_val); \ }while(0) I do not see why that wouldn't work if CAMLlocal is properly used on v_response. If it's not properly used, you may be invalidating the v_response pointer when evaluating caml_copy_nativeint in the line value caml__temp_val = (val); Other than that, I do not really see an issue with your code. What do you mean by "doesn't work" precisely? > Cheers, > Erik -- Guillaume Yziquel ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [Caml-list] Val_int vs caml_copy_nativeint 2011-08-08 3:53 ` Guillaume Yziquel @ 2011-08-08 7:46 ` Erik de Castro Lopo 2011-08-08 8:03 ` Guillaume Yziquel 0 siblings, 1 reply; 19+ messages in thread From: Erik de Castro Lopo @ 2011-08-08 7:46 UTC (permalink / raw) To: caml-list Guillaume Yziquel wrote: > What do you mean by "doesn't work" precisely? The integer value I assign in the C file (and print out for a sanity check) ends up as what looks like an address in the Ocaml code. Erik -- ---------------------------------------------------------------------- Erik de Castro Lopo http://www.mega-nerd.com/ ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [Caml-list] Val_int vs caml_copy_nativeint 2011-08-08 7:46 ` Erik de Castro Lopo @ 2011-08-08 8:03 ` Guillaume Yziquel 2011-08-08 9:17 ` Mathias Kende 2011-08-08 17:24 ` Xavier Leroy 0 siblings, 2 replies; 19+ messages in thread From: Guillaume Yziquel @ 2011-08-08 8:03 UTC (permalink / raw) To: caml-list Le Monday 08 Aug 2011 à 17:46:19 (+1000), Erik de Castro Lopo a écrit : > Guillaume Yziquel wrote: > > > What do you mean by "doesn't work" precisely? > > The integer value I assign in the C file (and print out for a > sanity check) ends up as what looks like an address in the > Ocaml code. > > Erik Then I do not see anything wrong if the code snippet you sent. However, when you change Val_int to caml_copy_nativeint, the layout of the tuple is different. With Val_int, you have an integral value in the tuple's field. With caml_copy_nativeint, you have a pointer in the tuple's field. So if you keep the same OCaml code when reading the result value, it's no surprise that the pointer is shown in place of the integer you expected. But this is just guessing. -- Guillaume Yziquel ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [Caml-list] Val_int vs caml_copy_nativeint 2011-08-08 8:03 ` Guillaume Yziquel @ 2011-08-08 9:17 ` Mathias Kende 2011-08-08 17:24 ` Xavier Leroy 1 sibling, 0 replies; 19+ messages in thread From: Mathias Kende @ 2011-08-08 9:17 UTC (permalink / raw) To: caml-list Le lundi 08 août 2011 à 10:03 +0200, Guillaume Yziquel a écrit : > With Val_int, you have an integral value in the tuple's field. > > With caml_copy_nativeint, you have a pointer in the tuple's field. More explicitly, Val_int creates you a value of type int in the OCaml world, while caml_copy_nativeint creates you a value of type natint in the OCaml world. That's why you have two different "functions" in the first place. natints (and strings) are allocated blocks in OCaml so you need to copy the data from the C world to some place in OCaml heap. Hence the caml_copy_... function. You don not need such function for ints which are directly stored in the value variable. Mathias ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [Caml-list] Val_int vs caml_copy_nativeint 2011-08-08 8:03 ` Guillaume Yziquel 2011-08-08 9:17 ` Mathias Kende @ 2011-08-08 17:24 ` Xavier Leroy 2011-08-09 1:33 ` Erik de Castro Lopo 1 sibling, 1 reply; 19+ messages in thread From: Xavier Leroy @ 2011-08-08 17:24 UTC (permalink / raw) To: caml-list On 08/08/2011 10:03 AM, Guillaume Yziquel wrote: > Then I do not see anything wrong if the code snippet you sent. However, > when you change Val_int to caml_copy_nativeint, the layout of the tuple > is different. [...] So if you keep the same OCaml code when reading > the result value, it's no surprise that the pointer is shown in > place of the integer you expected. This is good advice indeed: make sure your Caml type declaration matches the data representation that your Caml/C stub implements... > /* Package up the result as a tuple. */ > v_response = caml_alloc_tuple (3) ; > Store_field (v_response, 0, Val_int (width)) ; > Store_field (v_response, 1, Val_int (height)) ; > Store_field (v_response, 2, caml_copy_string (code)) ; > CAMLreturn (v_response) ; Additionally, do make sure that "v_response" is registered with the GC (declared with one of the CAMLlocal macros). If both conditions are met, your code should be all right. If it still misbehaves, feel free to post a repro case on the bug tracker http://caml.inria.fr/mantis - Xavier Leroy ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [Caml-list] Val_int vs caml_copy_nativeint 2011-08-08 17:24 ` Xavier Leroy @ 2011-08-09 1:33 ` Erik de Castro Lopo 2011-08-09 1:40 ` Romain Beauxis ` (2 more replies) 0 siblings, 3 replies; 19+ messages in thread From: Erik de Castro Lopo @ 2011-08-09 1:33 UTC (permalink / raw) To: caml-list Xavier Leroy wrote: > On 08/08/2011 10:03 AM, Guillaume Yziquel wrote: > > > Then I do not see anything wrong if the code snippet you sent. However, > > when you change Val_int to caml_copy_nativeint, the layout of the tuple > > is different. [...] So if you keep the same OCaml code when reading > > the result value, it's no surprise that the pointer is shown in > > place of the integer you expected. > > This is good advice indeed: make sure your Caml type declaration > matches the data representation that your Caml/C stub implements... > > > /* Package up the result as a tuple. */ > > v_response = caml_alloc_tuple (3) ; > > Store_field (v_response, 0, Val_int (width)) ; > > Store_field (v_response, 1, Val_int (height)) ; > > Store_field (v_response, 2, caml_copy_string (code)) ; > > CAMLreturn (v_response) ; > > Additionally, do make sure that "v_response" is registered with the GC > (declared with one of the CAMLlocal macros). This is strange, it wasn't declared with a CAMLlocal macro and it was working, but if I do declare it with one the program segfaults during garbage collection (caml_oldify_local_roots). The program is small, so I've included the working version of the C stub code below. In the Ocaml code I have: external iec16022ecc200 : int -> (* size *) string -> (* code *) (int * int * string) = "caml_iec16022ecc200" The C stub code below works. If I change "value v_response" to "CAMLlocal1 (v_response)" it segfaults. If I use caml_copy_nativeint() instead of Val_int when I'm preparing the v_response tuple I get what looks like a pointer instead of the small integer (ie [16, 160] range) I was expecting. Cheers, Erik #include <caml/mlvalues.h> #include <caml/alloc.h> #include <caml/memory.h> #include <caml/custom.h> #include <caml/fail.h> #include <caml/callback.h> #include <caml/bigarray.h> #include <stdio.h> #include <string.h> #include <assert.h> #include <iec16022ecc200.h> typedef union { unsigned char * u ; signed char * s ; char * c ; } flexi_char_ptr_t ; CAMLprim value caml_iec16022ecc200 (value v_size, value v_code) { unsigned char buffer [2048] ; flexi_char_ptr_t code, barcode ; int width, height, k ; value v_response ; CAMLparam2 (v_size, v_code) ; width = height = Int_val (v_size) ; code.c = String_val (v_code) ; barcode.u = iec16022ecc200 (&width, &height, NULL, strlen (code.c), code.u, NULL, NULL, NULL) ; if (barcode.u == NULL) { failwith ("iec16022ecc200 failed") ; fprintf (stderr, "%s %d: Should never get here.\n", __FILE__, __LINE__) ; exit (1) ; } ; /* Sanity check the buffer size. */ assert (width * height < (int) sizeof (buffer) - 1) ; /* Need to convert the resulting 0x00 and 0x01 byte string to a text * string that we can pass back to Ocaml. */ for (k = 0 ; k < width * height ; k++) buffer [k] = barcode.c [k] ? '1' : '0' ; /* Make sure buffer is string terminated. */ buffer [width * height] = 0 ; /* Free the memory allocated by iec16022ecc200(). */ free (barcode.u) ; barcode.u = buffer ; /* Package up the result as a tuple. */ v_response = caml_alloc_tuple (3) ; Store_field (v_response, 0, Val_int (width)) ; Store_field (v_response, 1, Val_int (height)) ; Store_field (v_response, 2, caml_copy_string (barcode.c)) ; CAMLreturn (v_response) ; } /* caml_iec16022ecc200 */ -- ---------------------------------------------------------------------- Erik de Castro Lopo http://www.mega-nerd.com/ ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [Caml-list] Val_int vs caml_copy_nativeint 2011-08-09 1:33 ` Erik de Castro Lopo @ 2011-08-09 1:40 ` Romain Beauxis 2011-08-09 8:44 ` David Allsopp 2011-08-09 22:53 ` Erik de Castro Lopo 2 siblings, 0 replies; 19+ messages in thread From: Romain Beauxis @ 2011-08-09 1:40 UTC (permalink / raw) To: caml-list 2011/8/8 Erik de Castro Lopo <mle+ocaml@mega-nerd.com>: > Xavier Leroy wrote: > >> On 08/08/2011 10:03 AM, Guillaume Yziquel wrote: >> >> > Then I do not see anything wrong if the code snippet you sent. However, >> > when you change Val_int to caml_copy_nativeint, the layout of the tuple >> > is different. [...] So if you keep the same OCaml code when reading >> > the result value, it's no surprise that the pointer is shown in >> > place of the integer you expected. >> >> This is good advice indeed: make sure your Caml type declaration >> matches the data representation that your Caml/C stub implements... >> >> > /* Package up the result as a tuple. */ >> > v_response = caml_alloc_tuple (3) ; >> > Store_field (v_response, 0, Val_int (width)) ; >> > Store_field (v_response, 1, Val_int (height)) ; >> > Store_field (v_response, 2, caml_copy_string (code)) ; >> > CAMLreturn (v_response) ; >> >> Additionally, do make sure that "v_response" is registered with the GC >> (declared with one of the CAMLlocal macros). > > This is strange, it wasn't declared with a CAMLlocal macro and it > was working, but if I do declare it with one the program segfaults > during garbage collection (caml_oldify_local_roots). > > The program is small, so I've included the working version of the > C stub code below. In the Ocaml code I have: > > external iec16022ecc200 : > int -> (* size *) > string -> (* code *) > (int * int * string) = "caml_iec16022ecc200" > > The C stub code below works. If I change "value v_response" to > "CAMLlocal1 (v_response)" it segfaults. If I use caml_copy_nativeint() > instead of Val_int when I'm preparing the v_response tuple I get what > looks like a pointer instead of the small integer (ie [16, 160] range) > I was expecting. > > Cheers, > Erik > > #include <caml/mlvalues.h> > #include <caml/alloc.h> > #include <caml/memory.h> > #include <caml/custom.h> > #include <caml/fail.h> > #include <caml/callback.h> > #include <caml/bigarray.h> > > #include <stdio.h> > #include <string.h> > #include <assert.h> > > #include <iec16022ecc200.h> > > > typedef union > { unsigned char * u ; > signed char * s ; > char * c ; > } flexi_char_ptr_t ; > > > CAMLprim value > caml_iec16022ecc200 (value v_size, value v_code) > { unsigned char buffer [2048] ; > flexi_char_ptr_t code, barcode ; > int width, height, k ; > value v_response ; This look odd to me. I always place CAMLParam and CAMLlocal declarations are the very beginning of the code.. Don't know if this matters here but perhaps.. > CAMLparam2 (v_size, v_code) ; > > width = height = Int_val (v_size) ; > code.c = String_val (v_code) ; > > barcode.u = iec16022ecc200 (&width, &height, NULL, strlen (code.c), code.u, NULL, NULL, NULL) ; > > if (barcode.u == NULL) > { failwith ("iec16022ecc200 failed") ; > fprintf (stderr, "%s %d: Should never get here.\n", __FILE__, __LINE__) ; > exit (1) ; > } ; > > /* Sanity check the buffer size. */ > assert (width * height < (int) sizeof (buffer) - 1) ; > > /* Need to convert the resulting 0x00 and 0x01 byte string to a text > * string that we can pass back to Ocaml. */ > for (k = 0 ; k < width * height ; k++) > buffer [k] = barcode.c [k] ? '1' : '0' ; > > /* Make sure buffer is string terminated. */ > buffer [width * height] = 0 ; > > /* Free the memory allocated by iec16022ecc200(). */ > free (barcode.u) ; > > barcode.u = buffer ; > > /* Package up the result as a tuple. */ > v_response = caml_alloc_tuple (3) ; > > Store_field (v_response, 0, Val_int (width)) ; > Store_field (v_response, 1, Val_int (height)) ; > Store_field (v_response, 2, caml_copy_string (barcode.c)) ; > > CAMLreturn (v_response) ; > } /* caml_iec16022ecc200 */ Romain ^ permalink raw reply [flat|nested] 19+ messages in thread
* RE: [Caml-list] Val_int vs caml_copy_nativeint 2011-08-09 1:33 ` Erik de Castro Lopo 2011-08-09 1:40 ` Romain Beauxis @ 2011-08-09 8:44 ` David Allsopp 2011-08-09 10:07 ` malc 2011-08-09 22:53 ` Erik de Castro Lopo 2 siblings, 1 reply; 19+ messages in thread From: David Allsopp @ 2011-08-09 8:44 UTC (permalink / raw) To: caml-list Erik de Castro Lopo wrote: > Xavier Leroy wrote: > > > On 08/08/2011 10:03 AM, Guillaume Yziquel wrote: > > > > > Then I do not see anything wrong if the code snippet you sent. > > > However, when you change Val_int to caml_copy_nativeint, the layout > > > of the tuple is different. [...] So if you keep the same OCaml code > > > when reading the result value, it's no surprise that the pointer is > > > shown in place of the integer you expected. > > > > This is good advice indeed: make sure your Caml type declaration > > matches the data representation that your Caml/C stub implements... > > > > > /* Package up the result as a tuple. */ > > > v_response = caml_alloc_tuple (3) ; > > > Store_field (v_response, 0, Val_int (width)) ; > > > Store_field (v_response, 1, Val_int (height)) ; > > > Store_field (v_response, 2, caml_copy_string (code)) ; > > > CAMLreturn (v_response) ; > > > > Additionally, do make sure that "v_response" is registered with the GC > > (declared with one of the CAMLlocal macros). > > This is strange, it wasn't declared with a CAMLlocal macro and it was > working, but if I do declare it with one the program segfaults during > garbage collection (caml_oldify_local_roots). If you altered this but left the program exactly the same then you violated rule 1 in 18.5.1 of the manual: CAMLparamn must come first. The result is predictable - you attempt to allocate a local variable before the local root is properly initialised... That said, in your specific example, my understanding is that it should be OK not using CAMLlocal because you return v_response with CAMLreturn before the GC could be triggered (no allocations or callbacks between caml_alloc_tuple and CAMLreturn). Whether that's a) correct and b) sensible (i.e. whether the performance "boost" justifies the commenting needed in the code to explain how brittle it is) is another matter! David ^ permalink raw reply [flat|nested] 19+ messages in thread
* RE: [Caml-list] Val_int vs caml_copy_nativeint 2011-08-09 8:44 ` David Allsopp @ 2011-08-09 10:07 ` malc 2011-08-09 10:43 ` David Allsopp 0 siblings, 1 reply; 19+ messages in thread From: malc @ 2011-08-09 10:07 UTC (permalink / raw) To: David Allsopp; +Cc: caml-list On Tue, 9 Aug 2011, David Allsopp wrote: > Erik de Castro Lopo wrote: > > Xavier Leroy wrote: > > > > > On 08/08/2011 10:03 AM, Guillaume Yziquel wrote: > > > > > > > Then I do not see anything wrong if the code snippet you sent. > > > > However, when you change Val_int to caml_copy_nativeint, the layout > > > > of the tuple is different. [...] So if you keep the same OCaml code > > > > when reading the result value, it's no surprise that the pointer is > > > > shown in place of the integer you expected. > > > > > > This is good advice indeed: make sure your Caml type declaration > > > matches the data representation that your Caml/C stub implements... > > > > > > > /* Package up the result as a tuple. */ > > > > v_response = caml_alloc_tuple (3) ; > > > > Store_field (v_response, 0, Val_int (width)) ; > > > > Store_field (v_response, 1, Val_int (height)) ; > > > > Store_field (v_response, 2, caml_copy_string (code)) ; > > > > CAMLreturn (v_response) ; > > > > > > Additionally, do make sure that "v_response" is registered with the GC > > > (declared with one of the CAMLlocal macros). > > > > This is strange, it wasn't declared with a CAMLlocal macro and it was > > working, but if I do declare it with one the program segfaults during > > garbage collection (caml_oldify_local_roots). > > If you altered this but left the program exactly the same then you violated rule 1 in 18.5.1 of the manual: CAMLparamn must come first. The result is predictable - you attempt to allocate a local variable before the local root is properly initialised... > > That said, in your specific example, my understanding is that it should > be OK not using CAMLlocal because you return v_response with CAMLreturn > before the GC could be triggered (no allocations or callbacks between > caml_alloc_tuple and CAMLreturn). I'm puzzled by this, caml_copy_string does allocation.. > Whether that's a) correct and b) > sensible (i.e. whether the performance "boost" justifies the commenting > needed in the code to explain how brittle it is) is another matter! > > > David > > > -- mailto:av1474@comtv.ru ^ permalink raw reply [flat|nested] 19+ messages in thread
* RE: [Caml-list] Val_int vs caml_copy_nativeint 2011-08-09 10:07 ` malc @ 2011-08-09 10:43 ` David Allsopp 0 siblings, 0 replies; 19+ messages in thread From: David Allsopp @ 2011-08-09 10:43 UTC (permalink / raw) To: malc; +Cc: caml-list malc wrote: > On Tue, 9 Aug 2011, David Allsopp wrote: > > > Erik de Castro Lopo wrote: > > > Xavier Leroy wrote: > > > > > > > On 08/08/2011 10:03 AM, Guillaume Yziquel wrote: > > > > > > > > > Then I do not see anything wrong if the code snippet you sent. > > > > > However, when you change Val_int to caml_copy_nativeint, the > > > > > layout of the tuple is different. [...] So if you keep the same > > > > > OCaml code when reading the result value, it's no surprise that > > > > > the pointer is shown in place of the integer you expected. > > > > > > > > This is good advice indeed: make sure your Caml type declaration > > > > matches the data representation that your Caml/C stub implements... > > > > > > > > > /* Package up the result as a tuple. */ > > > > > v_response = caml_alloc_tuple (3) ; > > > > > Store_field (v_response, 0, Val_int (width)) ; > > > > > Store_field (v_response, 1, Val_int (height)) ; > > > > > Store_field (v_response, 2, caml_copy_string (code)) ; > > > > > CAMLreturn (v_response) ; > > > > > > > > Additionally, do make sure that "v_response" is registered with > > > > the GC (declared with one of the CAMLlocal macros). > > > > > > This is strange, it wasn't declared with a CAMLlocal macro and it > > > was working, but if I do declare it with one the program segfaults > > > during garbage collection (caml_oldify_local_roots). > > > > If you altered this but left the program exactly the same then you > violated rule 1 in 18.5.1 of the manual: CAMLparamn must come first. The > result is predictable - you attempt to allocate a local variable before > the local root is properly initialised... > > > > > That said, in your specific example, my understanding is that it > > should be OK not using CAMLlocal because you return v_response with > > CAMLreturn before the GC could be triggered (no allocations or > > callbacks between caml_alloc_tuple and CAMLreturn). > > I'm puzzled by this, caml_copy_string does allocation.. Oops :$ So it does... ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [Caml-list] Val_int vs caml_copy_nativeint 2011-08-09 1:33 ` Erik de Castro Lopo 2011-08-09 1:40 ` Romain Beauxis 2011-08-09 8:44 ` David Allsopp @ 2011-08-09 22:53 ` Erik de Castro Lopo 2011-08-10 6:43 ` Gabriel Scherer 2 siblings, 1 reply; 19+ messages in thread From: Erik de Castro Lopo @ 2011-08-09 22:53 UTC (permalink / raw) To: caml-list Erik de Castro Lopo wrote: > This is strange, it wasn't declared with a CAMLlocal macro and it > was working, but if I do declare it with one the program segfaults > during garbage collection (caml_oldify_local_roots). Ok, with the help of someone off list I've sorted this out to my satisfaction. Things learned: a) In the C stub function, the call to CAMLParamN must be the first thing in the function, followed by any CAMLlocalN declarations. These should even occur before before any declarations of local C variables. b) caml_copy_nativeint creates a boxed native int (either Int32.t or Int64.t) not an unboxed Ocaml int. To create an unboxed Ocaml int, Val_int() is the correct macro. Thanks to all that responded. Erik -- ---------------------------------------------------------------------- Erik de Castro Lopo http://www.mega-nerd.com/ ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [Caml-list] Val_int vs caml_copy_nativeint 2011-08-09 22:53 ` Erik de Castro Lopo @ 2011-08-10 6:43 ` Gabriel Scherer 0 siblings, 0 replies; 19+ messages in thread From: Gabriel Scherer @ 2011-08-10 6:43 UTC (permalink / raw) To: caml-list [-- Attachment #1: Type: text/plain, Size: 448 bytes --] Erik de Castro Lopo wrote: > b) caml_copy_nativeint creates a boxed native int (either Int32.t > or Int64.t) not an unboxed Ocaml int. To create an unboxed > Ocaml int, Val_int() is the correct macro. > caml_copy_nativeint returns a element of the OCaml type 'nativeint': http://caml.inria.fr/pub/docs/manual-ocaml/libref/Nativeint.html The caml_copy_* documentation: http://caml.inria.fr/pub/docs/manual-ocaml/manual032.html#htoc238 [-- Attachment #2: Type: text/html, Size: 810 bytes --] ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [Caml-list] Val_int vs caml_copy_nativeint 2011-08-08 3:15 [Caml-list] Val_int vs caml_copy_nativeint Erik de Castro Lopo 2011-08-08 3:48 ` Romain Beauxis 2011-08-08 3:53 ` Guillaume Yziquel @ 2011-08-08 5:20 ` malc 2011-08-08 6:01 ` Guillaume Yziquel 2 siblings, 1 reply; 19+ messages in thread From: malc @ 2011-08-08 5:20 UTC (permalink / raw) To: caml-list On Mon, 8 Aug 2011, Erik de Castro Lopo wrote: > Hi all, > > I'm writing a C stub function to allow the calling of a C library > function from ocaml. The return from the stub is a tuple and I'm > doing this: > > /* Package up the result as a tuple. */ > v_response = caml_alloc_tuple (3) ; > > Store_field (v_response, 0, Val_int (width)) ; > Store_field (v_response, 1, Val_int (height)) ; > Store_field (v_response, 2, caml_copy_string (code)) ; > > CAMLreturn (v_response) ; > > The above works now, but didn't work when I was using > caml_copy_nativeint() instead of Val_int() and I'd like to know > why. I found it especially confusing because caml_copy_string() > worked and was obvioulsy the right thing to do. 18.5.2 Rule 5 After a structured block (a block with tag less than No_scan_tag) is allocated with the low-level functions, all fields of this block must be filled with well-formed values before the next allocation operation. If the block has been allocated with caml_alloc_small, filling is performed by direct assignment to the fields of the block: Field(v, n) = vn; ... I'd say rule 5 has been violated here. Why it "works" one way and doesn't work the other is the question to Damien i suppose. -- mailto:av1474@comtv.ru ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [Caml-list] Val_int vs caml_copy_nativeint 2011-08-08 5:20 ` malc @ 2011-08-08 6:01 ` Guillaume Yziquel 2011-08-08 6:22 ` malc 0 siblings, 1 reply; 19+ messages in thread From: Guillaume Yziquel @ 2011-08-08 6:01 UTC (permalink / raw) To: malc; +Cc: caml-list Le Monday 08 Aug 2011 à 09:20:17 (+0400), malc a écrit : > On Mon, 8 Aug 2011, Erik de Castro Lopo wrote: > > > Hi all, > > > > I'm writing a C stub function to allow the calling of a C library > > function from ocaml. The return from the stub is a tuple and I'm > > doing this: > > > > /* Package up the result as a tuple. */ > > v_response = caml_alloc_tuple (3) ; > > > > Store_field (v_response, 0, Val_int (width)) ; > > Store_field (v_response, 1, Val_int (height)) ; > > Store_field (v_response, 2, caml_copy_string (code)) ; > > > > CAMLreturn (v_response) ; > > > > The above works now, but didn't work when I was using > > caml_copy_nativeint() instead of Val_int() and I'd like to know > > why. I found it especially confusing because caml_copy_string() > > worked and was obvioulsy the right thing to do. > > 18.5.2 > > Rule 5 > > After a structured block (a block with tag less than No_scan_tag) > is allocated with the low-level functions, all fields of this block must > be filled with well-formed values before the next allocation operation. If > the block has been allocated with caml_alloc_small, filling is performed > by direct assignment to the fields of the block: > Field(v, n) = vn; > ... > > I'd say rule 5 has been violated here. No. caml_alloc_tuple is considered to be part of the simplified interface, not part of the low-level interface. Rule 5 shouldn't apply in this case. One of the reasons for rule 5 is that the contents of the allocated block may not satisfy GC constraints. So you should not allocate with the blocks item pointing to inconsistent garbage as the GC may the run over them. 18.4.4 caml_alloc(n, t) returns a fresh block of size n with tag t. If t is less than No_scan_tag, then the fields of the block are initialized with a valid value in order to satisfy the GC constraints. In caml_alloc function in alloc.c: if (tag < No_scan_tag){ for (i = 0; i < wosize; i++) Field (result, i) = 0; } and caml_alloc_tuple is roughly caml_alloc (in alloc.c) so definitely part of the simplified interface: CAMLexport value caml_alloc_tuple(mlsize_t n) { return caml_alloc(n, 0); } -- Guillaume Yziquel ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [Caml-list] Val_int vs caml_copy_nativeint 2011-08-08 6:01 ` Guillaume Yziquel @ 2011-08-08 6:22 ` malc 0 siblings, 0 replies; 19+ messages in thread From: malc @ 2011-08-08 6:22 UTC (permalink / raw) To: Guillaume Yziquel; +Cc: caml-list On Mon, 8 Aug 2011, Guillaume Yziquel wrote: > Le Monday 08 Aug 2011 ? 09:20:17 (+0400), malc a ?crit : > > On Mon, 8 Aug 2011, Erik de Castro Lopo wrote: > > > > > Hi all, > > > > > > I'm writing a C stub function to allow the calling of a C library > > > function from ocaml. The return from the stub is a tuple and I'm > > > doing this: > > > > > > /* Package up the result as a tuple. */ > > > v_response = caml_alloc_tuple (3) ; > > > > > > Store_field (v_response, 0, Val_int (width)) ; > > > Store_field (v_response, 1, Val_int (height)) ; > > > Store_field (v_response, 2, caml_copy_string (code)) ; > > > > > > CAMLreturn (v_response) ; > > > > > > The above works now, but didn't work when I was using > > > caml_copy_nativeint() instead of Val_int() and I'd like to know > > > why. I found it especially confusing because caml_copy_string() > > > worked and was obvioulsy the right thing to do. > > > > 18.5.2 > > > > Rule 5 > > > > After a structured block (a block with tag less than No_scan_tag) > > is allocated with the low-level functions, all fields of this block must > > be filled with well-formed values before the next allocation operation. If > > the block has been allocated with caml_alloc_small, filling is performed > > by direct assignment to the fields of the block: > > Field(v, n) = vn; > > ... > > > > I'd say rule 5 has been violated here. > > No. caml_alloc_tuple is considered to be part of the simplified > interface, not part of the low-level interface. Rule 5 shouldn't apply > in this case. > > One of the reasons for rule 5 is that the contents of the allocated > block may not satisfy GC constraints. So you should not allocate with > the blocks item pointing to inconsistent garbage as the GC may the run > over them. > > 18.4.4 > > caml_alloc(n, t) returns a fresh block of size n with tag t. > If t is less than No_scan_tag, then the fields of the block > are initialized with a valid value in order to satisfy the > GC constraints. > > In caml_alloc function in alloc.c: > > if (tag < No_scan_tag){ > for (i = 0; i < wosize; i++) Field (result, i) = 0; > } > > and caml_alloc_tuple is roughly caml_alloc (in alloc.c) so definitely > part of the simplified interface: > > CAMLexport value caml_alloc_tuple(mlsize_t n) > { > return caml_alloc(n, 0); > } > > I stand corrected. -- mailto:av1474@comtv.ru ^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2011-08-10 6:43 UTC | newest] Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2011-08-08 3:15 [Caml-list] Val_int vs caml_copy_nativeint Erik de Castro Lopo 2011-08-08 3:48 ` Romain Beauxis 2011-08-08 3:59 ` Guillaume Yziquel 2011-08-08 7:49 ` Erik de Castro Lopo 2011-08-08 3:53 ` Guillaume Yziquel 2011-08-08 7:46 ` Erik de Castro Lopo 2011-08-08 8:03 ` Guillaume Yziquel 2011-08-08 9:17 ` Mathias Kende 2011-08-08 17:24 ` Xavier Leroy 2011-08-09 1:33 ` Erik de Castro Lopo 2011-08-09 1:40 ` Romain Beauxis 2011-08-09 8:44 ` David Allsopp 2011-08-09 10:07 ` malc 2011-08-09 10:43 ` David Allsopp 2011-08-09 22:53 ` Erik de Castro Lopo 2011-08-10 6:43 ` Gabriel Scherer 2011-08-08 5:20 ` malc 2011-08-08 6:01 ` Guillaume Yziquel 2011-08-08 6:22 ` malc
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox