title: How from Ocaml can I call C++ code using itself a shared library .so ?
body: <p>I need to build an Ocaml/C++ module which calls a shared object (.so under linux)</p>
  
  <p>As long as it is a question to compile a simple Ocaml/C++ stub, I manage the thing but when I need to link the .so with ocamlmklib or ocamlopt, it fails</p>
  
  <p>I work under gcc 4.5 (c++0x)</p>
  
  <p><strong>files for the shared object :</strong> </p>
  
  <p><em>hello.hpp</em></p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;string&gt;
  
  using namespace std;
  
  class HelloApplication
  {
  public :
  
      HelloApplication();
      ~HelloApplication();
  
      void say(string s);
  
  };
  
  typedef HelloApplication *(*create_hello)();
  </code></pre>
  
  <p><em>hello.cpp :</em></p>
  
  <pre><code>#include "hello.hpp"
  
  HelloApplication::HelloApplication(){}
  HelloApplication::~HelloApplication(){}
  
  void HelloApplication::say(string s)
  {
       cout &lt;&lt; "Hello : " &lt;&lt; s &lt;&lt; endl;
  }
  
  extern "C"
  {
      HelloApplication *create()
      {
          return new HelloApplication();
      }
  
  }
  </code></pre>
  
  <p>the CMake.txt file to compile the thing :</p>
  
  <pre><code>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}
  )
  </code></pre>
  
  <p>I get a library named <strong>libtestHello.so</strong> </p>
  
  <p><strong>now files of the Ocaml/C++ module, named mymod:</strong></p>
  
  <p>*mymod_stubs.cpp :*</p>
  
  <pre><code>#include &lt;cstdlib&gt;
  #include &lt;dlfcn.h&gt;
  #include &lt;string&gt;
  
  #include "hello.hpp"
  
  extern "C" {
  #include &lt;memory.h&gt;
  #include &lt;mlvalues.h&gt;
  }
  
  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 &lt;&lt; "dlopen : " &lt;&lt; dlerror() &lt;&lt; endl;
          exit(EXIT_FAILURE);
      }
  
      void *hello_mkr = dlsym(hello_hndl, "create");
      if (hello_mkr == NULL)
      {
        cerr &lt;&lt; "dlsym : " &lt;&lt; dlerror() &lt;&lt; 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-&gt;say(s);
  
    CAMLreturn (Val_unit);
  }
  </code></pre>
  
  <p><em>mymod.ml :</em></p>
  
  <pre><code>external initHello : unit -&gt; unit = "initHello"
  
  external say : string -&gt; unit = "say"
  </code></pre>
  
  <p><em>caller.ml (test file) :</em></p>
  
  <pre><code>Mymod.initHello;;
  
  Mymod.say "tout le monde";;
  </code></pre>
  
  <p><em>Makefile :</em></p>
  
  <pre><code>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}
  </code></pre>
  
  <p><strong>it compiles but I can't open the shared object libtestHello.so:</strong></p>
  
  <blockquote>
    <p>$: ./caller.opt ./caller.opt: error while loading shared libraries:
    libtestHello.so: cannot open shared object file: No such file or
    directory</p>
  </blockquote>
  
  <p>thanks for your help :)</p>