From: Thomas Fischbacher <Thomas.Fischbacher@Physik.Uni-Muenchen.DE>
To: caml-list@inria.fr
Subject: C Callback issues
Date: Wed, 23 Nov 2005 13:59:49 +0100 (CET) [thread overview]
Message-ID: <Pine.LNX.4.61.0511231319580.19523@eiger.cip.physik.uni-muenchen.de> (raw)
Hello all,
suppose I have a C library which provides functionality via registering C
callbacks that take a closure parameter. For the sake of this example,
let's say via set_foo_callback(void (*f)(void *),void *closure_param).
Now, if I want to lift this to the OCaml level by writing a C
callback-wrapper which will use the closure arg to pass the OCaml
function to be called, I encounter a slight problem:
Callbacks have to be "announced globally" to C by means of
Callback.register. Now, if I want to use callbacks not only for internal
purposes in my ML wrapper library, but allow the user of that library to set
callbacks into his own code, the situation is as follows:
Ideally, it would be most convenient if the user could just use the
set_foo_callback ML variant of the equally named C function and provide a
ML function as callback. This will then be registered on the fly with
Callback.register and a gensym-ed name if necessary, and then passed on to
the C side.
The problem with this is the "if necessary" part. I do not really mind the
issue of callback closures becoming non-GC-able, as we will typically
only see at most about 100 of them in practically all reasonable programs.
However, I definitely want to avoid callback-registering the same closure
more than once, as I can imagine situations where the user wants to
switch many times between a small set of different callback functions.
So, what I need for this approach is a way to find out reasonably fast
whether a callback closure has been registered before.
One way to do this would be to keep all registered callbacks in an
associative list, which is scanned for (==) same-ness whenever a new
callback has to be registered. A nicer approach would be to use a hash
table, but here we run into the problem that OCaml does not support proper
EQ hash tables, and the "workaround" suggested earlier by Xavier does not
work with functions. Certainly, if on the C side, caml_name_value() is
implemented in such a way (I don't know) that it has to do an O(N) list
search instead of a table lookup, there would be no point in trying to
improve this by using a hash for the Caml-side lookup. Anyway, I think
this is just another indication that there are situations where EQ hash
tables really are needed.
Right now, I solved this probem in such a way that I split the
callback-registering phase off the callback-setting function:
I introduced a foo_callback type, which is passed into set_foo_callback,
and the user has to use register_foo_callback to map a ML function to a
foo_callback. Then it's up to him not to re-register the same function
many times as a callback. But somehow, it just does not feel right having
to annoy the user of the library with such details, just because of some
unrelated obscure OCaml limitaion (no EQ hash tables) that requires that
particular kind of design.
One may indeed argue that the approach I implemented in the end might be
the cleaner one. I somewhat doubt this, as it should eventually become
possible to completely shield the end user from low-level details such as
that somewhere deep in my ocaml library, it has to register C->Caml
callbacks. And as I said, it just does not feel right to have language
quirks dictate the design to such an extent.
Another minor issue: the documentation of the callbackN function should
maybe state more explicitly that the args parameter is of type
values[] args, and not a ML vector.
(Yes, one may infer this from the presence of the "number of arguments"
parameter, which would be spurious if it were a ML vector, but
nevertheless.)
--
regards, tf@cip.physik.uni-muenchen.de (o_
Thomas Fischbacher - http://www.cip.physik.uni-muenchen.de/~tf //\
(lambda (n) ((lambda (p q r) (p p q r)) (lambda (g x y) V_/_
(if (= x 0) y (g g (- x 1) (* x y)))) n 1)) (Debian GNU)
next reply other threads:[~2005-11-23 12:59 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-11-23 12:59 Thomas Fischbacher [this message]
2005-11-23 13:40 ` [Caml-list] " Olivier Andrieu
2005-11-23 14:11 ` Thomas Fischbacher
2005-11-23 13:41 ` Alain Frisch
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=Pine.LNX.4.61.0511231319580.19523@eiger.cip.physik.uni-muenchen.de \
--to=thomas.fischbacher@physik.uni-muenchen.de \
--cc=caml-list@inria.fr \
/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