Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[Caml-list] linking errors involving cpp files

10 views
Skip to first unread message

Aaron Bohannon

unread,
Dec 15, 2009, 12:09:44 AM12/15/09
to OCaml List
Hi,

How do I link C++ code with OCaml? Let's say I have a main program in
C/C++ and a function I want to call in OCaml:

---- main.c / main.cpp ---
#include <caml/mlvalues.h>
#include <caml/memory.h>
#include <caml/callback.h>
int main (int argc, char ** argv) {
char * caml_argv[argc + 1];
int i;
for (i = 0; i < argc + 1; i++) caml_argv[i] = argv[i];
caml_argv[argc] = NULL;
caml_main (caml_argv);
return 0;
}
--------

---- test.ml ----
let f x = x + 1
let () = Callback.register "test" f
--------

If I name the main program "main.c", I can compile the code like this
with no trouble whatsoever:

gcc -I /opt/local/lib/ocaml -c main.c
ocamlopt -o main test.cmx main.o

If I name the main program "main.cpp", and run the same commands---

gcc -I /opt/local/lib/ocaml -c main.cpp
ocamlopt -o main test.cmx main.o

---then I get this:

Undefined symbols:
"_caml_atom_table", referenced from:
_intern_alloc in libasmrun.a(intern.o)
_intern_rec in libasmrun.a(intern.o)
_caml_alloc in libasmrun.a(alloc.o)
_caml_alloc_dummy_float in libasmrun.a(alloc.o)
_caml_alloc_dummy in libasmrun.a(alloc.o)
_caml_alloc_array in libasmrun.a(alloc.o)
"___gxx_personality_v0", referenced from:
_main in main.o
CIE in main.o
"_caml_code_area_start", referenced from:
_extern_rec in libasmrun.a(extern.o)
_extern_rec in libasmrun.a(extern.o)
_segv_handler in libasmrun.a(signals_asm.o)
_caml_code_checksum in libasmrun.a(intern.o)
_intern_rec in libasmrun.a(intern.o)
"_caml_code_area_end", referenced from:
_extern_rec in libasmrun.a(extern.o)
_segv_handler in libasmrun.a(signals_asm.o)
_caml_code_checksum in libasmrun.a(intern.o)
"caml_main(char**)", referenced from:
_main in main.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
File "caml_startup", line 1, characters 0-1:
Error: Error during linking


Now I know gcc does something slightly different with cpp files, and I
can eliminate the complaint about the __gxx symbol if I add "-cclib
-lstdc++" (which I fully expected to need working with C++ programs).
But why are the caml symbols missing!?!? (It took me over 2 hours to
figure out it was the "cpp" extension that was the root of these
missing caml symbols in my real program because that was the *last*
thing I expected.) I'm using OCaml 3.11.1 on OS X 10.6.2.

- Aaron

_______________________________________________
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs

Robert Roessler

unread,
Dec 15, 2009, 2:01:20 AM12/15/09
to Aaron Bohannon, OCaml List
Aaron Bohannon wrote:
> How do I link C++ code with OCaml? Let's say I have a main program in
> C/C++ and a function I want to call in OCaml:
>
> ---- main.c / main.cpp ---
> #include<caml/mlvalues.h>
> #include<caml/memory.h>
> #include<caml/callback.h>
> int main (int argc, char ** argv) {
> char * caml_argv[argc + 1];
> int i;
> for (i = 0; i< argc + 1; i++) caml_argv[i] = argv[i];
> caml_argv[argc] = NULL;
> caml_main (caml_argv);
> return 0;
> }
> --------
>...

> ---then I get this:
>
> Undefined symbols:

You might try (when mixing C++ and OCaml) wrapping the whole thing in an
'extern "C" {...}' block (*including* the #includes and the entire main
function).

Robert Roessler

Aaron Bohannon

unread,
Dec 15, 2009, 8:50:44 AM12/15/09
to Robert Roessler, OCaml List
On Tue, Dec 15, 2009 at 1:59 AM, Robert Roessler <roes...@rftp.com> wrote:
> Aaron Bohannon wrote:
>>
>> How do I link C++ code with OCaml?

> You might try (when mixing C++ and OCaml) wrapping the whole thing in an


> 'extern "C" {...}' block (*including* the #includes and the entire main
> function).

Thanks for the tip. This does resolve the missing caml symbols (even
when naming the file with a cpp extension). However, my real program
actually uses some C++ features. I think I could convert it to a real
C program, but I assumed there would be some other way.

- Aaron

Mark Shinwell

unread,
Dec 15, 2009, 9:00:13 AM12/15/09
to Aaron Bohannon, caml...@inria.fr
On Tue, Dec 15, 2009 at 08:50:33AM -0500, Aaron Bohannon wrote:
> On Tue, Dec 15, 2009 at 1:59 AM, Robert Roessler <roes...@rftp.com> wrote:
> > Aaron Bohannon wrote:
> >>
> >> How do I link C++ code with OCaml?
>
> > You might try (when mixing C++ and OCaml) wrapping the whole thing in an
> > 'extern "C" {...}' block (*including* the #includes and the entire main
> > function).
>
> Thanks for the tip. This does resolve the missing caml symbols (even
> when naming the file with a cpp extension). However, my real program
> actually uses some C++ features. I think I could convert it to a real
> C program, but I assumed there would be some other way.

I suspect it will work if only the #include directives pertaining to Caml
header files are marked as 'extern "C"'. You just need to tell the compiler to
use the C linkage convention rather than the C++ name mangling convention for
the external Caml functions that your program (implicitly or explicitly) calls.
This is done at the function prototype site, not the call site. Everything
else in the program should be unaffected.

Xavier, could the headers have the guards added? (I only spot-checked one,
mlvalues.h, and that didn't appear to have it).

Mark

Jan Kybic

unread,
Dec 15, 2009, 9:50:18 AM12/15/09
to Aaron Bohannon, OCaml List
On Tue, Dec 15, 2009 at 2:50 PM, Aaron Bohannon <boha...@cis.upenn.edu> wrote:
>
> Thanks for the tip. �This does resolve the missing caml symbols (even
> when naming the file with a cpp extension). �However, my real program
> actually uses some C++ features. �I think I could convert it to a real
> C program, but I assumed there would be some other way.
>

What you can do is to create a thin C layer between your Ocaml and C++ code.
I am including a very simple code - an interface to the Cubpack
library in Ocaml.

If your interface is big, you might try some of the authomatic
builders like SWIG (http://www.swig.org) which I understand can wrap
C++ classes for use in Ocaml.

Jan

--
-------------------------------------------------------------------------
Jan Kybic <ky...@fel.cvut.cz> tel. +420 2 2435 5721
http://cmp.felk.cvut.cz/~kybic ICQ 20056945

// stub to call Cubpack++ integration routines from Ocaml
//
//
// Jan Kybic, February 2004
// $Id: cubpack_stub.cc 322 2004-02-06 18:03:01Z jkybic $

extern "C" {
#include <caml/mlvalues.h>
#include <caml/memory.h>
#include <caml/alloc.h>
#include <caml/callback.h>
}

#include <cubpack.h>
#include <stdio.h>

// This code is NOT thread safe
// There is nothing to do about it except change Cubpack++

static value ocamlCallback ;

// Call a Ocaml function with two arguments u,v
real evalOcaml(const Point& p) {
CAMLparam0() ;
double z ;
CAMLlocal3(ou,ov,oz) ;
ou=copy_double(p.X()) ;
ov=copy_double(p.Y()) ;
oz=callback2(ocamlCallback,ou,ov) ;
z=Double_val(oz) ;
CAMLreturn(z) ;
}

static double doIntegrate(double a, double r,int m) {
CAMLparam0() ;
Point p1(0.0,0.0), p2(0.0,1.0), p3(1.0,0.0);
TRIANGLE T(p1,p2,p3);
CAMLreturn (Integrate(evalOcaml,T)) ;
}

extern "C"
// parameters: absolute and relative error bounds, maximum number
// of evaluations, the function to evaluate
value cubpackIntegrateTriangle (value a,value r,value m,value f) {
CAMLparam4(a,r,m,f) ; // register for GC
CAMLlocal1(z) ;
register_global_root(&ocamlCallback) ;
ocamlCallback=f ;
z=copy_double(doIntegrate(Double_val(a),Double_val(r),Int_val(m))) ;
remove_global_root(&ocamlCallback) ;
CAMLreturn(z) ;
}


// end of cubpack_stub.cc

Basile STARYNKEVITCH

unread,
Dec 15, 2009, 10:04:53 AM12/15/09
to ky...@fel.cvut.cz, Aaron Bohannon, OCaml List
Jan Kybic wrote:
> On Tue, Dec 15, 2009 at 2:50 PM, Aaron Bohannon <boha...@cis.upenn.edu> wrote:
>> Thanks for the tip. This does resolve the missing caml symbols (even
>> when naming the file with a cpp extension). However, my real program
>> actually uses some C++ features. I think I could convert it to a real
>> C program, but I assumed there would be some other way.
>>
>
> What you can do is to create a thin C layer between your Ocaml and C++ code.
> I am including a very simple code - an interface to the Cubpack
> library in Ocaml.
>


In addition of all the other good answers, you could look at how some existing C++ open-source libraries interface to Ocaml.

Both the Parma Polyhedra Library (PPL, under GPLv3 licence), at http://www.cs.unipr.it/ppl/ and the Low Level Virtual
Machine library (LLVM, under a BSD-like licence) at http://llvm.org/ are free libraries, coded in C++, interfaced to Ocaml.

Regards.


--
Basile STARYNKEVITCH http://starynkevitch.net/Basile/
email: basile<at>starynkevitch<dot>net mobile: +33 6 8501 2359
8, rue de la Faiencerie, 92340 Bourg La Reine, France
*** opinions {are only mines, sont seulement les miennes} ***

Aaron Bohannon

unread,
Dec 15, 2009, 3:47:56 PM12/15/09
to Mark Shinwell, caml...@inria.fr
Yes, it seems you're right. I just need the "extern" annotation
around the includes.

extern "C" {


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

Thanks to everyone for the helpful comments.

- Aaron

0 new messages