caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* problem creating .cma library
@ 2009-12-30 17:48 rouanvd
  2009-12-30 23:30 ` [Caml-list] " Guillaume Yziquel
  0 siblings, 1 reply; 21+ messages in thread
From: rouanvd @ 2009-12-30 17:48 UTC (permalink / raw)
  To: caml-list

Hi everyone.

I am trying to create an ocaml binding to a C library as a test to see if I
can get the ocaml FFI to work.  This is just experimental so I can gain
experience to later write bindings to real C libraries for ocaml.

I am using ocaml 3.11.0 with the MingW toolchain on windows (vista).

I first create a dll called libmylib.dll which contains 1 method called:
void my_print(char* str);

The DLL is created with the MingW toolchan and works correctly as I create
a test C application that links against libmylib.dll and executes correctly.

the library is created with the following gcc commands:

 gcc -fPIC -Wall -c mylib.c
 gcc -shared -o libmylib.dll mylib.o


Now I create the mylib_stub.c file which contains the marshalling code
between the libmylib.dll library and ocaml.  This file contains the
following C code:

=======================================
#include <stdio.h>
#include <caml/mlvalues.h>
#include "../mylib/mylib.h"

CAMLprim value
my_print_stub(value v) {
    char* str = (char*)String_val( v );
    my_print( str );

    return Val_unit;
}
=======================================

I then create the mylib.ml file which contains the following ocaml code:

=======================================
external my_print : string -> unit = "my_print_stub"
=======================================

I then use the following commands to create a .cma file that is supposed
to expose the my_print function in the libmylib.dll to ocaml:

 ocamlc -c mylib.ml
 ocamlc -c mylib_stub.c

 ocamlmklib -o _stubs mylib_stub.o -L/mingw/lib -L. -lmylib

 ocamlc -a -o mylib.cma mylib.cmo -dllib -l_stubs -ccopt -L. -cclib -lmylib


Up to this point, there are no errors.

When I finaly build the test ocaml app which is supposed to use the
mylib.cma library, ocamlc tells me:

 "Unbound module Mylib"

The command used to compile the test app is

 ocamlc -verbose mylib.cma -c Main.ml

The Main.ml file contains the following code:

=======================================
open Mylib

let main () =
    my_print "my_print = ok"


main ()
=======================================

Is there a way to verify that the .cma library was created correctly?

I had to install flexlink for ocaml to get the dll linking to work on
windows.

Kind regards
Rouan.


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

* Re: [Caml-list] problem creating .cma library
  2009-12-30 17:48 problem creating .cma library rouanvd
@ 2009-12-30 23:30 ` Guillaume Yziquel
  2010-01-05 13:04   ` Damien Doligez
  0 siblings, 1 reply; 21+ messages in thread
From: Guillaume Yziquel @ 2009-12-30 23:30 UTC (permalink / raw)
  To: rouanvd; +Cc: caml-list

rouanvd@softwarerealisations.com a écrit :
> Hi everyone.

Hi.

> I am using ocaml 3.11.0 with the MingW toolchain on windows (vista).

Cannot help you much there.

> Now I create the mylib_stub.c file which contains the marshalling code
> between the libmylib.dll library and ocaml.  This file contains the
> following C code:
> 
> =======================================
> #include <stdio.h>
> #include <caml/mlvalues.h>
> #include "../mylib/mylib.h"
> 
> CAMLprim value
> my_print_stub(value v) {

       CAMLparam1(v);  /* is missing here, for garbage
                          collection purposes. */

>     char* str = (char*)String_val( v );

       /* You do not need the right-hand side (char*) casting. */

>     my_print( str );
> 
>     return Val_unit;
> }

> When I finaly build the test ocaml app which is supposed to use the
> mylib.cma library, ocamlc tells me:
> 
>  "Unbound module Mylib"

Firs of all, mylib.cma is simply an archive of OCaml modules. It may 
contain multiple modules, and might not contain a module called Mylib.

You have to ensure that mylib.cmo is included in mylib.cma. Moreover, 
when you create mylib.cma, you also need a compiled interface, i.e. a 
mylib.cmi file. It's an interface for mylib.cmo. Without it, there's no 
description of module Mylib in mylib.cma.

> The command used to compile the test app is
> 
>  ocamlc -verbose mylib.cma -c Main.ml

You've got something fundamentally wrong here:

Out of main.ml (lower case for the the first letter), you first create a 
main.cmo file. And also a main.mli file with ocamlc -i. You compile the 
main.mli file to main.cmi. Then you create the mylib.cma archive from 
main.cmo and main.cmi.

And mylib.cma will contain the module Main. Not the module Mylib.

> The Main.ml file contains the following code:
> 
> =======================================
> open Mylib
> 
> let main () =
>     my_print "my_print = ok"
> 
> 
> main ()
> =======================================

Here, you're declaring the submodule Mylib of the module Main. Also 
known as Main.Mylib. Not as Mylib.

> Is there a way to verify that the .cma library was created correctly?

There are some tools, such as ocamldumpobj and ocamlobjinfo. Forgot 
which one applies to .cmas.

> I had to install flexlink for ocaml to get the dll linking to work on
> windows.

Can't help you here.

> Kind regards
> Rouan.

All the best,

-- 
      Guillaume Yziquel
http://yziquel.homelinux.org/


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

* Re: [Caml-list] problem creating .cma library
  2009-12-30 23:30 ` [Caml-list] " Guillaume Yziquel
@ 2010-01-05 13:04   ` Damien Doligez
  2010-01-08 23:38     ` Guillaume Yziquel
  0 siblings, 1 reply; 21+ messages in thread
From: Damien Doligez @ 2010-01-05 13:04 UTC (permalink / raw)
  To: caml-list List


On 2009-12-31, at 00:30, Guillaume Yziquel wrote:

>> #include <stdio.h>
>> #include <caml/mlvalues.h>
>> #include "../mylib/mylib.h"
>> CAMLprim value
>> my_print_stub(value v) {
>
>      CAMLparam1(v);  /* is missing here, for garbage
>                         collection purposes. */
>
>>    char* str = (char*)String_val( v );
>
>      /* You do not need the right-hand side (char*) casting. */
>
>>    my_print( str );
>>    return Val_unit;
>> }

If you use CAMLparam1, you must use CAMLreturn instead of return.

-- Damien


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

* Re: [Caml-list] problem creating .cma library
  2010-01-05 13:04   ` Damien Doligez
@ 2010-01-08 23:38     ` Guillaume Yziquel
  2010-01-08 23:54       ` Basile STARYNKEVITCH
  0 siblings, 1 reply; 21+ messages in thread
From: Guillaume Yziquel @ 2010-01-08 23:38 UTC (permalink / raw)
  To: Damien Doligez; +Cc: caml-list List

Damien Doligez a écrit :
> 
> On 2009-12-31, at 00:30, Guillaume Yziquel wrote:
> 
>>> #include <stdio.h>
>>> #include <caml/mlvalues.h>
>>> #include "../mylib/mylib.h"
>>> CAMLprim value
>>> my_print_stub(value v) {
>>
>>      CAMLparam1(v);  /* is missing here, for garbage
>>                         collection purposes. */
>>
>>>    char* str = (char*)String_val( v );
>>
>>      /* You do not need the right-hand side (char*) casting. */
>>
>>>    my_print( str );
>>>    return Val_unit;
>>> }
> 
> If you use CAMLparam1, you must use CAMLreturn instead of return.

Yes. Indeed. Didn't see it.

However, I had a look at

	https://yquem.inria.fr/caml/svn/ocaml/version/3.09/byterun/sys.c

and more specifically at the function

> CAMLprim value caml_sys_exit(value retcode)
> {
> #ifndef NATIVE_CODE
>   caml_debugger(PROGRAM_EXIT);
> #endif
>   exit(Int_val(retcode));
>   return Val_unit;
> }

or the function

> CAMLprim value caml_sys_close(value fd)
> {
>   close(Int_val(fd));
>   return Val_unit;
> }

Why do these functions not follow the usual CAMLparam/CAMLreturn macro 
stuff?

-- 
      Guillaume Yziquel
http://yziquel.homelinux.org/


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

* Re: [Caml-list] problem creating .cma library
  2010-01-08 23:38     ` Guillaume Yziquel
@ 2010-01-08 23:54       ` Basile STARYNKEVITCH
  2010-01-09  0:11         ` Guillaume Yziquel
  0 siblings, 1 reply; 21+ messages in thread
From: Basile STARYNKEVITCH @ 2010-01-08 23:54 UTC (permalink / raw)
  To: guillaume.yziquel; +Cc: Damien Doligez, caml-list List

Guillaume Yziquel wrote:
> 
> However, I had a look at
> 
>     https://yquem.inria.fr/caml/svn/ocaml/version/3.09/byterun/sys.c
> 
> and more specifically at the function
> 
>> CAMLprim value caml_sys_exit(value retcode)
>> {
>> #ifndef NATIVE_CODE
>>   caml_debugger(PROGRAM_EXIT);
>> #endif
>>   exit(Int_val(retcode));
>>   return Val_unit;
>> }
> 
> or the function
> 
>> CAMLprim value caml_sys_close(value fd)
>> {
>>   close(Int_val(fd));
>>   return Val_unit;
>> }
> 
> Why do these functions not follow the usual CAMLparam/CAMLreturn macro 
> stuff?
> 

Because they are written by the Ocaml guys (Damien knows really well the Ocaml garbage collector; he wrote it). And 
also, because these particular functions do not do any allocation of Ocaml values (either directly or indirectly).

My advice for people coding C code for ocaml is the following:

1. *always* use the CAMLparam/CAMLreturn/... macros.

2. if you dare not using them for some very few functions (because they don't allocate, ...) add a big fat comment with 
a warning inside.

Regards


-- 
Basile STARYNKEVITCH         http://starynkevitch.net/Basile/
email: basile<at>starynkevitch<dot>net mobile: +33 6 8501 2359
8, rue de la Faiencerie, 92340 Bourg La Reine, France
*** opinions {are only mines, sont seulement les miennes} ***


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

* Re: [Caml-list] problem creating .cma library
  2010-01-08 23:54       ` Basile STARYNKEVITCH
@ 2010-01-09  0:11         ` Guillaume Yziquel
  2010-01-09  7:58           ` David Allsopp
  0 siblings, 1 reply; 21+ messages in thread
From: Guillaume Yziquel @ 2010-01-09  0:11 UTC (permalink / raw)
  To: Basile STARYNKEVITCH; +Cc: Damien Doligez, caml-list List

Basile STARYNKEVITCH a écrit :
>>
>> Why do these functions not follow the usual CAMLparam/CAMLreturn macro 
>> stuff?
> 
> Because they are written by the Ocaml guys (Damien knows really well the 
> Ocaml garbage collector; he wrote it). And also, because these 
> particular functions do not do any allocation of Ocaml values (either 
> directly or indirectly).

So, no allocation of OCaml values (or in place modification, either, I 
guess) implies no need for CAMLparam/CAMLreturn stuff?

> My advice for people coding C code for ocaml is the following:
> 
> 1. *always* use the CAMLparam/CAMLreturn/... macros.
> 
> 2. if you dare not using them for some very few functions (because they 
> don't allocate, ...) add a big fat comment with a warning inside.
> 
> Regards

I want to understand them so that I can abstract away in some other file 
/ .so, some rather usual constructs involving OCaml structures. I think 
it is smarter to take some time doing this, with detailed comments all 
over, than repeating the same mistakes over and over (or worse: 
wondering if you made mistakes) when doing C bindings.

All the best,

-- 
      Guillaume Yziquel
http://yziquel.homelinux.org/


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

* RE: [Caml-list] problem creating .cma library
  2010-01-09  0:11         ` Guillaume Yziquel
@ 2010-01-09  7:58           ` David Allsopp
  2010-01-09 11:33             ` Guillaume Yziquel
  0 siblings, 1 reply; 21+ messages in thread
From: David Allsopp @ 2010-01-09  7:58 UTC (permalink / raw)
  To: 'caml-list List'

Guillaume Yziquel:
> Basile STARYNKEVITCH a écrit :
> >>
> >> Why do these functions not follow the usual CAMLparam/CAMLreturn
> >> macro stuff?
> >
> > Because they are written by the Ocaml guys (Damien knows really well
> > the Ocaml garbage collector; he wrote it). And also, because these
> > particular functions do not do any allocation of Ocaml values (either
> > directly or indirectly).
> 
> So, no allocation of OCaml values (or in place modification, either, I
> guess) implies no need for CAMLparam/CAMLreturn stuff?

Chapter 18 of the manual in Section 18.5 describes pretty much everything you need to know about writing safe stubs that work with the garbage collector. 

> 
> > My advice for people coding C code for ocaml is the following:
> >
> > 1. *always* use the CAMLparam/CAMLreturn/... macros.
> >
> > 2. if you dare not using them for some very few functions (because
> > they don't allocate, ...) add a big fat comment with a warning inside.
> >
> > Regards
> 
> I want to understand them so that I can abstract away in some other file
> / .so, some rather usual constructs involving OCaml structures. I think
> it is smarter to take some time doing this, with detailed comments all
> over, than repeating the same mistakes over and over (or worse:
> wondering if you made mistakes) when doing C bindings.

Having written a few C stubs myself, I'd also highly recommend just following the manual and not worrying about what the macros do - if you want/need to improve allocation performance then you can use the lower-level interface for allocation (but that still involves CAMLparamn/CAMLreturn). I usually find that tricks like this (think Obj.magic) mean that when something goes wrong, there's always a niggling thought in the back of your mind that it's the trick which has broken everything when in fact it's something blindly obvious but you waste hours double-checking the tricks!

In the ideal world, the C written for C stubs would be parsed by a camlp4-like pre-processor which would automatically insert the expansion of those macros where required. If you have CAMLparamn and CAMLreturn on functions which don't strictly need them then you're only creating a few more local roots than are strictly necessary which isn't likely to hurt that much...


David


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

* Re: [Caml-list] problem creating .cma library
  2010-01-09  7:58           ` David Allsopp
@ 2010-01-09 11:33             ` Guillaume Yziquel
  2010-01-09 12:52               ` Richard Jones
  0 siblings, 1 reply; 21+ messages in thread
From: Guillaume Yziquel @ 2010-01-09 11:33 UTC (permalink / raw)
  To: David Allsopp; +Cc: 'caml-list List'

David Allsopp a écrit :
> Guillaume Yziquel:
>
>> So, no allocation of OCaml values (or in place modification, either, I
>> guess) implies no need for CAMLparam/CAMLreturn stuff?
> 
> Chapter 18 of the manual in Section 18.5 describes pretty much everything you need to know about writing safe stubs that work with the garbage collector.  

Yes. It is all I need to know to write safe stubs. But it does not 
answer the question above. It does state that you do not need 
registration of the result value if there's no allocation going on 
between the moment result get its value and the return statement. But it 
does not say when you can avoid CAMLparam macros.

By the way, here's a question I've been wondering about this section. 
Rule 3: When I have a Abstract_tag block used to wrap a pointer in the C 
heap, it seems to me that you can just do it with a Field(v,0)= 
assignment. Do you need Store_field for that?

>> I want to understand them so that I can abstract away in some other file
>> / .so, some rather usual constructs involving OCaml structures. I think
>> it is smarter to take some time doing this, with detailed comments all
>> over, than repeating the same mistakes over and over (or worse:
>> wondering if you made mistakes) when doing C bindings.
> 
> Having written a few C stubs myself, I'd also highly recommend just following the manual and not worrying about what the macros do - if you want/need to improve allocation performance then you can use the lower-level interface for allocation (but that still involves CAMLparamn/CAMLreturn). I usually find that tricks like this (think Obj.magic) mean that when something goes wrong, there's always a niggling thought in the back of your mind that it's the trick which has broken everything when in fact it's something blindly obvious but you waste hours double-checking the tricks!

Yes, but it's also quite a pain not to optimise the binding when you're 
trying to bind a columnar database that compiles SQL to its own language 
and tat tries to make the best use of CPU cache. You tend to feel guilty...

> In the ideal world, the C written for C stubs would be parsed by a camlp4-like pre-processor which would automatically insert the expansion of those macros where required. If you have CAMLparamn and CAMLreturn on functions which don't strictly need them then you're only creating a few more local roots than are strictly necessary which isn't likely to hurt that much...

Maybe. I'm not so sure about that...

> David

All the best,

-- 
      Guillaume Yziquel
http://yziquel.homelinux.org/


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

* Re: [Caml-list] problem creating .cma library
  2010-01-09 11:33             ` Guillaume Yziquel
@ 2010-01-09 12:52               ` Richard Jones
  2010-01-09 14:00                 ` Daniel Bünzli
  2010-01-09 19:29                 ` Guillaume Yziquel
  0 siblings, 2 replies; 21+ messages in thread
From: Richard Jones @ 2010-01-09 12:52 UTC (permalink / raw)
  To: Guillaume Yziquel; +Cc: David Allsopp, 'caml-list List'

On Sat, Jan 09, 2010 at 12:33:08PM +0100, Guillaume Yziquel wrote:
> David Allsopp a écrit :
> >Guillaume Yziquel:
> >
> >>So, no allocation of OCaml values (or in place modification, either, I
> >>guess) implies no need for CAMLparam/CAMLreturn stuff?
> >
> >Chapter 18 of the manual in Section 18.5 describes pretty much everything 
> >you need to know about writing safe stubs that work with the garbage 
> >collector.  
> 
> Yes. It is all I need to know to write safe stubs. But it does not 
> answer the question above. It does state that you do not need 
> registration of the result value if there's no allocation going on 
> between the moment result get its value and the return statement. But it 
> does not say when you can avoid CAMLparam macros.

The basic problem is that whenever you do an allocation, the allocator
might need to run the garbage collector.  Allocations from the minor
heap are normally quick (just comparing and decrementing a pointer),
but once the minor heap runs out a minor heap collection has to be
done, and that implies a slice of major heap collection too.

Why is this a problem?  Because you might in your C code have some
value on the stack.  'value' is (or can be) a pointer.  The OCaml
garbage collector can move pointed-to-objects around, firstly from the
minor heap to the major heap, secondly when compacting the major heap.
So your C value (pointer) *could* become an invalid pointer if what it
was pointing to got moved.

The way to avoid this small chance is to register the value with the
garbage collector, which is essentially what the CAMLparam* and
CAMLlocal* macros do.  So if the GC needs to move that object, it will
update the pointer for you.

If your function never allocates (and never calls anything which
allocates), then you don't need to register values, because no
allocation => they can't be moved.  [In fact there are some other
exceptions as well where you can prove that an allocation won't move
your pointer, eg. if you only allocate one thing and immediately
return the value.]

However it's always safe to use the macros, even if you're not
allocating, albeit a tiny little bit slower.

You might find my series on the garbage collector interesting if you
want to look into this further:

http://rwmj.wordpress.com/?s=ocaml+internals

Also if you are calling C functions which don't allocate from OCaml
code, you might want to read about noalloc:

http://camltastic.blogspot.com/2008/08/tip-calling-c-functions-directly-with.html

> By the way, here's a question I've been wondering about this section. 
> Rule 3: When I have a Abstract_tag block used to wrap a pointer in the C 
> heap, it seems to me that you can just do it with a Field(v,0)= 
> assignment. Do you need Store_field for that?

This is to do with the Remembered Set.  See part 5 of the above
series.

Rich.

-- 
Richard Jones
Red Hat


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

* Re: [Caml-list] problem creating .cma library
  2010-01-09 12:52               ` Richard Jones
@ 2010-01-09 14:00                 ` Daniel Bünzli
  2010-01-09 14:02                   ` Daniel Bünzli
  2010-01-09 19:36                   ` Guillaume Yziquel
  2010-01-09 19:29                 ` Guillaume Yziquel
  1 sibling, 2 replies; 21+ messages in thread
From: Daniel Bünzli @ 2010-01-09 14:00 UTC (permalink / raw)
  To: Guillaume Yziquel; +Cc: caml-list List

Section 2) of this paper also has a very gentle and readable
introduction to the gc :

http://portal.acm.org/citation.cfm?id=141130

Another thing you need to know, if you have long running pieces of C
code that don't interact with ocaml's runtime system, is the two
functions :

caml_enter_blocking_section
caml_leave_blocking_section

They are explained in this message  :

http://caml.inria.fr/pub/ml-archives/caml-list/2001/06/58d7a7e8747056c3842e53b4e9454f44.en.html

Best,

Daniel


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

* Re: [Caml-list] problem creating .cma library
  2010-01-09 14:00                 ` Daniel Bünzli
@ 2010-01-09 14:02                   ` Daniel Bünzli
  2010-01-09 14:21                     ` Joel Reymont
  2010-01-09 19:36                   ` Guillaume Yziquel
  1 sibling, 1 reply; 21+ messages in thread
From: Daniel Bünzli @ 2010-01-09 14:02 UTC (permalink / raw)
  To: Guillaume Yziquel; +Cc: caml-list List

> http://portal.acm.org/citation.cfm?id=141130

http://portal.acm.org/citation.cfm?id=1411308

Sorry,

Daniel


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

* Re: [Caml-list] problem creating .cma library
  2010-01-09 14:02                   ` Daniel Bünzli
@ 2010-01-09 14:21                     ` Joel Reymont
  0 siblings, 0 replies; 21+ messages in thread
From: Joel Reymont @ 2010-01-09 14:21 UTC (permalink / raw)
  To: Daniel Bünzli; +Cc: Guillaume Yziquel, caml-list List


On Jan 9, 2010, at 2:02 PM, Daniel Bünzli wrote:

> http://portal.acm.org/citation.cfm?id=1411308

How can I access this paper without an ACM subscription?

	Thanks, Joel

---
http://wagerlabs.com




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

* Re: [Caml-list] problem creating .cma library
  2010-01-09 12:52               ` Richard Jones
  2010-01-09 14:00                 ` Daniel Bünzli
@ 2010-01-09 19:29                 ` Guillaume Yziquel
  2010-01-11 12:18                   ` Gerd Stolpmann
  2010-01-20 14:42                   ` Damien Doligez
  1 sibling, 2 replies; 21+ messages in thread
From: Guillaume Yziquel @ 2010-01-09 19:29 UTC (permalink / raw)
  To: Richard Jones; +Cc: David Allsopp, 'caml-list List'

Richard Jones a écrit :
>
> Why is this a problem?  Because you might in your C code have some
> value on the stack.  'value' is (or can be) a pointer.  The OCaml
> garbage collector can move pointed-to-objects around, firstly from the
> minor heap to the major heap, secondly when compacting the major heap.
> So your C value (pointer) *could* become an invalid pointer if what it
> was pointing to got moved.

Yes, I understood the nature of the problem.

> The way to avoid this small chance is to register the value with the
> garbage collector, which is essentially what the CAMLparam* and
> CAMLlocal* macros do.  So if the GC needs to move that object, it will
> update the pointer for you.
> 
> If your function never allocates (and never calls anything which
> allocates), then you don't need to register values, because no
> allocation => they can't be moved.  [In fact there are some other
> exceptions as well where you can prove that an allocation won't move
> your pointer, eg. if you only allocate one thing and immediately
> return the value.]

I've been looking at the pcre bindings, and these bindings make minimal 
usage of CAMLparam, CAMLlocal and CAMLreturn.

For instance, here is the piece of code that executes R code ad catches 
errors. I've tried to follow guidelines available on the net, and 
inspired myself from pcre.

> CAMLprim value r_eval_sxp (value sexp_list) {
>   CAMLparam0();
>   CAMLlocal2(ml_error_call, ml_error_message);
>   SEXP e;
>   int error = 0;
>   PROTECT(e = R_tryEval(Sexp_val(sexp_list), R_GlobalEnv, &error));
>   UNPROTECT(1);
>   if (error) {
>     ml_error_call = Val_sexp(error_call);
>     error_call = NULL;
>     ml_error_message = caml_copy_string(error_message);
>     error_message = NULL;
>     value error_result = caml_alloc_small(2, 0);
>     Store_field(error_result, 0, ml_error_call);
>     Store_field(error_result, 1, ml_error_message);
>     raise_with_arg(*caml_named_value("OCaml-R generic error"), error_result);
>   }
>   CAMLreturn(Val_sexp(e));
> }

Do you see GC / allocation / threading problems with it?

Would it be legitimate to include CAMLlocal2 inside the error-handling 
braces?

> You might find my series on the garbage collector interesting if you
> want to look into this further:
> 
> http://rwmj.wordpress.com/?s=ocaml+internals

These are very interesting. Could not find part 6, though...

> Also if you are calling C functions which don't allocate from OCaml
> code, you might want to read about noalloc:
> 
> http://camltastic.blogspot.com/2008/08/tip-calling-c-functions-directly-with.html

Two comments on this:

-1- I remember a post by Jon Harrop concerning external mathematical 
functions such as the exponential in Pervasives. He was arguing that it 
could be done directly from the .ml file by using such "tags". Where can 
I find a list of all these tags for external functions? There's "float", 
but are there others?

-2- If I understand this post well, the following function

> CAMLprim value init_r (value argv, value sigs) {
> 
>   /* -1- argv is an OCaml array of strings, which gives the command line
>      arguments used to invoke the R interpreter. Code segfaults if
>      the array does not contain a first element, which is the name of
>      the program, typically "R", or "OCaml-R". Other arguments typically
>      are "--vanilla", "--slave"...
> 
>      -2- sigs is an OCaml int. When set to 0, R signal handlers are not
>      removed. When set to, say, 1, R signal handlers are removed. It is
>      very useful to remove signal handlers when embedding R. */
> 
>   int length = Wosize_val(argv);
>   char* argv2[length];
>   int i;
> 
>   // We duplicate the OCaml array into a C array.
>   for (i=0; i<length; i++) argv2[i]=String_val(Field(argv, i));
> 
>   /* Don't let R set up its own signal handlers when sigs = 1.
>      This requires R >= 2.3.1. */
>   if (Int_val(sigs)) R_SignalHandlers = 0;
> 
>   // This is the libR.so function.
>   i = Rf_initEmbeddedR(length, argv2);
> 
>   // Returns 1 if R is correctly initialised.
>   return Val_int(i);
> }

could be called with "noalloc"?

>> By the way, here's a question I've been wondering about this section. 
>> Rule 3: When I have a Abstract_tag block used to wrap a pointer in the C 
>> heap, it seems to me that you can just do it with a Field(v,0)= 
>> assignment. Do you need Store_field for that?
> 
> This is to do with the Remembered Set.  See part 5 of the above
> series.

The remembere set, in this context, explains why I would need 
Store_field when dealing with pure OCaml world. When wrapping pointers 
to the C heap in abstract blocks, I do not see the point of Store_field, 
and it seems to me that Field= assignment is fine. Am I mistaken?

All the best,

-- 
      Guillaume Yziquel
http://yziquel.homelinux.org/


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

* Re: [Caml-list] problem creating .cma library
  2010-01-09 14:00                 ` Daniel Bünzli
  2010-01-09 14:02                   ` Daniel Bünzli
@ 2010-01-09 19:36                   ` Guillaume Yziquel
  2010-01-10  2:11                     ` Daniel Bünzli
  2010-01-10 13:31                     ` ygrek
  1 sibling, 2 replies; 21+ messages in thread
From: Guillaume Yziquel @ 2010-01-09 19:36 UTC (permalink / raw)
  To: Daniel Bünzli; +Cc: caml-list List

Daniel Bünzli a écrit :
> Section 2) of this paper also has a very gentle and readable
> introduction to the gc :
> 
> http://portal.acm.org/citation.cfm?id=141130

Thanks for the link.

> Another thing you need to know, if you have long running pieces of C
> code that don't interact with ocaml's runtime system, is the two
> functions :
> 
> caml_enter_blocking_section
> caml_leave_blocking_section
> 
> They are explained in this message  :
> 
> http://caml.inria.fr/pub/ml-archives/caml-list/2001/06/58d7a7e8747056c3842e53b4e9454f44.en.html

OK.

So if I want to call R code that multithreads with OCaml, I should write 
something like

>   enter_blocking_section();
>   PROTECT(e = R_tryEval(Sexp_val(sexp_list), R_GlobalEnv, &error));
>   UNPROTECT(1);
>   leave_blocking_section();

Am I correct?

-- 
      Guillaume Yziquel
http://yziquel.homelinux.org/


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

* Re: [Caml-list] problem creating .cma library
  2010-01-09 19:36                   ` Guillaume Yziquel
@ 2010-01-10  2:11                     ` Daniel Bünzli
  2010-01-11 17:14                       ` Guillaume Yziquel
  2010-01-10 13:31                     ` ygrek
  1 sibling, 1 reply; 21+ messages in thread
From: Daniel Bünzli @ 2010-01-10  2:11 UTC (permalink / raw)
  To: guillaume.yziquel; +Cc: caml-list List

> So if I want to call R code that multithreads with OCaml, I should write
> something like
>
>>  enter_blocking_section();
>>  PROTECT(e = R_tryEval(Sexp_val(sexp_list), R_GlobalEnv, &error));
>>  UNPROTECT(1);
>>  leave_blocking_section();
>
> Am I correct?

Yes, but the functions have now a caml_ prefix.

Make sure that there is no interaction whatsoever with ocaml's runtime
system (e.g. ocaml value allocation) between the two calls.

Note also that in case you need to use some caml value after the leave
call you have to declare it with a CAMLparam macro as it may move
during the blocking section even if the stub itself doesn't allocate.

Best,

Daniel


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

* Re: [Caml-list] problem creating .cma library
  2010-01-09 19:36                   ` Guillaume Yziquel
  2010-01-10  2:11                     ` Daniel Bünzli
@ 2010-01-10 13:31                     ` ygrek
  2010-01-11 18:01                       ` Guillaume Yziquel
  1 sibling, 1 reply; 21+ messages in thread
From: ygrek @ 2010-01-10 13:31 UTC (permalink / raw)
  To: caml-list

On Sat, 09 Jan 2010 20:36:07 +0100
Guillaume Yziquel <guillaume.yziquel@citycable.ch> wrote:

> So if I want to call R code that multithreads with OCaml, I should write 
> something like
> 
> >   enter_blocking_section();
> >   PROTECT(e = R_tryEval(Sexp_val(sexp_list), R_GlobalEnv, &error));
> >   UNPROTECT(1);
> >   leave_blocking_section();
> 
> Am I correct?

I bet no. It is not safe to access block ocaml value
inside blocking_section. In this particular case Sexp_val(v) is Field
(v,0) whis in turn is v[0] or *v. So you read the pointer, then in
another thread GC moves things around and old copy of the pointed
value is overwritten, then you read the value through 
the old pointer and get garbage.
Put Sexp_val call before caml_enter_blocking_section().

-- 
 ygrek
 http://ygrek.org.ua


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

* Re: [Caml-list] problem creating .cma library
  2010-01-09 19:29                 ` Guillaume Yziquel
@ 2010-01-11 12:18                   ` Gerd Stolpmann
  2010-01-11 17:11                     ` Guillaume Yziquel
  2010-01-20 14:42                   ` Damien Doligez
  1 sibling, 1 reply; 21+ messages in thread
From: Gerd Stolpmann @ 2010-01-11 12:18 UTC (permalink / raw)
  To: guillaume.yziquel; +Cc: Richard Jones, 'caml-list List'

> For instance, here is the piece of code that executes R code ad catches 
> errors. I've tried to follow guidelines available on the net, and 
> inspired myself from pcre.
> 
> > CAMLprim value r_eval_sxp (value sexp_list) {
> >   CAMLparam0();
> >   CAMLlocal2(ml_error_call, ml_error_message);
> >   SEXP e;
> >   int error = 0;
> >   PROTECT(e = R_tryEval(Sexp_val(sexp_list), R_GlobalEnv, &error));
> >   UNPROTECT(1);
> >   if (error) {
> >     ml_error_call = Val_sexp(error_call);
> >     error_call = NULL;
> >     ml_error_message = caml_copy_string(error_message);
> >     error_message = NULL;
> >     value error_result = caml_alloc_small(2, 0);
> >     Store_field(error_result, 0, ml_error_call);
> >     Store_field(error_result, 1, ml_error_message);
> >     raise_with_arg(*caml_named_value("OCaml-R generic error"), error_result);
> >   }
> >   CAMLreturn(Val_sexp(e));
> > }
> 
> Do you see GC / allocation / threading problems with it?
> 
> Would it be legitimate to include CAMLlocal2 inside the error-handling 
> braces?

No. You would start a new context for local roots, and there is no way
to end it (CAMLreturn ends the context).

There are the macros Begin_roots<n> and End_roots that should be used in
this case, e.g.

if (error) {
  value ml_error_call = Val_unit;
  value ml_error_message = Val_unit;

  Begin_roots2(ml_error_call, ml_error_message);
  ...
  End_roots();

  raise_with_arg(...)
}

The macros are only documented in memory.h.

So far I know, raising an exception from within Begin_roots/End_roots is
not allowed.

Gerd
-- 
------------------------------------------------------------
Gerd Stolpmann, Bad Nauheimer Str.3, 64289 Darmstadt,Germany 
gerd@gerd-stolpmann.de          http://www.gerd-stolpmann.de
Phone: +49-6151-153855                  Fax: +49-6151-997714
------------------------------------------------------------


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

* Re: [Caml-list] problem creating .cma library
  2010-01-11 12:18                   ` Gerd Stolpmann
@ 2010-01-11 17:11                     ` Guillaume Yziquel
  0 siblings, 0 replies; 21+ messages in thread
From: Guillaume Yziquel @ 2010-01-11 17:11 UTC (permalink / raw)
  To: Gerd Stolpmann; +Cc: Richard Jones, 'caml-list List'

Gerd Stolpmann a écrit :
>>
>> Would it be legitimate to include CAMLlocal2 inside the error-handling 
>> braces?
> 
> No. You would start a new context for local roots, and there is no way
> to end it (CAMLreturn ends the context).
> 
> There are the macros Begin_roots<n> and End_roots that should be used in
> this case, e.g.
> 
> if (error) {
>   value ml_error_call = Val_unit;
>   value ml_error_message = Val_unit;
> 
>   Begin_roots2(ml_error_call, ml_error_message);
>   ...
>   End_roots();
> 
>   raise_with_arg(...)
> }

End_roots before caml_raise_with_arg? Why not after?

I mean, you do not do a CAMLreturn before a caml_raise_with_args, so why 
should't this be the same for End_roots()?

> The macros are only documented in memory.h.
> 
> So far I know, raising an exception from within Begin_roots/End_roots is
> not allowed.

It seems to me that the major issue is how caml_local_roots gets 
restored. With the CAMLparam/CAMLreturn macros, this is done by storing 
its original value in caml__frame and restoring it via CAMLreturn.

As it is written in memory.h

> Your function may raise an exception or return a [value] with the
> [CAMLreturn] macro.

I assume that caml_local_roots gets restored by a mechanism in the 'try' 
of the 'try / with' construct after the siglongjmp of caml_raise.

Therefore it should be OK to use caml_raise_with_args before End_roots().

Am I right, or is this plainly wild guessing?

-- 
      Guillaume Yziquel
http://yziquel.homelinux.org/


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

* Re: [Caml-list] problem creating .cma library
  2010-01-10  2:11                     ` Daniel Bünzli
@ 2010-01-11 17:14                       ` Guillaume Yziquel
  0 siblings, 0 replies; 21+ messages in thread
From: Guillaume Yziquel @ 2010-01-11 17:14 UTC (permalink / raw)
  To: Daniel Bünzli; +Cc: caml-list List

Daniel Bünzli a écrit :
>> So if I want to call R code that multithreads with OCaml, I should write
>> something like
>>
>>>  enter_blocking_section();
>>>  PROTECT(e = R_tryEval(Sexp_val(sexp_list), R_GlobalEnv, &error));
>>>  UNPROTECT(1);
>>>  leave_blocking_section();
>> Am I correct?
> 
> Yes, but the functions have now a caml_ prefix.
> 
> Make sure that there is no interaction whatsoever with ocaml's runtime
> system (e.g. ocaml value allocation) between the two calls.

I will have interaction, because I plan to be able to make R call OCaml 
code (not in the foreseeable future). But it's just a question of 
wrapping the call back to Ocaml with a

	caml_leave_blocking_section()
	callingOCamlcode()
	caml_enter_blocking_section()

construct. As far as I've understood.

> Note also that in case you need to use some caml value after the leave
> call you have to declare it with a CAMLparam macro as it may move
> during the blocking section even if the stub itself doesn't allocate.

Very helpful. Thanks a lot.

-- 
      Guillaume Yziquel
http://yziquel.homelinux.org/


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

* Re: [Caml-list] problem creating .cma library
  2010-01-10 13:31                     ` ygrek
@ 2010-01-11 18:01                       ` Guillaume Yziquel
  0 siblings, 0 replies; 21+ messages in thread
From: Guillaume Yziquel @ 2010-01-11 18:01 UTC (permalink / raw)
  To: ygrek; +Cc: caml-list

ygrek a écrit :
> On Sat, 09 Jan 2010 20:36:07 +0100
> Guillaume Yziquel <guillaume.yziquel@citycable.ch> wrote:
> 
>> So if I want to call R code that multithreads with OCaml, I should write 
>> something like
>>
>>>   enter_blocking_section();
>>>   PROTECT(e = R_tryEval(Sexp_val(sexp_list), R_GlobalEnv, &error));
>>>   UNPROTECT(1);
>>>   leave_blocking_section();
>> Am I correct?
> 
> I bet no. It is not safe to access block ocaml value
> inside blocking_section. In this particular case Sexp_val(v) is Field
> (v,0) whis in turn is v[0] or *v. So you read the pointer, then in
> another thread GC moves things around and old copy of the pointed
> value is overwritten, then you read the value through 
> the old pointer and get garbage.
> Put Sexp_val call before caml_enter_blocking_section().

OK. Thanks....



-- 
      Guillaume Yziquel
http://yziquel.homelinux.org/


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

* Re: [Caml-list] problem creating .cma library
  2010-01-09 19:29                 ` Guillaume Yziquel
  2010-01-11 12:18                   ` Gerd Stolpmann
@ 2010-01-20 14:42                   ` Damien Doligez
  1 sibling, 0 replies; 21+ messages in thread
From: Damien Doligez @ 2010-01-20 14:42 UTC (permalink / raw)
  To: guillaume.yziquel; +Cc: caml-list List


On 2010-01-09, at 20:29, Guillaume Yziquel wrote:

> The remembere set, in this context, explains why I would need  
> Store_field when dealing with pure OCaml world. When wrapping  
> pointers to the C heap in abstract blocks, I do not see the point of  
> Store_field, and it seems to me that Field= assignment is fine. Am I  
> mistaken?

When assigning into an Abstract block, Store_field is not needed.
Moreover, when assigning or overwriting a non-pointer in an Abstract
block, Store_field is forbidden.  So you'd better never use it to
assign into an Abstract block.

A trick to remember it: the contents of an Abstract block is not
fields as far as the GC is concerned.

> I assume that caml_local_roots gets restored by a mechanism in the  
> 'try' of the 'try / with' construct after the siglongjmp of  
> caml_raise.
>
> Therefore it should be OK to use caml_raise_with_args before  
> End_roots().
>
> Am I right, or is this plainly wild guessing?


Your wild guessing is correct (line 249 of interp.c).

-- Damien


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

end of thread, other threads:[~2010-01-20 14:42 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-12-30 17:48 problem creating .cma library rouanvd
2009-12-30 23:30 ` [Caml-list] " Guillaume Yziquel
2010-01-05 13:04   ` Damien Doligez
2010-01-08 23:38     ` Guillaume Yziquel
2010-01-08 23:54       ` Basile STARYNKEVITCH
2010-01-09  0:11         ` Guillaume Yziquel
2010-01-09  7:58           ` David Allsopp
2010-01-09 11:33             ` Guillaume Yziquel
2010-01-09 12:52               ` Richard Jones
2010-01-09 14:00                 ` Daniel Bünzli
2010-01-09 14:02                   ` Daniel Bünzli
2010-01-09 14:21                     ` Joel Reymont
2010-01-09 19:36                   ` Guillaume Yziquel
2010-01-10  2:11                     ` Daniel Bünzli
2010-01-11 17:14                       ` Guillaume Yziquel
2010-01-10 13:31                     ` ygrek
2010-01-11 18:01                       ` Guillaume Yziquel
2010-01-09 19:29                 ` Guillaume Yziquel
2010-01-11 12:18                   ` Gerd Stolpmann
2010-01-11 17:11                     ` Guillaume Yziquel
2010-01-20 14:42                   ` Damien Doligez

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).