From mboxrd@z Thu Jan 1 00:00:00 1970 Received: (from weis@localhost) by pauillac.inria.fr (8.7.6/8.7.3) id TAA08407 for caml-redistribution; Thu, 17 Apr 1997 19:37:10 +0200 (MET DST) Received: from nez-perce.inria.fr (nez-perce.inria.fr [192.93.2.78]) by pauillac.inria.fr (8.7.6/8.7.3) with ESMTP id QAA04891 for ; Thu, 17 Apr 1997 16:28:44 +0200 (MET DST) Received: from relay2.eunet.fr (relay2.EUnet.fr [192.134.192.149]) by nez-perce.inria.fr (8.7.6/8.7.3) with SMTP id QAA24700 for ; Thu, 17 Apr 1997 16:28:36 +0200 (MET DST) Received: from dassav (dassav.dassault-aviation.fr) by relay2.eunet.fr (5.65c8d/96.05.03) via EUnet-France id AA20230; Thu, 17 Apr 1997 16:27:50 +0200 (MET) Received: from fnet-ia1.dassault-aviation.fr by dassav (5.x/SMI-SVR4) id AA10623; Thu, 17 Apr 1997 16:26:17 +0200 Received: from fnet-ia1 (localhost) by fnet-ia1.dassault-aviation.fr (5.x/SMI-SVR4) id AA07829; Thu, 17 Apr 1997 16:33:41 +0200 Message-Id: <335634C4.2D49@dassault-aviation.fr> Date: Thu, 17 Apr 1997 16:33:40 +0200 From: Thierry Bravier Organization: Dassault Aviation DGT/DTN/ELO/EAV X-Mailer: Mozilla 2.01 (X11; I; SunOS 5.4 sun4c) Mime-Version: 1.0 To: caml-list@inria.fr Cc: Vincent Subject: Re: Interfacing C++ code with O'Caml References: <3355063C.A7A@parc.anglia.ac.uk> Sender: weis Vincent wrote: > I am trying to interface C++ code with O'Caml and > I've noticed a mail from Christopher Jeris on > Fri, 6 Dec 1996 about O'Caml/C++ interfacing. > > This looks a bit tricky and I just wonder if > O'Caml current version includes C++ interfacing > facilities (or if we could expect O'Caml next releases > to do so). Thierry Bravier Dassault Aviation - DGT / DTN / ELO / EAV 78, Quai Marcel Dassault F-92214 Saint-Cloud Cedex - France Telephone : (33) 01 47 11 53 07 Telecopie : (33) 01 47 11 52 83 E-Mail : mailto:bravier@dassault-aviation.fr #============================================================================== # File: README # Language: fundamental # Author: Thierry Bravier # Time-stamp: <97/04/17 15:11:37 tb> # Created: 97/04/17 14:57:38 tb #============================================================================== Dear caml community, I also have interest in interfacing Ocaml with C/C++. First, thanks to Xavier Leroy and to the whole ocaml team for making ocaml available. Here is a small contribution that might be useful to C++ programmers. These files include a C++ minimal API to ML values. #------------------------------------------------------------------------------ README: This file. #------------------------------------------------------------------------------ Makefile: Edit CXX variable to use your C++ compiler. #------------------------------------------------------------------------------ ML.hh ML.cc: C++ API Features are: A ML class emulating the standard ocaml `value' type. ML objects are a kind of `smart' value since they are useable as any other type variable conforming to ocaml GC checking in and out protocol. a ML should be useable wherever a standard ocaml `value' is, thanks to a cast operator. Named values can be used through a name to ML constructor. Callbacks are there too. They are to be used with the functional call operator. #------------------------------------------------------------------------------ ML_cc.cc: The C++ main of a test program for the API. (main () is there). #------------------------------------------------------------------------------ ML_ml.ml: The ML part of the test program. #------------------------------------------------------------------------------ The output of the test program is: 15:00:49 ocaml+C++> ML_cc Begin Middle x = 10 x = 20 x = 30 x = 40 End #------------------------------------------------------------------------------ Remarks: This is really a minimal API. I began thinking of how ML exceptions could be handled (I think mlraise() should be available to the C API) and it seems to be tricky, especially if you nest C++ calls in ML and ML calls in C++. It is even worse if you intend to try/catch C++ exceptions in ML and try/with ML exceptions in C++. The first difficulty is that, outside ML::init()/::caml_startup(), ML exceptions are not catchable allowing the user to call later a registered ML closure raising a fatal ML exception. Althouh this first version does not try to handle exceptions it still can be used (provided you garantee no ML exception will be raised outside startup). All suggestions are welcome as usual. Thierry Bravier Dassault Aviation - DGT / DTN / ELO / EAV 78, Quai Marcel Dassault F-92214 Saint-Cloud Cedex - France Telephone : (33) 01 47 11 53 07 Telecopie : (33) 01 47 11 52 83 E-Mail : mailto:bravier@dassault-aviation.fr #============================================================================== #============================================================================== # File: Makefile # Language: make # Author: Thierry Bravier # Time-stamp: <97/04/17 14:22:24 tb> # Created: 97/04/17 14:21:17 tb #============================================================================== OCAMLC=ocamlc STDLIB=/logiciel/ML/ocaml/stdlib # C++ compiler: g++ or CC CXX=g++ CCC=$(CXX) CXXFLAGS= CCFLAGS=$(CXXFLAGS) CPPFLAGS=-I$(STDLIB) LDFLAGS=-L$(STDLIB) LDLIBS=-lcamlrun -ltermlib #============================================================================== OBJ=ML.o ML_ml.o ML_cc.o #============================================================================== ML_cc: $(OBJ) $(LINK.cc) -o $@ $(OBJ) $(LDLIBS) ML_ml.o: ML_ml.ml $(OCAMLC) -custom -output-obj -o $@ ML_ml.ml ML.o: ML.cc ML.hh $(COMPILE.cc) ML.cc ML_cc.o: ML_cc.cc ML.hh $(COMPILE.cc) ML_cc.cc #============================================================================== // ============================================================================ // File: ML.hh // Language: c++ // Author: Thierry Bravier // Time-stamp: <97/04/17 14:37:13 tb> // Created: 97/03/10 10:55:26 tb // ============================================================================ #ifndef ML_HH #define ML_HH // ============================================================================ extern "C" { #include } // ============================================================================ class ML { public: static void init (char ** argv); ~ML (void); // delete ML ML (const value& v); // ML from value ML (const char *name); // ML from named value ML& operator = (const ML& rhs); // assignment operator value (void) const; // convert ML to value value operator () (void) const; // callback0 value operator () (value v1) const; // callback1 value operator () (value v1, value v2) const; // callback2 value operator () (value v1, value v2, value v3) const; // callback3 private: value _value; }; // ============================================================================ #endif /* ML_HH */ // ============================================================================ // ============================================================================ // File: ML.cc // Language: c++ // Author: Thierry Bravier // Time-stamp: <97/04/17 14:37:39 tb> // Created: 97/03/10 10:55:26 tb // ============================================================================ extern "C" { #include #include #include } // ---------------------------------------------------------------------------- #include #include #include "ML.hh" // ============================================================================ // init // ============================================================================ static int ready = 0; static void get_ready (char **argv) { if (!ready) { ready = 1; ::caml_startup (argv); } } static void must_be_ready (void) { if (!ready) { cerr << "ML not initialized" << endl; ::exit (1); } } // ---------------------------------------------------------------------------- static value new_root (value *pv, value v) { must_be_ready (); ::register_global_root (pv); return *pv = v; } static void delete_root (value *pv) { must_be_ready (); ::remove_global_root (pv); } static value named_value (const char *name) { must_be_ready (); return *::caml_named_value ((char*) name); } // ---------------------------------------------------------------------------- void ML::init (char **argv) { get_ready (argv); } // ============================================================================ // ML // ============================================================================ ML::~ML (void) { delete_root (&_value); } // ---------------------------------------------------------------------------- ML::ML (const value& v) : _value (new_root (&_value, v)) {} ML::ML (const char *s) : _value (new_root (&_value, named_value (s))) {} // ---------------------------------------------------------------------------- ML& ML::operator = (const ML& rhs) { if (this != &rhs) { delete_root (&_value); _value = new_root (&_value, rhs); } return *this; } // ---------------------------------------------------------------------------- ML::operator value (void) const { return _value; } // ---------------------------------------------------------------------------- value ML::operator () (void) const { return ::callback (*this, Val_unit); } value ML::operator () (value v1) const { return ::callback (*this, v1); } value ML::operator () (value v1, value v2) const { return ::callback2 (*this, v1, v2); } value ML::operator () (value v1, value v2, value v3) const { return ::callback3 (*this, v1, v2, v3); } // ============================================================================ // ============================================================================ // File: ML_cc.cc // Language: c++ // Author: Thierry Bravier // Time-stamp: <97/04/17 14:24:56 tb> // Created: 97/03/10 10:55:26 tb // ============================================================================ #include #include "ML.hh" // ============================================================================ main (int, char **argv) { cout << "Begin" << endl; ML::init (argv); cout << "Middle" << endl; { ML foo = "foo"; ML bar = "bar"; foo (bar); } cout << "End" << endl; } // ============================================================================ (* ============================================================================ * File: ML_ml.ml * Language: caml * Author: Thierry Bravier * Time-stamp: <97/04/17 13:49:19 tb> * Created: 97/03/12 18:08:00 tb * ========================================================================= *) open Callback open Printf (* ========================================================================= *) let _ = begin Callback.register "foo" (List.iter (fun x -> printf "\tx = %d\n" x; flush stdout)); Callback.register "bar" [10; 20; 30; 40] end (* ========================================================================= *)