caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Xavier Leroy <Xavier.Leroy@inria.fr>
To: Tim Leek <trleek@gmail.com>
Cc: caml-list@inria.fr
Subject: Re: [Caml-list] C wrappers for Ocaml functions
Date: Tue, 14 Apr 2009 16:40:10 +0200	[thread overview]
Message-ID: <49E4A04A.5050701@inria.fr> (raw)
In-Reply-To: <9af41d0e0904140451l5a3a0207vb5bd7532a35bbc4e@mail.gmail.com>

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

> So I am investigating packing my nice Ocaml code into a library and
> writing C bindings so that I can talk to it. [...]
> In particular, I have found
> none that cover how to obtain pointers to OCaml function return values
> that are not strings or ints, how to store them in C-land, and how to pass
> them back to Ocaml as parameters.

You have two choices: copy the contents of the OCaml data structure to
a C data structure, e.g. an OCaml tuple or record of ints can be
copied to a C struct, field by field; or, treat the OCaml value as an
opaque type on C's side.

The code you posted attempts to do the second approach, but you cannot
just take a Caml "value" and give it to arbitrary C code: the Caml GC
will lose track of the value and reclaim it (or copy it elsewhere) at
the first opportunity.

Instead, you need to wrap the Caml value in a C memory block and
register it with the GC using caml_register_global_root.  Then, an
explicit free function must be provided in the C interface to
unregister with the GC and to free the wrapper.  See the
attached modification of your ht_wrap.c example.  It should put you on
the right tracks.

> 5. And this is how I am attempting to compile it.  Note that error I'm
> getting here is in link.  If I add "-lm" it gets less noisy but still is
> mad at me. Why am I having to add math library?

Because the Caml runtime system needs it.  As Dmitry wrote, the
simplest way to build your example is:

ocamlopt -output-obj -o ht_lib.o ht.ml
ocamlopt -c ht_wrap.c
gcc -o htt ht_test.c ht_lib.o ht_wrap.o -L`ocamlopt -where` -lasmrun -lcurses -lm

Hope this helps,

- Xavier Leroy

[-- Attachment #2: ht_wrap.c --]
[-- Type: text/x-c, Size: 1381 bytes --]

#include <caml/mlvalues.h>
#include <caml/callback.h>
#include <caml/alloc.h>
#include <caml/memory.h>

#include "ht.h"

struct hashtable {
  value v;
};

static struct hashtable * ht_alloc (value v)
{
  struct hashtable * wrapper = malloc(sizeof(struct hashtable));
  if (wrapper == NULL) return NULL;
  wrapper->v = v;
  caml_register_global_root(&(wrapper->v));
  return wrapper;
}

void ht_free (struct hashtable * ht)
{
  caml_remove_global_root(&(ht->v));
  free(ht);
}

struct hashtable * ht_create (void) {
 static value *create_closure = NULL;
 if (create_closure == NULL)
   create_closure = caml_named_value("create");
 return ht_alloc(caml_callback(*create_closure, Val_unit));
}

void ht_add (struct hashtable * ht, char *key, int val) {
 static value *add_closure = NULL;
 if (add_closure == NULL)
   add_closure = caml_named_value("add");
 caml_callback3(*add_closure, ht->v, caml_copy_string(key), Val_int(val));
}

void ht_mem (struct hashtable * ht, char *key) {
 static value *mem_closure = NULL;
 if (mem_closure == NULL)
   mem_closure = caml_named_value("mem");
 caml_callback2(*mem_closure, ht->v, caml_copy_string(key));
}

void ht_remove (struct hashtable * ht, char *key) {
 static value *remove_closure = NULL;
 if (remove_closure == NULL)
   remove_closure = caml_named_value("remove");
 caml_callback2(*remove_closure, ht->v, caml_copy_string(key));
}

      parent reply	other threads:[~2009-04-14 14:40 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-04-14 11:51 Tim Leek
2009-04-14 14:06 ` [Caml-list] " Dmitry Bely
2009-04-14 14:40 ` Xavier Leroy [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=49E4A04A.5050701@inria.fr \
    --to=xavier.leroy@inria.fr \
    --cc=caml-list@inria.fr \
    --cc=trleek@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).