如何从Ocaml使用自己的共享库.so调用C ++代码?

我需要build立一个调用共享对象(Linux下的.so)的Ocaml / C ++模块,

只要编译一个简单的Ocaml / C ++存根就是一个问题,我pipe理这个东西,但是当我需要将.so和ocamlmklib或者ocamlopt连接起来的时候,它会失败

我在gcc 4.5下工作(c ++ 0x)

共享对象的文件:

hello.hpp

#include <iostream> #include <string> using namespace std; class HelloApplication { public : HelloApplication(); ~HelloApplication(); void say(string s); }; typedef HelloApplication *(*create_hello)(); 

hello.cpp:

 #include "hello.hpp" HelloApplication::HelloApplication(){} HelloApplication::~HelloApplication(){} void HelloApplication::say(string s) { cout << "Hello : " << s << endl; } extern "C" { HelloApplication *create() { return new HelloApplication(); } } 

CMake.txt文件来编译这个东西:

 cmake_minimum_required(VERSION 2.6) project(testHello_proj) set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Release" FORCE) #set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Debug" FORCE) set(LIBRARY_OUTPUT_PATH lib/${CMAKE_BUILD_TYPE}) ## Compiler flags if(CMAKE_COMPILER_IS_GNUCXX) set ( CMAKE_CXX_FLAGS "-O2 -std=c++0x" CACHE STRING "g++ Compiler Flags for All Builds" FORCE) set ( CMAKE_CXX_FLAGS_DEBUG "-std=c++0x -O2 -g -Wall" CACHE STRING "g++ Compiler Flags for Debug Builds" FORCE) set ( CMAKE_CXX_FLAGS_RELEASE "-O2 -fmessage-length=0 -std=c++0x" CACHE STRING "g++ Compiler Flags for Release Builds" FORCE) set ( CMAKE_CXX_FLAGS_MINSIZEREL "-Os -std=c++0x" CACHE STRING "g++ Compiler Flags for Release minsize builds" FORCE) set ( CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g1 -std=c++0x" CACHE STRING "g++ Compiler Flags for Release with Debug Info builds" FORCE) endif() file( GLOB_RECURSE source_files src/* ) add_library( testHello SHARED ${source_files} ) 

我得到一个名为libtestHello.so的库

现在Ocaml / C ++模块的文件名为mymod:

* mymod_stubs.cpp:*

 #include <cstdlib> #include <dlfcn.h> #include <string> #include "hello.hpp" extern "C" { #include <memory.h> #include <mlvalues.h> } using namespace std; HelloApplication* hello; extern "C" value initHello (value unit) { CAMLparam1 (unit); create_hello hello_pMaker; void* hello_hndl = dlopen("/path_to_cmake_dir/build/lib/Release/libtestHello.so", RTLD_LAZY); if(hello_hndl == NULL) { cerr << "dlopen : " << dlerror() << endl; exit(EXIT_FAILURE); } void *hello_mkr = dlsym(hello_hndl, "create"); if (hello_mkr == NULL) { cerr << "dlsym : " << dlerror() << endl; exit(EXIT_FAILURE); } hello_pMaker = (create_hello)hello_mkr; HelloApplication* hello_ptr(hello_pMaker()); hello = hello_ptr; CAMLreturn (Val_unit); } extern "C" value say (value v_str) { CAMLparam1 (v_str); string s = String_val(v_str); hello->say(s); CAMLreturn (Val_unit); } 

mymod.ml:

 external initHello : unit -> unit = "initHello" external say : string -> unit = "say" 

caller.ml(testing文件):

 Mymod.initHello;; Mymod.say "tout le monde";; 

Makefile:

 CPPSRC=mymod_stubs.cpp CPPOBJ=mymod_stubs.o CPPINC=-I/usr/local/lib/ocaml/caml -I/path_to_cmake_dir/src CPPLIB=-std=c++0x MODSRC=mymod.ml MODNAME=mymod OPTOBJ=mymod.cmx OPTLIB=mymod.cmxa CALLERSRC=caller.ml OPTCALLERFLAGS=-I . -cclib CALLERLIB=-lstdc++ OPTCALLEREXEC=caller.opt all: opttest #g++ cppcompile: g++ -o ${CPPOBJ} ${CPPLIB} ${CPPINC} -c ${CPPSRC} #native optcompile: cppcompile ocamlopt -c ${MODSRC} optmklib: optcompile ocamlmklib -o ${MODNAME} -ccopt -L/path_to_cmake_dir/build/lib/Release -cclib -ltestHello ${CPPOBJ} ocamlmklib -o ${MODNAME} -ccopt -L/path_to_cmake_dir/build/lib/Release -cclib -ltestHello ${OPTOBJ} opttest: optmklib ocamlopt ${OPTCALLERFLAGS} ${CALLERLIB} ${OPTLIB} ${CALLERSRC} -o ${OPTCALLEREXEC} #clean clean : rm -f *.cma *.cmo *.cmx *.cmxa *.cmi *.so *.a *.o ${OPTCALLEREXEC} 

它编译但我不能打开共享对象libtestHello.so:

$:./caller.opt ./caller.opt:加载共享库时出错:libtestHello.so:无法打开共享目标文件:没有这样的文件或目录

谢谢你的帮助 :)

您可能需要在链接时传递-rdynamic-Wl,-rpath

(我不确定你可以从C或C ++代码中调用Ocaml代码而不用担心;你需要初始化Ocaml运行时系统;同样的,std C ++库可能不适用于未打补丁的ocaml程序,例如因为静态构造函数对象…)