* [Caml-list] C interop: Return values in parameters @ 2012-12-30 13:08 Marek Kubica 2012-12-30 14:01 ` Török Edwin 0 siblings, 1 reply; 5+ messages in thread From: Marek Kubica @ 2012-12-30 13:08 UTC (permalink / raw) To: caml-list Hi, I am trying to wrap a C library in OCaml but I don't know how to do this particular thing: I have a library that looks roughly like this: int function(void** ptr); So I get an int as return value to show whether the function succeeded and it *sets* the ptr. void* ptr; function(&ptr); // ptr is different now How can I wrap such a function in OCaml? When I call my OCaml wrapper let retval = function ptr in ... the pointer does not get updated. Is there a function in the C API to force OCaml to update the values? regards, Marek ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Caml-list] C interop: Return values in parameters 2012-12-30 13:08 [Caml-list] C interop: Return values in parameters Marek Kubica @ 2012-12-30 14:01 ` Török Edwin 2012-12-30 14:19 ` Marek Kubica 0 siblings, 1 reply; 5+ messages in thread From: Török Edwin @ 2012-12-30 14:01 UTC (permalink / raw) To: caml-list On 12/30/2012 03:08 PM, Marek Kubica wrote: > Hi, > > I am trying to wrap a C library in OCaml but I don't know how to do > this particular thing: > > I have a library that looks roughly like this: > > int function(void** ptr); > > So I get an int as return value to show whether the function succeeded > and it *sets* the ptr. > > void* ptr; > function(&ptr); > // ptr is different now > > How can I wrap such a function in OCaml? > When I call my OCaml wrapper > > let retval = function ptr in > ... > > the pointer does not get updated. Is there a function in the C API to > force OCaml to update the values? Use a '<yourtype> ref' for the parameter (or a record with a mutable field) on the OCaml side, and you can update the field on the C side then. Or if your C type is not actually void*, and your C function doesn't have side-effects (besides updating ptr) you can also make the OCaml function return the actual value, and raise an exception if the function failed. Best regards, --Edwin ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Caml-list] C interop: Return values in parameters 2012-12-30 14:01 ` Török Edwin @ 2012-12-30 14:19 ` Marek Kubica 2012-12-30 14:36 ` Gabriel Scherer 0 siblings, 1 reply; 5+ messages in thread From: Marek Kubica @ 2012-12-30 14:19 UTC (permalink / raw) To: Török Edwin; +Cc: caml-list Hi, Thanks for your help. On Sun, 30 Dec 2012 16:01:06 +0200 Török Edwin <edwin+ml-ocaml@etorok.net> wrote: > Use a '<yourtype> ref' for the parameter (or a record with a mutable > field) on the OCaml side, and you can update the field on the C side > then. I was thinking about the same thing and checked http://www.linux-nantes.org/~fmonnier/ocaml/ocaml-wrapping-c.php and http://caml.inria.fr/pub/docs/manual-ocaml-4.00/manual033.html and couldn't find how to modify a ref value from C. My code looks like this: CAMLprim value ost_read_next_header(value archive, value entry) { struct archive* handle = (struct archive*)archive; struct archive_entry* ent = (struct archive_entry*)entry; printf("ent: %p\n", ent); int retval = archive_read_next_header(handle, &ent); // ent changed printf("ent: %p\n", ent); entry = (value)ent; return Val_int(retval); } And the second parameter is defined as "entry ref", yet when I look at the resulting value from OCaml, the ref's value did not change: let entry = ref (Archive.entry_new ()) in Archive.print_pointer !entry; ... ignore (Archive.read_next_header handle entry); Archive.print_pointer !entry; It still points to the same value that my Archive.entry_new returned. > Or if your C type is not actually void*, and your C function doesn't > have side-effects (besides updating ptr) you can also make the OCaml > function return the actual value, and raise an exception if the > function failed. I thought about this, but I have a number of these functions and some have more than one return parameter, so I'd need to return a tuple at least. I plan to make this wrapper as close to C and low-level, so I can write a proper high-level wrapper on top. If the ref-appoach does not get me anywhere, I might still do this. regards, Marek ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Caml-list] C interop: Return values in parameters 2012-12-30 14:19 ` Marek Kubica @ 2012-12-30 14:36 ` Gabriel Scherer 2012-12-31 1:48 ` Marek Kubica 0 siblings, 1 reply; 5+ messages in thread From: Gabriel Scherer @ 2012-12-30 14:36 UTC (permalink / raw) To: Marek Kubica; +Cc: Török Edwin, caml-list References are a derived concept defined as: type 'a ref = { mutable contents : 'a } You can update them from the C side just as you would handle a polymorphic record, with Field and Store_field. In the code you show, the OCaml value corresponding to the pointer is exactly the pointer, hidden as a 'value' type. This is correct as OCaml detects out-of-(OCaml)-heap pointer. However, if you used a custom block instead ( http://caml.inria.fr/pub/docs/manual-ocaml-4.00/manual033.html#toc150 ), OCaml would do the boxing for you: Data_custom_val(v) already returns a pointer than can be dereferenced or mutated. I think you have a choice between using references explicitly for those functions of the API that mutate input references, or uniformly representing this type of data as a custom block. The latter option may be valuable if you have uses for the other features of custom blocks, eg. the user-defined comparison and finalization operations, and probably not worth the trouble otherwise. Finally, explicitly using references to signal mutability in some part of your API is probably clearer and a better design. On Sun, Dec 30, 2012 at 3:19 PM, Marek Kubica <marek@xivilization.net> wrote: > Hi, > > Thanks for your help. > > On Sun, 30 Dec 2012 16:01:06 +0200 > Török Edwin <edwin+ml-ocaml@etorok.net> wrote: > >> Use a '<yourtype> ref' for the parameter (or a record with a mutable >> field) on the OCaml side, and you can update the field on the C side >> then. > > I was thinking about the same thing and checked > > http://www.linux-nantes.org/~fmonnier/ocaml/ocaml-wrapping-c.php > and > http://caml.inria.fr/pub/docs/manual-ocaml-4.00/manual033.html > > and couldn't find how to modify a ref value from C. > > My code looks like this: > > CAMLprim value ost_read_next_header(value archive, value entry) > { > struct archive* handle = (struct archive*)archive; > struct archive_entry* ent = (struct archive_entry*)entry; > printf("ent: %p\n", ent); > int retval = archive_read_next_header(handle, &ent); > // ent changed > printf("ent: %p\n", ent); > entry = (value)ent; > return Val_int(retval); > } > > And the second parameter is defined as "entry ref", yet when I look at > the resulting value from OCaml, the ref's value did not change: > > let entry = ref (Archive.entry_new ()) in > Archive.print_pointer !entry; > ... > ignore (Archive.read_next_header handle entry); > Archive.print_pointer !entry; > > It still points to the same value that my Archive.entry_new returned. > >> Or if your C type is not actually void*, and your C function doesn't >> have side-effects (besides updating ptr) you can also make the OCaml >> function return the actual value, and raise an exception if the >> function failed. > > I thought about this, but I have a number of these functions and some > have more than one return parameter, so I'd need to return a tuple at > least. I plan to make this wrapper as close to C and low-level, so I > can write a proper high-level wrapper on top. > > If the ref-appoach does not get me anywhere, I might still do this. > > regards, > Marek > > -- > Caml-list mailing list. Subscription management and archives: > https://sympa.inria.fr/sympa/arc/caml-list > Beginner's list: http://groups.yahoo.com/group/ocaml_beginners > Bug reports: http://caml.inria.fr/bin/caml-bugs ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Caml-list] C interop: Return values in parameters 2012-12-30 14:36 ` Gabriel Scherer @ 2012-12-31 1:48 ` Marek Kubica 0 siblings, 0 replies; 5+ messages in thread From: Marek Kubica @ 2012-12-31 1:48 UTC (permalink / raw) To: Gabriel Scherer; +Cc: Török Edwin, caml-list Hello Gabriel, Thanks for your mail. I read it multiple times to grasp all information. On Sun, 30 Dec 2012 15:36:16 +0100 Gabriel Scherer <gabriel.scherer@gmail.com> wrote: > References are a derived concept defined as: > > type 'a ref = { mutable contents : 'a } > > You can update them from the C side just as you would handle a > polymorphic record, with Field and Store_field. Turns out Field is also valid as L-Value so I can even use Field(x,0) to set. Fun :) With this solution, I managed to fix my immediate problem. > In the code you show, the OCaml value corresponding to the pointer is > exactly the pointer, hidden as a 'value' type. This is correct as > OCaml detects out-of-(OCaml)-heap pointer. However, if you used a > custom block instead ( > http://caml.inria.fr/pub/docs/manual-ocaml-4.00/manual033.html#toc150 > ), OCaml would do the boxing for you: Data_custom_val(v) already > returns a pointer than can be dereferenced or mutated. I read this as well as <http://www.linux-nantes.org/~fmonnier/ocaml/ocaml-wrapping-c.php#ref_custom> and while I seem to understand how it works, I don't get how to modify it. Do I understand right that I'd just create such a custom block and just wrap the pointer into it? I'll probably implement it tomorrow and see how I like it. > I think you have a choice between using references explicitly for > those functions of the API that mutate input references, or uniformly > representing this type of data as a custom block. The latter option > may be valuable if you have uses for the other features of custom > blocks, eg. the user-defined comparison and finalization operations, > and probably not worth the trouble otherwise. Finally, explicitly > using references to signal mutability in some part of your API is > probably clearer and a better design. Well, except for finalization I don't really have much use for the operations that custom blocks expose, but the finalization might be worth the work. Thanks again, I really felt productive today, by getting things done. regards, Marek ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2012-12-31 1:48 UTC | newest] Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2012-12-30 13:08 [Caml-list] C interop: Return values in parameters Marek Kubica 2012-12-30 14:01 ` Török Edwin 2012-12-30 14:19 ` Marek Kubica 2012-12-30 14:36 ` Gabriel Scherer 2012-12-31 1:48 ` Marek Kubica
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).