[
Home
]
[ Index:
by date
|
by threads
]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
| Date: | -- (:) |
| From: | Daniel_Bünzli <daniel.buenzli@e...> |
| Subject: | Bigarrays and temporar C pointers |
Hello,
Suppose that I have a C library which allows me to access data via a
temporar pointer with the following interface :
> void *map(void); /* Returns a valid pointer to data */
> int map_size(void); /* Returns the size of the data in bytes. */
> void unmap(void); /* Invalidates the last pointer returned by map. */
Mapping data to a pointer must only be done for a short period of time:
map, get size, process data, and unmap.
I would like to be able to process data in ocaml with bigarrays. To do
so I provide the ocaml function `map'. This function maps the pointer,
pass it as a bigarray to a user callback to process the data and then
unmaps the pointer.
> open Bigarray;;
>
> type ('a, 'b) data = ('a, 'b, c_layout) Array1.t
>
> val map : ('a, b) kind -> (('a, 'b) data -> unit) -> unit
Map is implemented as follow (C primitives are at the end of the mail),
> external _map_ptr : ('a, 'b) kind -> ('a, 'b) data = "stub_map_ptr"
> external _unmap_ptr : ('a, 'b) data -> unit = "stub_unmap_ptr"
>
> let map k f =
> let a = _map_ptr k in
> f a;
> _unmap_ptr a
My problem is that the provided bigarray may escape the scope of the
user callback (e.g. by setting a global reference to the bigarray)
potentially allowing the user to access data at an invalid pointer
position after the pointer was invalidated.
In fact for the bigarray itself it is not a problem, I set its
dimension to zero when I unmap it in _unmap_ptr (see the C
implementation below) so access outside the user callback raise
exceptions. However, according to my experiments and wandering in the
implementation of bigarray this doesn't work if the user extracts a
subarray with Array1.sub and sets it to a global variable.
Is there a solution to make that completely safe or I can only warn the
user that he should not to try to escape data from the callback ?
Thanks for your help,
Daniel
The implementation of the C primitives :
> extern int bigarray_element_size[]; /* bigarray_stubs.c */
>
> CAMLprim value stub_map_ptr (value kind)
> {
> void *p = map ();
> long dim = map_size () / bigarray_element_size[Int_val (kind)];
> int flag = Int_val (kind) | BIGARRAY_C_LAYOUT | BIGARRAY_EXTERNAL;
> return alloc_bigarray(flag, 1, p, &dim);
> }
>
> CAMLprim value stub_unmap_ptr (value b)
> {
> struct caml_bigarray *arr = Bigarray_val(b);
> arr->data = NULL;
> arr->dim[0] = 0;
> unmap();
> return Val_unit;
> }