caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* FW: CamlIDL: Returning a whole array of cows
@ 2007-11-05 18:31 Jakob Lichtenberg
  2007-11-05 20:50 ` [Caml-list] " Christopher L Conway
  0 siblings, 1 reply; 5+ messages in thread
From: Jakob Lichtenberg @ 2007-11-05 18:31 UTC (permalink / raw)
  To: caml-list

[-- Attachment #1: Type: text/plain, Size: 2890 bytes --]

Resending due to no answer.

- Jakob

From: Jakob Lichtenberg
Sent: Monday, September 17, 2007 1:11 PM
To: 'caml-list@inria.fr'
Subject: CamlIDL: Returning a whole array of cows

1. Summary: Stub code generated by Camlidl seems to call camlidl_malloc with an uninitialized size.


2. Details:

I am declaring a function 'void get_cows([out] int* len, [length_is(*len), size_is(*len), out] cow** cows);' that creates and returns an array of cows.  (Each cow is just a pointer to a structure.)  The generated stub code seems incorrect:

cow_stubs.c:
value camlidl_cow_get_cows(value _unit)
{
  int *len; /*out*/
  cow **cows; /*out*/
  int _c1;
  mlsize_t _c2;
  value _v3;
  value _vres;

  struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL };
  camlidl_ctx _ctx = &_ctxs;
  len = &_c1;
  cows = camlidl_malloc(*len * sizeof(cow *), _ctx);
  get_cows(len, cows);
  _vres = camlidl_alloc(*len, 0);
  Begin_root(_vres)
    for (_c2 = 0; _c2 < *len; _c2++) {
      _v3 = camlidl_c2ml_cow_cow(&*cows[_c2], _ctx);
      modify(&Field(_vres, _c2), _v3);
    }
  End_roots()
  camlidl_free(_ctx);
  return _vres;
}

As you can see camlidl_malloc is called with an uninitialized value.

Is this a bug in camlidl, or am I writing my IDL file incorrectly.  Another way to ask:  How do I declared that a function reserves an array


3. Implementation details:

This is my C api I'd like to access from ocaml:

cow.h:
typedef struct _cow {
  char* name;
  int age;
} *cow;

cow get_dummy_cow();

void get_cows_inout(int inputlen, int *outputlen, cow ca[]); // Write cows to 'ca', however not more than 'inputlen' elements.  Write number of cows written to '*outputlen'.

void get_cows(int* len, cow **ca); // Malloc array for cows.  Save number of elements to *len, save address for array in '*ca'.

void print_cow(cow o);

I'd like to access this API from OCaml using CamlIDL.  I use the following idl file:

cow.idl:
typedef [abstract] void* cow;

[pointer_default(ref)] interface Cow {

cow get_dummy_cow(void);

void get_cows_inout([in] int inputlen, [out] int * outputlen,
                    [in,out,size_is(inputlen),length_is(*outputlen)] cow d[]);

void get_cows([out] int* len, [length_is(*len), size_is(*len), out] cow** cows);

void print_cow(cow o);

}

I compile this using:

                camlidl cow.idl

And use it from the following ML program:

mlmain.ml:
let main use_inout =
  let cows =
    if use_inout then Cow.get_cows_inout(Array.create 3 (Cow.get_dummy_cow()))
    else Cow.get_cows()
  in
  Array.iter Cow.print_cow cows

let _ = main true;

This works fine.  However, if I change the call to main to 'main false'  I get a crash.

Thanks,


-        Jakob

PS. I know that I am leaking memory - that I can fix with a simple quote(dealloc, "free(*cows);");

[-- Attachment #2: Type: text/html, Size: 16915 bytes --]

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

* Re: [Caml-list] FW: CamlIDL: Returning a whole array of cows
  2007-11-05 18:31 FW: CamlIDL: Returning a whole array of cows Jakob Lichtenberg
@ 2007-11-05 20:50 ` Christopher L Conway
  2007-11-05 21:20   ` Jakob Lichtenberg
  0 siblings, 1 reply; 5+ messages in thread
From: Christopher L Conway @ 2007-11-05 20:50 UTC (permalink / raw)
  To: Jakob Lichtenberg; +Cc: caml-list

Jakob,

I sent out pretty much the same question to the list just last week
and also didn't get a satisfactory answer (see here:
http://caml.inria.fr/pub/ml-archives/caml-list/2007/10/efb73229fa177fb413e663a2c1ad28b4.en.html).
 It seems that when you add a size_is annotation to a parameter, the
size is treated as a pre-condition, not as a post-condition. If you
have the freedom to change the C API, you might try:

[size_is(*outputlen)] cow *get_cows_inout([in] int inputlen, [ignore]
int *outputlen);

IIRC, this will give you the correct behavior. The alternative is
hand-code the wrapper.

Regards,
Chris

On 11/5/07, Jakob Lichtenberg <jakobl@windows.microsoft.com> wrote:
>
>
>
>
> Resending due to no answer.
>
>
>
> - Jakob
>
>
>
>
>
> From: Jakob Lichtenberg
>  Sent: Monday, September 17, 2007 1:11 PM
>  To: 'caml-list@inria.fr'
>  Subject: CamlIDL: Returning a whole array of cows
>
>
>
> 1. Summary: Stub code generated by Camlidl seems to call camlidl_malloc with
> an uninitialized size.
>
>
>
>
>
> 2. Details:
>
>
>
> I am declaring a function 'void get_cows([out] int* len, [length_is(*len),
> size_is(*len), out] cow** cows);' that creates and returns an array of cows.
>  (Each cow is just a pointer to a structure.)  The generated stub code seems
> incorrect:
>
>
>
> cow_stubs.c:
>
> value camlidl_cow_get_cows(value _unit)
>
> {
>
>   int *len; /*out*/
>
>   cow **cows; /*out*/
>
>   int _c1;
>
>   mlsize_t _c2;
>
>   value _v3;
>
>   value _vres;
>
>
>
>   struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL };
>
>   camlidl_ctx _ctx = &_ctxs;
>
>   len = &_c1;
>
>   cows = camlidl_malloc(*len * sizeof(cow *), _ctx);
>
>   get_cows(len, cows);
>
>   _vres = camlidl_alloc(*len, 0);
>
>   Begin_root(_vres)
>
>     for (_c2 = 0; _c2 < *len; _c2++) {
>
>       _v3 = camlidl_c2ml_cow_cow(&*cows[_c2], _ctx);
>
>       modify(&Field(_vres, _c2), _v3);
>
>     }
>
>   End_roots()
>
>   camlidl_free(_ctx);
>
>   return _vres;
>
> }
>
>
>
> As you can see camlidl_malloc is called with an uninitialized value.
>
>
>
> Is this a bug in camlidl, or am I writing my IDL file incorrectly.  Another
> way to ask:  How do I declared that a function reserves an array
>
>
>
>
>
> 3. Implementation details:
>
>
>
> This is my C api I'd like to access from ocaml:
>
>
>
> cow.h:
>
> typedef struct _cow {
>
>   char* name;
>
>   int age;
>
> } *cow;
>
>
>
> cow get_dummy_cow();
>
>
>
> void get_cows_inout(int inputlen, int *outputlen, cow ca[]); // Write cows
> to 'ca', however not more than 'inputlen' elements.  Write number of cows
> written to '*outputlen'.
>
>
>
> void get_cows(int* len, cow **ca); // Malloc array for cows.  Save number of
> elements to *len, save address for array in '*ca'.
>
>
>
> void print_cow(cow o);
>
>
>
> I'd like to access this API from OCaml using CamlIDL.  I use the following
> idl file:
>
>
>
> cow.idl:
>
> typedef [abstract] void* cow;
>
>
>
> [pointer_default(ref)] interface Cow {
>
>
>
> cow get_dummy_cow(void);
>
>
>
> void get_cows_inout([in] int inputlen, [out] int * outputlen,
>
>
> [in,out,size_is(inputlen),length_is(*outputlen)] cow d[]);
>
>
>
> void get_cows([out] int* len, [length_is(*len), size_is(*len), out] cow**
> cows);
>
>
>
> void print_cow(cow o);
>
>
>
> }
>
>
>
> I compile this using:
>
>
>
>                 camlidl cow.idl
>
>
>
> And use it from the following ML program:
>
>
>
> mlmain.ml:
>
> let main use_inout =
>
>   let cows =
>
>     if use_inout then Cow.get_cows_inout(Array.create 3
> (Cow.get_dummy_cow()))
>
>     else Cow.get_cows()
>
>   in
>
>   Array.iter Cow.print_cow cows
>
>
>
> let _ = main true;
>
>
>
> This works fine.  However, if I change the call to main to 'main false'  I
> get a crash.
>
>
>
> Thanks,
>
>
>
> -        Jakob
>
>
>
> PS. I know that I am leaking memory – that I can fix with a simple
> quote(dealloc, "free(*cows);");
> _______________________________________________
> Caml-list mailing list. Subscription management:
> http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
> Archives: http://caml.inria.fr
> 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] FW: CamlIDL: Returning a whole array of cows
  2007-11-05 20:50 ` [Caml-list] " Christopher L Conway
@ 2007-11-05 21:20   ` Jakob Lichtenberg
  2007-11-05 21:28     ` Christopher L Conway
  0 siblings, 1 reply; 5+ messages in thread
From: Jakob Lichtenberg @ 2007-11-05 21:20 UTC (permalink / raw)
  To: Christopher L Conway; +Cc: caml-list

Christopher,

Thanks for the immediate reply,

Even if I can change the interface, you suggestion provides an ML API with the wrong ML type:
  val get_cows : int -> cow array

I want a type:
  val get_cows : unit -> cow array

Why: The ML user has no idea how many cows will be returned and can hence not be expected to provide this as an argument!

Thanks,

- Jakob

-----Original Message-----
From: christopherleeconway@gmail.com [mailto:christopherleeconway@gmail.com] On Behalf Of Christopher L Conway
Sent: Monday, November 05, 2007 12:51 PM
To: Jakob Lichtenberg
Cc: caml-list@inria.fr
Subject: Re: [Caml-list] FW: CamlIDL: Returning a whole array of cows

Jakob,

I sent out pretty much the same question to the list just last week
and also didn't get a satisfactory answer (see here:
http://caml.inria.fr/pub/ml-archives/caml-list/2007/10/efb73229fa177fb413e663a2c1ad28b4.en.html).
 It seems that when you add a size_is annotation to a parameter, the
size is treated as a pre-condition, not as a post-condition. If you
have the freedom to change the C API, you might try:

[size_is(*outputlen)] cow *get_cows_inout([in] int inputlen, [ignore]
int *outputlen);

IIRC, this will give you the correct behavior. The alternative is
hand-code the wrapper.

Regards,
Chris

On 11/5/07, Jakob Lichtenberg <jakobl@windows.microsoft.com> wrote:
>
>
>
>
> Resending due to no answer.
>
>
>
> - Jakob
>
>
>
>
>
> From: Jakob Lichtenberg
>  Sent: Monday, September 17, 2007 1:11 PM
>  To: 'caml-list@inria.fr'
>  Subject: CamlIDL: Returning a whole array of cows
>
>
>
> 1. Summary: Stub code generated by Camlidl seems to call camlidl_malloc with
> an uninitialized size.
>
>
>
>
>
> 2. Details:
>
>
>
> I am declaring a function 'void get_cows([out] int* len, [length_is(*len),
> size_is(*len), out] cow** cows);' that creates and returns an array of cows.
>  (Each cow is just a pointer to a structure.)  The generated stub code seems
> incorrect:
>
>
>
> cow_stubs.c:
>
> value camlidl_cow_get_cows(value _unit)
>
> {
>
>   int *len; /*out*/
>
>   cow **cows; /*out*/
>
>   int _c1;
>
>   mlsize_t _c2;
>
>   value _v3;
>
>   value _vres;
>
>
>
>   struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL };
>
>   camlidl_ctx _ctx = &_ctxs;
>
>   len = &_c1;
>
>   cows = camlidl_malloc(*len * sizeof(cow *), _ctx);
>
>   get_cows(len, cows);
>
>   _vres = camlidl_alloc(*len, 0);
>
>   Begin_root(_vres)
>
>     for (_c2 = 0; _c2 < *len; _c2++) {
>
>       _v3 = camlidl_c2ml_cow_cow(&*cows[_c2], _ctx);
>
>       modify(&Field(_vres, _c2), _v3);
>
>     }
>
>   End_roots()
>
>   camlidl_free(_ctx);
>
>   return _vres;
>
> }
>
>
>
> As you can see camlidl_malloc is called with an uninitialized value.
>
>
>
> Is this a bug in camlidl, or am I writing my IDL file incorrectly.  Another
> way to ask:  How do I declared that a function reserves an array
>
>
>
>
>
> 3. Implementation details:
>
>
>
> This is my C api I'd like to access from ocaml:
>
>
>
> cow.h:
>
> typedef struct _cow {
>
>   char* name;
>
>   int age;
>
> } *cow;
>
>
>
> cow get_dummy_cow();
>
>
>
> void get_cows_inout(int inputlen, int *outputlen, cow ca[]); // Write cows
> to 'ca', however not more than 'inputlen' elements.  Write number of cows
> written to '*outputlen'.
>
>
>
> void get_cows(int* len, cow **ca); // Malloc array for cows.  Save number of
> elements to *len, save address for array in '*ca'.
>
>
>
> void print_cow(cow o);
>
>
>
> I'd like to access this API from OCaml using CamlIDL.  I use the following
> idl file:
>
>
>
> cow.idl:
>
> typedef [abstract] void* cow;
>
>
>
> [pointer_default(ref)] interface Cow {
>
>
>
> cow get_dummy_cow(void);
>
>
>
> void get_cows_inout([in] int inputlen, [out] int * outputlen,
>
>
> [in,out,size_is(inputlen),length_is(*outputlen)] cow d[]);
>
>
>
> void get_cows([out] int* len, [length_is(*len), size_is(*len), out] cow**
> cows);
>
>
>
> void print_cow(cow o);
>
>
>
> }
>
>
>
> I compile this using:
>
>
>
>                 camlidl cow.idl
>
>
>
> And use it from the following ML program:
>
>
>
> mlmain.ml:
>
> let main use_inout =
>
>   let cows =
>
>     if use_inout then Cow.get_cows_inout(Array.create 3
> (Cow.get_dummy_cow()))
>
>     else Cow.get_cows()
>
>   in
>
>   Array.iter Cow.print_cow cows
>
>
>
> let _ = main true;
>
>
>
> This works fine.  However, if I change the call to main to 'main false'  I
> get a crash.
>
>
>
> Thanks,
>
>
>
> -        Jakob
>
>
>
> PS. I know that I am leaking memory - that I can fix with a simple
> quote(dealloc, "free(*cows);");
> _______________________________________________
> Caml-list mailing list. Subscription management:
> http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
> Archives: http://caml.inria.fr
> 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] FW: CamlIDL: Returning a whole array of cows
  2007-11-05 21:20   ` Jakob Lichtenberg
@ 2007-11-05 21:28     ` Christopher L Conway
  2007-11-05 21:35       ` Jakob Lichtenberg
  0 siblings, 1 reply; 5+ messages in thread
From: Christopher L Conway @ 2007-11-05 21:28 UTC (permalink / raw)
  To: Jakob Lichtenberg; +Cc: caml-list

Jakob,

Sorry for the confusion: my suggestion was for your get_cows_inout
function (where the integer input constrains the length of the
output). For get_cows, just use:

[size_is(*len)] cow *get_cows([ignore] int* len);

Regards,
Chris

On 11/5/07, Jakob Lichtenberg <jakobl@windows.microsoft.com> wrote:
> Christopher,
>
> Thanks for the immediate reply,
>
> Even if I can change the interface, you suggestion provides an ML API with the wrong ML type:
>   val get_cows : int -> cow array
>
> I want a type:
>   val get_cows : unit -> cow array
>
> Why: The ML user has no idea how many cows will be returned and can hence not be expected to provide this as an argument!
>
> Thanks,
>
> - Jakob
>
> -----Original Message-----
> From: christopherleeconway@gmail.com [mailto:christopherleeconway@gmail.com] On Behalf Of Christopher L Conway
> Sent: Monday, November 05, 2007 12:51 PM
> To: Jakob Lichtenberg
> Cc: caml-list@inria.fr
> Subject: Re: [Caml-list] FW: CamlIDL: Returning a whole array of cows
>
> Jakob,
>
> I sent out pretty much the same question to the list just last week
> and also didn't get a satisfactory answer (see here:
> http://caml.inria.fr/pub/ml-archives/caml-list/2007/10/efb73229fa177fb413e663a2c1ad28b4.en.html).
>  It seems that when you add a size_is annotation to a parameter, the
> size is treated as a pre-condition, not as a post-condition. If you
> have the freedom to change the C API, you might try:
>
> [size_is(*outputlen)] cow *get_cows_inout([in] int inputlen, [ignore]
> int *outputlen);
>
> IIRC, this will give you the correct behavior. The alternative is
> hand-code the wrapper.
>
> Regards,
> Chris
>
> On 11/5/07, Jakob Lichtenberg <jakobl@windows.microsoft.com> wrote:
> >
> >
> >
> >
> > Resending due to no answer.
> >
> >
> >
> > - Jakob
> >
> >
> >
> >
> >
> > From: Jakob Lichtenberg
> >  Sent: Monday, September 17, 2007 1:11 PM
> >  To: 'caml-list@inria.fr'
> >  Subject: CamlIDL: Returning a whole array of cows
> >
> >
> >
> > 1. Summary: Stub code generated by Camlidl seems to call camlidl_malloc with
> > an uninitialized size.
> >
> >
> >
> >
> >
> > 2. Details:
> >
> >
> >
> > I am declaring a function 'void get_cows([out] int* len, [length_is(*len),
> > size_is(*len), out] cow** cows);' that creates and returns an array of cows.
> >  (Each cow is just a pointer to a structure.)  The generated stub code seems
> > incorrect:
> >
> >
> >
> > cow_stubs.c:
> >
> > value camlidl_cow_get_cows(value _unit)
> >
> > {
> >
> >   int *len; /*out*/
> >
> >   cow **cows; /*out*/
> >
> >   int _c1;
> >
> >   mlsize_t _c2;
> >
> >   value _v3;
> >
> >   value _vres;
> >
> >
> >
> >   struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL };
> >
> >   camlidl_ctx _ctx = &_ctxs;
> >
> >   len = &_c1;
> >
> >   cows = camlidl_malloc(*len * sizeof(cow *), _ctx);
> >
> >   get_cows(len, cows);
> >
> >   _vres = camlidl_alloc(*len, 0);
> >
> >   Begin_root(_vres)
> >
> >     for (_c2 = 0; _c2 < *len; _c2++) {
> >
> >       _v3 = camlidl_c2ml_cow_cow(&*cows[_c2], _ctx);
> >
> >       modify(&Field(_vres, _c2), _v3);
> >
> >     }
> >
> >   End_roots()
> >
> >   camlidl_free(_ctx);
> >
> >   return _vres;
> >
> > }
> >
> >
> >
> > As you can see camlidl_malloc is called with an uninitialized value.
> >
> >
> >
> > Is this a bug in camlidl, or am I writing my IDL file incorrectly.  Another
> > way to ask:  How do I declared that a function reserves an array
> >
> >
> >
> >
> >
> > 3. Implementation details:
> >
> >
> >
> > This is my C api I'd like to access from ocaml:
> >
> >
> >
> > cow.h:
> >
> > typedef struct _cow {
> >
> >   char* name;
> >
> >   int age;
> >
> > } *cow;
> >
> >
> >
> > cow get_dummy_cow();
> >
> >
> >
> > void get_cows_inout(int inputlen, int *outputlen, cow ca[]); // Write cows
> > to 'ca', however not more than 'inputlen' elements.  Write number of cows
> > written to '*outputlen'.
> >
> >
> >
> > void get_cows(int* len, cow **ca); // Malloc array for cows.  Save number of
> > elements to *len, save address for array in '*ca'.
> >
> >
> >
> > void print_cow(cow o);
> >
> >
> >
> > I'd like to access this API from OCaml using CamlIDL.  I use the following
> > idl file:
> >
> >
> >
> > cow.idl:
> >
> > typedef [abstract] void* cow;
> >
> >
> >
> > [pointer_default(ref)] interface Cow {
> >
> >
> >
> > cow get_dummy_cow(void);
> >
> >
> >
> > void get_cows_inout([in] int inputlen, [out] int * outputlen,
> >
> >
> > [in,out,size_is(inputlen),length_is(*outputlen)] cow d[]);
> >
> >
> >
> > void get_cows([out] int* len, [length_is(*len), size_is(*len), out] cow**
> > cows);
> >
> >
> >
> > void print_cow(cow o);
> >
> >
> >
> > }
> >
> >
> >
> > I compile this using:
> >
> >
> >
> >                 camlidl cow.idl
> >
> >
> >
> > And use it from the following ML program:
> >
> >
> >
> > mlmain.ml:
> >
> > let main use_inout =
> >
> >   let cows =
> >
> >     if use_inout then Cow.get_cows_inout(Array.create 3
> > (Cow.get_dummy_cow()))
> >
> >     else Cow.get_cows()
> >
> >   in
> >
> >   Array.iter Cow.print_cow cows
> >
> >
> >
> > let _ = main true;
> >
> >
> >
> > This works fine.  However, if I change the call to main to 'main false'  I
> > get a crash.
> >
> >
> >
> > Thanks,
> >
> >
> >
> > -        Jakob
> >
> >
> >
> > PS. I know that I am leaking memory - that I can fix with a simple
> > quote(dealloc, "free(*cows);");
> > _______________________________________________
> > Caml-list mailing list. Subscription management:
> > http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
> > Archives: http://caml.inria.fr
> > 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] FW: CamlIDL: Returning a whole array of cows
  2007-11-05 21:28     ` Christopher L Conway
@ 2007-11-05 21:35       ` Jakob Lichtenberg
  0 siblings, 0 replies; 5+ messages in thread
From: Jakob Lichtenberg @ 2007-11-05 21:35 UTC (permalink / raw)
  To: Christopher L Conway; +Cc: caml-list

Christopher,

I probably added to the confusion by providing get_cows_inout in the first place :-)

Let me clarify: I am interested in camlidl exposing the function:

  val get_cows : unit -> cow array

My included get_cows_inout simply demonstrate my current workaround where I hack the cows API, but the ML code that use get_cows_inout is incredibly ugly.

Thanks,

- Jakob


-----Original Message-----
From: christopherleeconway@gmail.com [mailto:christopherleeconway@gmail.com] On Behalf Of Christopher L Conway
Sent: Monday, November 05, 2007 1:28 PM
To: Jakob Lichtenberg
Cc: caml-list@inria.fr
Subject: Re: [Caml-list] FW: CamlIDL: Returning a whole array of cows

Jakob,

Sorry for the confusion: my suggestion was for your get_cows_inout
function (where the integer input constrains the length of the
output). For get_cows, just use:

[size_is(*len)] cow *get_cows([ignore] int* len);

Regards,
Chris

On 11/5/07, Jakob Lichtenberg <jakobl@windows.microsoft.com> wrote:
> Christopher,
>
> Thanks for the immediate reply,
>
> Even if I can change the interface, you suggestion provides an ML API with the wrong ML type:
>   val get_cows : int -> cow array
>
> I want a type:
>   val get_cows : unit -> cow array
>
> Why: The ML user has no idea how many cows will be returned and can hence not be expected to provide this as an argument!
>
> Thanks,
>
> - Jakob
>
> -----Original Message-----
> From: christopherleeconway@gmail.com [mailto:christopherleeconway@gmail.com] On Behalf Of Christopher L Conway
> Sent: Monday, November 05, 2007 12:51 PM
> To: Jakob Lichtenberg
> Cc: caml-list@inria.fr
> Subject: Re: [Caml-list] FW: CamlIDL: Returning a whole array of cows
>
> Jakob,
>
> I sent out pretty much the same question to the list just last week
> and also didn't get a satisfactory answer (see here:
> http://caml.inria.fr/pub/ml-archives/caml-list/2007/10/efb73229fa177fb413e663a2c1ad28b4.en.html).
>  It seems that when you add a size_is annotation to a parameter, the
> size is treated as a pre-condition, not as a post-condition. If you
> have the freedom to change the C API, you might try:
>
> [size_is(*outputlen)] cow *get_cows_inout([in] int inputlen, [ignore]
> int *outputlen);
>
> IIRC, this will give you the correct behavior. The alternative is
> hand-code the wrapper.
>
> Regards,
> Chris
>
> On 11/5/07, Jakob Lichtenberg <jakobl@windows.microsoft.com> wrote:
> >
> >
> >
> >
> > Resending due to no answer.
> >
> >
> >
> > - Jakob
> >
> >
> >
> >
> >
> > From: Jakob Lichtenberg
> >  Sent: Monday, September 17, 2007 1:11 PM
> >  To: 'caml-list@inria.fr'
> >  Subject: CamlIDL: Returning a whole array of cows
> >
> >
> >
> > 1. Summary: Stub code generated by Camlidl seems to call camlidl_malloc with
> > an uninitialized size.
> >
> >
> >
> >
> >
> > 2. Details:
> >
> >
> >
> > I am declaring a function 'void get_cows([out] int* len, [length_is(*len),
> > size_is(*len), out] cow** cows);' that creates and returns an array of cows.
> >  (Each cow is just a pointer to a structure.)  The generated stub code seems
> > incorrect:
> >
> >
> >
> > cow_stubs.c:
> >
> > value camlidl_cow_get_cows(value _unit)
> >
> > {
> >
> >   int *len; /*out*/
> >
> >   cow **cows; /*out*/
> >
> >   int _c1;
> >
> >   mlsize_t _c2;
> >
> >   value _v3;
> >
> >   value _vres;
> >
> >
> >
> >   struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL };
> >
> >   camlidl_ctx _ctx = &_ctxs;
> >
> >   len = &_c1;
> >
> >   cows = camlidl_malloc(*len * sizeof(cow *), _ctx);
> >
> >   get_cows(len, cows);
> >
> >   _vres = camlidl_alloc(*len, 0);
> >
> >   Begin_root(_vres)
> >
> >     for (_c2 = 0; _c2 < *len; _c2++) {
> >
> >       _v3 = camlidl_c2ml_cow_cow(&*cows[_c2], _ctx);
> >
> >       modify(&Field(_vres, _c2), _v3);
> >
> >     }
> >
> >   End_roots()
> >
> >   camlidl_free(_ctx);
> >
> >   return _vres;
> >
> > }
> >
> >
> >
> > As you can see camlidl_malloc is called with an uninitialized value.
> >
> >
> >
> > Is this a bug in camlidl, or am I writing my IDL file incorrectly.  Another
> > way to ask:  How do I declared that a function reserves an array
> >
> >
> >
> >
> >
> > 3. Implementation details:
> >
> >
> >
> > This is my C api I'd like to access from ocaml:
> >
> >
> >
> > cow.h:
> >
> > typedef struct _cow {
> >
> >   char* name;
> >
> >   int age;
> >
> > } *cow;
> >
> >
> >
> > cow get_dummy_cow();
> >
> >
> >
> > void get_cows_inout(int inputlen, int *outputlen, cow ca[]); // Write cows
> > to 'ca', however not more than 'inputlen' elements.  Write number of cows
> > written to '*outputlen'.
> >
> >
> >
> > void get_cows(int* len, cow **ca); // Malloc array for cows.  Save number of
> > elements to *len, save address for array in '*ca'.
> >
> >
> >
> > void print_cow(cow o);
> >
> >
> >
> > I'd like to access this API from OCaml using CamlIDL.  I use the following
> > idl file:
> >
> >
> >
> > cow.idl:
> >
> > typedef [abstract] void* cow;
> >
> >
> >
> > [pointer_default(ref)] interface Cow {
> >
> >
> >
> > cow get_dummy_cow(void);
> >
> >
> >
> > void get_cows_inout([in] int inputlen, [out] int * outputlen,
> >
> >
> > [in,out,size_is(inputlen),length_is(*outputlen)] cow d[]);
> >
> >
> >
> > void get_cows([out] int* len, [length_is(*len), size_is(*len), out] cow**
> > cows);
> >
> >
> >
> > void print_cow(cow o);
> >
> >
> >
> > }
> >
> >
> >
> > I compile this using:
> >
> >
> >
> >                 camlidl cow.idl
> >
> >
> >
> > And use it from the following ML program:
> >
> >
> >
> > mlmain.ml:
> >
> > let main use_inout =
> >
> >   let cows =
> >
> >     if use_inout then Cow.get_cows_inout(Array.create 3
> > (Cow.get_dummy_cow()))
> >
> >     else Cow.get_cows()
> >
> >   in
> >
> >   Array.iter Cow.print_cow cows
> >
> >
> >
> > let _ = main true;
> >
> >
> >
> > This works fine.  However, if I change the call to main to 'main false'  I
> > get a crash.
> >
> >
> >
> > Thanks,
> >
> >
> >
> > -        Jakob
> >
> >
> >
> > PS. I know that I am leaking memory - that I can fix with a simple
> > quote(dealloc, "free(*cows);");
> > _______________________________________________
> > Caml-list mailing list. Subscription management:
> > http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
> > Archives: http://caml.inria.fr
> > 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

end of thread, other threads:[~2007-11-05 21:35 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-11-05 18:31 FW: CamlIDL: Returning a whole array of cows Jakob Lichtenberg
2007-11-05 20:50 ` [Caml-list] " Christopher L Conway
2007-11-05 21:20   ` Jakob Lichtenberg
2007-11-05 21:28     ` Christopher L Conway
2007-11-05 21:35       ` Jakob Lichtenberg

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