2016-02-07 69 views
4

我正在探索一些冒險的想法。OCaml爲另一個共享庫共享lib

TL:DR; gnumake能夠使用可加載的模塊,我試圖用C語言來使用OCaml,但是在OCaml運行時初始化時遇到了問題。

我有這樣的OCaml的代碼:

(* This is speak_ocaml.ml *) 
let do_speak() = 
    print_endline "This called from OCaml!!"; 
    flush stdout; 
    "Some return value from OCaml" 

let() = 
    Callback.register "speak" do_speak 

,我也有這樣的C代碼:(是的,需要使用額外的CAML宏但在這裏不相關)

#include <stdlib.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#include <unistd.h> 
#include <errno.h> 

#include <gnumake.h> 
#include <caml/mlvalues.h> 
#include <caml/callback.h> 
#include <caml/memory.h> 
#include <caml/alloc.h> 

int plugin_is_GPL_compatible; 

char *ocaml_speaker(const char *func_name, int argc, char **argv) 
{ 
    char *answer = 
    String_val(caml_callback(*caml_named_value("speak"), Val_unit)); 

    printf("Speaking and got: %s\n", answer); 
    char *buf = gmk_alloc(strlen(answer) + 1); 
    strcpy(buf, answer); 
    /* receive_arg */ 
    return buf; 
} 

int do_speak_gmk_setup() 
{ 
    printf("Getting Called by Make\n"); 
    // This is pretty critical, will explain below 
    char **argv = {"/home/Edgar/foo", NULL}; 
    caml_startup(argv); 
    printf("Called caml_startup\n"); 
    gmk_add_function("speak", ocaml_speaker, 1, (unsigned int)1, 1); 
    return 1; 
} 

和我編譯它與這個Makefile

all: 
    ocamlopt -c speak_ocaml.ml 
    ocamlopt -output-obj -o caml_code.o speak_ocaml.cmx 
    clang -I`ocamlc -where` -c do_speak.c -o do_speak.o 

    clang -shared -undefined dynamic_lookup -fPIC -L`ocamlc -where` -ldl \ 
    -lasmrun do_speak.o caml_code.o -o do_speak.so 

show_off: 
    echo "Speaker?" 
    ${speak 123} 

clean: 
    @rm -rf *.{cmi,cmt,cmi,cmx,o,cmo,so} 

而我的問題是,只有當我在Makefile中添加相應的load do_speak.so時,210會關閉,caml_startup不會正確關閉。現在我打電話caml_startup因爲如果我不這麼做,我得到的

Makefile:9: dlopen(do_speak.so, 9): Symbol not found: _caml_atom_table 
    Referenced from: do_speak.so 
    Expected in: flat namespace 
in do_speak.so 
Makefile:9: *** do_speak.so: failed to load. Stop. 

一個錯誤,這是因爲在OS X上鐺不鏈接,在這裏看到更多的詳細信息的方式:http://psellos.com/2014/10/2014.10.atom-table-undef.html

我有種想法......我需要從OCaml代碼創建一個C共享庫,然後它需要成爲另一個C共享庫的一部分,我明顯沒有使用caml_startup想要的原始argv指針。正如我的代碼示例所示,我試圖將其僞造出來,並且還使用了caml_startup(NULL)char **argv = {NULL}; caml_startup(argv),但它們的成功率相似。我不知道如何正確初始化運行時。

回答

2

我實際上無法分辨你在問什麼。然而,這裏是你的問題的這部分註釋:

我試圖僞造出來,並且還使用caml_startup(NULL)和焦炭** argv的= {NULL}; caml_startup(argv)類似的缺乏成功。我不知道如何正確初始化運行時。

據我所知,對於caml_startupargv參數的唯一理由是建立在命令行參數(用於Sys.argv)。如果你並不需要命令行參數,它應該是確定這樣的呼籲:

char *arg = NULL; 
caml_startup(&arg); 

技術上argv應該包含至少一個字符串(節目的名稱)。因此,也許它會更好,這樣的呼籲:

char *argv[] = { "program", NULL }; 
caml_startup(argv); 
+0

的一點是,我試圖用OCaml的代碼爲C lib目錄來尋找旨在被編譯成一個C LIB本身,而不是作爲C代碼一個C可執行文件,因爲我丟棄了OCaml並選擇了C++來完成這個任務,所以現在並不重要。 –