Leonidas changed the topic of #ocaml to: Discussion about the OCaml programming language | http://www.ocaml.org | OCaml 5.1.1 released: https://ocaml.org/releases/5.1.1 | Try OCaml in your browser: https://try.ocamlpro.com | Public channel logs at https://libera.irclog.whitequark.org/ocaml/
<discocaml> <leostera> hi, i'm trying to pass an ocaml value into some C code, and want to preserve and return that ocaml value later on.
<discocaml> <leostera>
<discocaml> <leostera> currently I am trying to decipher how to use `caml_register_generational_global_root`, but roughly what I have is this:
<discocaml> <leostera>
<discocaml> <leostera> ```c
<discocaml> <leostera> value* ocaml_value = malloc (sizeof (value*));
<discocaml> <leostera> *ocaml_value = Field(v_event, 0); // the value is in a record
<discocaml> <leostera> caml_register_generational_global_root(ocaml_value);
<discocaml> <leostera> // save `ocaml_value` for later
<discocaml> <leostera> ```
<discocaml> <leostera>
<discocaml> <leostera> and then eventually I get that `ocaml_value` and i use `Store_field` to reconstruct a record that will be a response.
<discocaml> <leostera> i'm reading through the C FFI docs, and i've been searching github for calls to `caml_register_generational_global_root` , but I'm not sure that what I have is working 🤔
<discocaml> <leostera> what's the right way of safely storing an OCaml value pointer into a C struct?
czy has joined #ocaml
alexherbo2 has quit [Ping timeout: 250 seconds]
Tuplanolla has quit [Quit: Leaving.]
average has quit [Quit: Connection closed for inactivity]
pi3ce has joined #ocaml
rgrinberg has quit [Quit: My Mac has gone to sleep. ZZZzzz…]
meritamen has joined #ocaml
meritamen has quit [Quit: My MacBook has gone to sleep. ZZZzzz…]
jmcantrell has joined #ocaml
rgrinberg has joined #ocaml
rgrinberg has quit [Quit: My Mac has gone to sleep. ZZZzzz…]
omegatron has quit [Quit: Power is a curious thing. It can be contained, hidden, locked away, and yet it always breaks free.]
justache- is now known as justache
meritamen has joined #ocaml
jmcantrell has quit [Quit: WeeChat 4.1.2]
rgrinberg has joined #ocaml
jmcantrell has joined #ocaml
rgrinberg has quit [Ping timeout: 256 seconds]
trev has joined #ocaml
azimut has quit [Remote host closed the connection]
azimut has joined #ocaml
azimut has quit [Remote host closed the connection]
azimut has joined #ocaml
rgrinberg has joined #ocaml
rgrinberg has quit [Ping timeout: 256 seconds]
average has joined #ocaml
azimut has quit [Ping timeout: 240 seconds]
Serpent7776 has joined #ocaml
wingsorc has quit [Quit: Leaving]
bartholin has joined #ocaml
average has quit [Quit: Connection closed for inactivity]
neiluj has joined #ocaml
waleee has quit [Ping timeout: 252 seconds]
alexherbo2 has joined #ocaml
<discocaml> <octachron> You should not register a value allocated with malloc.
<discocaml> <octachron> Registering a root informs the GC that there is an owner for a part of memory managed by the GC.
bartholin has quit [Quit: Leaving]
romildo has joined #ocaml
<discocaml> <leostera> gotcha
<discocaml> <leostera> i'm literally mimicking code i'm seeing in hhvm, flow, clangml, and other github projects
meritamen has quit [Quit: My MacBook has gone to sleep. ZZZzzz…]
neiluj has quit [Quit: neiluj]
neiluj has joined #ocaml
<neiluj> Hi! with Qcheck, how do I make sure that the assume(...) that fail are not counted as passing tests?
<neiluj> or that it retries and the number of tests specified should correspond to the number of failing+passing tests
<neiluj> not counting skipped tests
meritamen has joined #ocaml
<discocaml> <leostera> i'm confused, this is how i saw a lot of folks doing it on github projects, can you show me what the right way of doing this is?
romildo has quit [Quit: Leaving]
<discocaml> <leostera> should I be registering a global root for the address of the field itself?
<discocaml> <leostera>
<discocaml> <leostera> ```c
<discocaml> <leostera> value* ocaml_value = &Field(input, 0);
<discocaml> <leostera> caml_register_generational_global_root(ocaml_value);
<discocaml> <leostera> ```
<Armael> what you register as a root should be the address of a C location in memory, that stores an ocaml value
<Armael> eg if myglob is a C global variable: value myglob = Val_unit; caml_register_generational_global_root(&myglob);
<discocaml> <leostera> so i should be able to do: `caml_register_generational_global_root(&Field(input, 0));` ?
<Armael> or, instead of a C global, with a malloc'd location: value* foo = malloc(sizeof(value)); *foo = Val_unit; caml_register_etc(foo);
<Armael> no that'd register a location in ocaml memory
<Armael> what you register as a root needs to be a C-managed bit of memory that you provide
<Armael> &Field(...) is an address somewhere in ocaml-managed memory, you can't use that
<Armael> (sorry, I agree it's confusing, it would be clearer with a drawing maybe…)
<discocaml> <leostera> i'm not using a c global btw
<discocaml> <leostera> this is what i'm doing 🤔
<discocaml> <leostera> ok so to summarize `caml_register_generational_global_root` should receive a pointer to C-managed memory?
<discocaml> <leostera> how do i tell the GC not to gc the ocaml value tho? 🤔
romildo has joined #ocaml
romildo has quit [Quit: Leaving]
<discocaml> <0aty> Isn't the point simply that C-managed memory that can hold pointers to OCaml-managed memory needs to count as a GC root? I might just be stating the obvious here but I don't see how it matters if its /technically/ a C global
meritamen has quit [Remote host closed the connection]
olle has joined #ocaml
fweht has joined #ocaml
<Armael> the C global was just an example, it works with malloc'd memory as well
<Armael> caml_register_generational_global_root should receive a pointer to C-managed memory that stores an ocaml value
<Armael> then the GC will not collect the value contained there
<Armael> (the GC will also *update* the contents of the rooted C-managed memory whenever the ocaml block stored there moves around in memory...)
<discocaml> <0aty> Even if it isnt malloced, if you have an ocaml-managed piece of memory, and you want to reference it from C, even if the reference is on the stack, you should still register it as a gc root though, right? because otherwise the Gc will clean it up under your feet
<discocaml> <0aty> and if its on the stack, obviously deregister before the end of the stack frame so the Gc doesnt do something with a random reference into the stack
<Armael> yes, whenever you want to reference an ocaml value from C you need to root it
<Armael> (except in specific cases where you know you are not calling the GC (not allocating etc))
a51 has quit [Quit: WeeChat 4.1.2]
azimut has joined #ocaml
azimut has quit [Remote host closed the connection]
azimut has joined #ocaml
rgrinberg has joined #ocaml
a51 has joined #ocaml
rgrinberg has quit [Quit: My Mac has gone to sleep. ZZZzzz…]
rgrinberg has joined #ocaml
Inline has joined #ocaml
alexherbo2 has quit [Remote host closed the connection]
alexherbo2 has joined #ocaml
rgrinberg has quit [Quit: My Mac has gone to sleep. ZZZzzz…]
rgrinberg has joined #ocaml
average has joined #ocaml
oriba has joined #ocaml
Serpent7776 has quit [Ping timeout: 276 seconds]
rgrinberg has quit [Quit: My Mac has gone to sleep. ZZZzzz…]
olle has quit [Ping timeout: 260 seconds]
rgrinberg has joined #ocaml
alexherbo2 has quit [Remote host closed the connection]
a51 has quit [Quit: WeeChat 4.1.2]
rgrinberg has quit [Quit: My Mac has gone to sleep. ZZZzzz…]
neiluj has quit [Quit: neiluj]
bartholin has joined #ocaml
a51 has joined #ocaml
omegatron has joined #ocaml
waleee has joined #ocaml
fweht has quit [Quit: Connection closed for inactivity]
dylanj has joined #ocaml
<discocaml> <octachron> @leostera , sorry for my erroneous answer (it is far better to trust Armael than me on those matters).
<discocaml> <.armael.> At some point it’d be nice to extend/revamp the FFI page of the ocaml manual, perhaps with more drawings…
jmcantrell has quit [Quit: WeeChat 4.1.2]
trev has quit [Quit: trev]
jmcantrell has joined #ocaml
<discocaml> <leostera> no worries 🙏🏼
jmcantrell has quit [Quit: WeeChat 4.1.2]
neiluj has joined #ocaml
jmcantrell has joined #ocaml
jmcantrell has quit [Quit: WeeChat 4.1.2]
Tuplanolla has joined #ocaml
jmcantrell has joined #ocaml
neiluj has quit [Ping timeout: 256 seconds]
bartholin has quit [Quit: Leaving]
<discocaml> <Ada> speaking of ffi, `CArray.from_ptr pointer len |> CArray.to_list |> List.to_seq |> String.of_seq`
<discocaml> <Ada> is there a better way to do this
<discocaml> <._null._> Probably better not to go through a list at first
<companion_cube> :/
<discocaml> <Ada> yeah, thats what is really annoying me
<companion_cube> A function with a loop, if there's a way to get individual CArray items
<discocaml> <Kali> could you not write your own conversion function?
<discocaml> <Kali> i know it's a little annoying but it shouldn't be more than a few lines
<discocaml> <Ada> yeah, i was just checking before i wrote a manual loop that i'm not missing something super simple
<discocaml> <Ada> ctypes has a built in string conversion system, but it only works on null terminated strings and this is binary data
<discocaml> <._null._> `CArray.from_ptr pointer len |> fun a -> String.init len (CArray.get a)` ?
<Armael> (personally now that I learned to use the "standard" C FFI I can't be bothered to use ctypes anymore...)
<discocaml> <Ada> oh cool, somehow i didnt know about String.init
<discocaml> <Ada> Armael: i don't know C very well and the dune ctypes generation is really appealing
<discocaml> <Ada> the actual ctypes api is quite eh
<Armael> ye to be fair when I was using ctypes there was no dune support and the build story was very annoying
<Armael> tho with the normal FFI building is also fairly easy
<Armael> I guess there's a steeper learning curve with the normal FFI, but I feel that I understand better what I'm doing
<Armael> with ctypes I always fear that I'll get stuck in some cases where I don't know how to express what I need using the ctypes DSL
<discocaml> <Ada> if i was gonna port something big i would definitely learn the normal ffi
<Armael> makes sense, for smaller bindings ctypes is very convenient
<discocaml> <Ada> thank u sm
rgrinberg has joined #ocaml
rgrinberg has quit [Client Quit]
<companion_cube> Armael: agreed, especially given it has lower overhead afaik
oriba has quit [Quit: https://quassel-irc.org - Chat comfortably. Anywhere.]
<discocaml> <Ada> i don’t think ctypes_stubs has any overhead for simple stuff
<discocaml> <Ada> but even with dune passing functions into c use ctypes_foreign