caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* Interfacing C++ code with O'Caml
@ 1997-04-16 17:02 Vincent
  1997-04-17 14:33 ` Thierry Bravier
  0 siblings, 1 reply; 2+ messages in thread
From: Vincent @ 1997-04-16 17:02 UTC (permalink / raw)
  To: caml-list

Hi,

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

	Thanks a lot.

	Vincent.


-- 
______________________________________________________________

  Vincent B.G.Leleu
  Parallel Computing Research Centre
  Anglia Polytechnic University
  Victoria Rd. South, Chelmsford
  Essex CM1 1JJ
  England

  E-Mail : vincent@parc.anglia.ac.uk
  URL    : http://www.parc.anglia.ac.uk/~vincent
  Phone  : +44 1245 493131 ext. 3416
  Fax    : +44 1245 495263 - PARC
  Pager  : +44 1426 634330 (phone numbers only)





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

* Re: Interfacing C++ code with O'Caml
  1997-04-16 17:02 Interfacing C++ code with O'Caml Vincent
@ 1997-04-17 14:33 ` Thierry Bravier
  0 siblings, 0 replies; 2+ messages in thread
From: Thierry Bravier @ 1997-04-17 14:33 UTC (permalink / raw)
  To: caml-list; +Cc: Vincent

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 <caml/mlvalues.h>
}

// ============================================================================
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 <caml/mlvalues.h>
#include <caml/memory.h>
#include <caml/callback.h>
}

// ----------------------------------------------------------------------------
#include <iostream.h>
#include <stdlib.h>

#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 <iostream.h>

#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

(* ========================================================================= *)





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

end of thread, other threads:[~1997-04-17 17:37 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1997-04-16 17:02 Interfacing C++ code with O'Caml Vincent
1997-04-17 14:33 ` Thierry Bravier

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