Мне нужно создать модуль Ocaml / C ++, который вызывает общий объект (.so в Linux)
Пока речь идет о компиляции простой заглушки Ocaml / C ++, я справляюсь с этим, но когда мне нужно связать .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 (тестовый файл):
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: не удается открыть общий объектный файл: такого файла нет или
каталог
спасибо за вашу помощь:)