caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Gabriel Scherer <gabriel.scherer@gmail.com>
To: Joel Reymont <joelr1@gmail.com>
Cc: Goswin von Brederlow <goswin-v-b@web.de>, caml-list@inria.fr
Subject: Re: [Caml-list] using modules to wrap c++ classes
Date: Thu, 3 May 2012 16:27:51 +0200	[thread overview]
Message-ID: <CAPFanBGgwsrNXSTO-5vGzoKk3cT=+8dnY9yBeqq0b5FgHW4H-Q@mail.gmail.com> (raw)
In-Reply-To: <CAOQwdX25S6Wjmf=g8f19cyvx6rUYxGEmGwFnUCNn612CvxmJFA@mail.gmail.com>

It looks like this callback pattern does not use recursion through
this/self, but is only one standard way to build closures and
callbacks. The most natural way to expose this to OCaml would be to
allow the OCaml programmer to simply use a first-class function
instead of this callback. I see two possible solutions:

(1) You could define, on the C++ side, a generic GenericAdmCallbacks
class whose constructor would take as parameter a function pointer
implementing Alert (so the function itself only does the plumbing).
Then you can expose this class as an OCaml abstract type, and wrap its
constructor to expose it to OCaml, so that it takes ocaml-land
callbacks and return the abstract type. You can then expose to OCaml
your function manipulating AdmCallbacks (let's call it
"call_me_later"). So you would have an OCaml interface like this

  let callback : abstract_admcallbacks = amdcallback (fun p_info
p_context ai_code -> ...)
  call_me_later callback

(2) You can put that wrapping logic in the wrapper for call_me_later
directly (take an ocaml function, builds the GenericAdmCallbacks, and
pass it to the underlying C++ function)

   call_me_later (fun p_info p_context ai_code -> ....)

If the AmdCallbacks interface really is as simple as you've shown, the
latter technique is the most convenient. If callbacks have a richer
interface (eg. your C++ API expose functions to build callbacks from
other callbacks), you'll need a type to speak about callbacks, so the
first option is better.

(I think I'd go for (1): you can still re-wrap amdcallback into a more
convenient form on the ocaml-land, so that you have as little wrapping
logic as possible in the unsafe C++ wrapping layer.)

On Thu, May 3, 2012 at 3:56 PM, Joel Reymont <joelr1@gmail.com> wrote:
> Say I have a library class AdmCallbacks
>
> class AdmCallbacks
>     {
>     public :
>     AdmCallbacks();
>     virtual ~AdmCallbacks();
>
>     /*   ----------------------------------------------------------------   */
>
>     virtual int Alert(AlertInfo * pInfo,
>                       void *      pContext,
>                       int *       aiCode) = 0;
>
>     private :
>     };
>
> I subclass it and implement the Alert method to receive notifications.
>
> I then create an instance of my derived class and pass it to some
> initialization function so that the API knows to call the methods of
> my instance.
>
> My derived class may look like this
>
> class MyAdmCallbacks: public AdmCallbacks
>     {
>     public :
>     MyAdmCallbacks()  {};
>     ~MyAdmCallbacks() {};
>
>     /*   ----------------------------------------------------------------   */
>
>     virtual int Alert(AlertInfo * pInfo,
>                       void *      pContext,
>                       int *       aiCode);
>     };
>
> int MyAdmCallbacks::Alert(AlertInfo * pInfo,
>                          void *      pContext,
>                          int *       aiCode)
>     {
>     int iIgnored;
>
>     /*   ----------------------------------------------------------------   */
>
>     cout << endl << endl;
>     if (!pInfo -> dump(&iIgnored))
>          {
>          cout << "error in pInfo -> dump : " << iIgnored << endl;
>          }
>
>     /*   ----------------------------------------------------------------   */
>
>     *aiCode = API_OK;
>     return (OK);
>     }
>
> Now, suppose I want to implement the derived class on the OCaml side.
>
> What is the best way to do it?
>
> I can derive on the C++ side, keep a pointer to the OCaml instance
> (self) in a member variable, instantiate MyAdmCallbacks in the
> "MyAdmCallbacks_new" stub function which takes the OCaml self and then
> set the member variable.
>
> The Alert method on the C++ side would then dispatch to OCaml using
> the stored OCaml self to call the Alert method as per 18.3.5 of the
> manual
>
> callback(caml_get_public_method(foo, hash_variant("bar")), foo);
>
> Is there a better way to implement this on the OCaml side?
>
>    Thanks, Joel
>
> --------------------------------------------------------------------------
> Working on AlgoKit, a new algorithmic trading platform using Rithmic R|API
> ---------------------+------------+---------------------------------------
> http://wagerlabs.com | @wagerlabs | http://www.linkedin.com/in/joelreymont
> ---------------------+------------+---------------------------------------
>
> --
> Caml-list mailing list.  Subscription management and archives:
> https://sympa-roc.inria.fr/wws/info/caml-list
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs
>


  reply	other threads:[~2012-05-03 14:28 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-05-03 12:22 Joel Reymont
2012-05-03 13:35 ` Goswin von Brederlow
2012-05-03 13:56   ` Joel Reymont
2012-05-03 14:27     ` Gabriel Scherer [this message]
2012-05-03 15:02       ` Joel Reymont
2012-05-03 18:41         ` Joel Reymont
2012-05-03 19:20           ` Joel Reymont
2012-05-04  8:43           ` Goswin von Brederlow
2012-05-04 17:23             ` Joel Reymont
2012-05-05 12:39               ` Goswin von Brederlow
2012-05-05 14:11                 ` Joel Reymont

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='CAPFanBGgwsrNXSTO-5vGzoKk3cT=+8dnY9yBeqq0b5FgHW4H-Q@mail.gmail.com' \
    --to=gabriel.scherer@gmail.com \
    --cc=caml-list@inria.fr \
    --cc=goswin-v-b@web.de \
    --cc=joelr1@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).