私はCとOcamlソースを混在させてプログラムをコンパイルしようとしています.CのアプリケーションのメインはOCamlコードのいくつかを呼び出しています。 いいえ、ここに問題はありません。標準的なOcamlツールを使って簡単に行えるのは、一般的な操作fully documentedのようです。OCamlをCに埋め込む:リンクエラー
CamlオブジェクトにCamlをコンパイルし、CamlオブジェクトをCオブジェクトにコンパイルし、次にCファイルをコンパイルし、最後にすべてのCオブジェクトをまとめてコンパイルするという4つのステップで少し説明します。実行可能ファイル
理論があり、OCamlのコンパイラはCamlのランタイム、GCを埋め込み、そのすべてのものを自動的に、そして私達はちょうど私たちはocamlのバイトコード(-lcamlrun
を参照)、またはネイティブバイナリ(-lasmrun
を参照)どちらを使用するかどうかを示す必要があります。
だから、それはやってみましょう。ステップ1,2および3は期待通りに行った、良い! 第4ステップだけが問題になります。ただ、見て取る:モジュールPervasive
に見つけることができなかったmain
- 複数の定義:
cc -o /home/thomas/Documents/projects/ocaml/GogoGame/bin/GogoPlayer.exe \ -L/usr/lib/ocaml -lcamlrun \ /home/thomas/Documents/projects/ocaml/GogoGame/src/init_camlcode.o \ /home/thomas/Documents/projects/ocaml/GogoGame/src/init.o \ /home/thomas/Documents/projects/ocaml/GogoGame/src/interface.o \ /home/thomas/Documents/projects/ocaml/GogoGame/src/caml_func.oo /home/thomas/Documents/projects/ocaml/GogoGame/src/interface.o: In function `main': interface.c:(.text+0x0): multiple definition of `main' /usr/lib/ocaml/libcamlrun.a(main.o):(.text+0x0): first defined here /usr/lib/ocaml/libcamlrun.a(floats.o): In function `caml_exp_float': (.text+0x488): undefined reference to `exp' /usr/lib/ocaml/libcamlrun.a(floats.o): In function `caml_fmod_float': (.text+0x4f9): undefined reference to `fmod' /usr/lib/ocaml/libcamlrun.a(floats.o): In function `caml_log_float': (…) /usr/lib/ocaml/libcamlrun.a(unix.o): In function `caml_dlopen': (.text+0x2ed): undefined reference to `dlopen' /usr/lib/ocaml/libcamlrun.a(unix.o): In function `caml_dlclose': (.text+0x300): undefined reference to `dlclose' /usr/lib/ocaml/libcamlrun.a(unix.o): In function `caml_dlsym': (.text+0x31b): undefined reference to `dlsym' /usr/lib/ocaml/libcamlrun.a(unix.o): In function `caml_dlerror': (.text+0x342): undefined reference to `dlerror' /home/thomas/Documents/projects/ocaml/GogoGame/src/init_camlcode.o:(.data.rel+0xc): undefined reference to `caml_array_get_addr' /home/thomas/Documents/projects/ocaml/GogoGame/src/init_camlcode.o:(.data.rel+0x10): undefined reference to `caml_array_get_float' (...) /home/thomas/Documents/projects/ocaml/GogoGame/src/init_camlcode.o:(.data.rel+0x31c): undefined reference to `caml_lazy_make_forward' /home/thomas/Documents/projects/ocaml/GogoGame/src/init_camlcode.o:(.data.rel+0x320): undefined reference to `caml_get_public_method' /home/thomas/Documents/projects/ocaml/GogoGame/src/init_camlcode.o:(.data.rel+0x3ac): undefined reference to `caml_terminfo_setup' /home/thomas/Documents/projects/ocaml/GogoGame/src/init_camlcode.o:(.data.rel+0x3b0): undefined reference to `caml_terminfo_backup' /home/thomas/Documents/projects/ocaml/GogoGame/src/init_camlcode.o:(.data.rel+0x3b4): undefined reference to `caml_terminfo_standout' /home/thomas/Documents/projects/ocaml/GogoGame/src/init_camlcode.o:(.data.rel+0x3b8): undefined reference to `caml_terminfo_resume' /home/thomas/Documents/projects/ocaml/GogoGame/src/init.o: In function `camlInit__f_1030': (.text+0xc): undefined reference to `camlPervasives' /home/thomas/Documents/projects/ocaml/GogoGame/src/init.o: In function `camlInit__f_1030': (.text+0x11): undefined reference to `camlPervasives__output_string_1191' /home/thomas/Documents/projects/ocaml/GogoGame/src/init.o: In function `camlInit__f_1030': (.text+0x19): undefined reference to `camlPervasives__string_of_int_1130' /home/thomas/Documents/projects/ocaml/GogoGame/src/init.o: In function `camlInit__f_1030': (.text+0x20): undefined reference to `camlPervasives' /home/thomas/Documents/projects/ocaml/GogoGame/src/init.o: In function `camlInit__f_1030': (.text+0x25): undefined reference to `camlPervasives__output_string_1191' /home/thomas/Documents/projects/ocaml/GogoGame/src/init.o: In function `camlInit__format_result_1034': (.text+0x9c): undefined reference to `camlPrintf__sprintf_1414' /home/thomas/Documents/projects/ocaml/GogoGame/src/init.o: In function `camlInit__entry': (.text+0xe1): undefined reference to `caml_c_call' /home/thomas/Documents/projects/ocaml/GogoGame/src/init.o: In function `camlInit__entry': (.text+0xfb): undefined reference to `caml_c_call' /home/thomas/Documents/projects/ocaml/GogoGame/src/init.o: In function `camlInit__entry': (.text+0x115): undefined reference to `caml_c_call' /home/thomas/Documents/projects/ocaml/GogoGame/src/init.o: In function `camlInit__f_1030': (.text+0x32): undefined reference to `camlPervasives__print_newline_1276' collect2: ld returned 1 exit status make: *** [GogoPlayer] Error 1
私見を、2つのエラーがあるようです私は本当にそれを修正する方法は考えていない、多分私は他のファイルをリンクする必要があります。 誰かがアイデアを持っていますか?
尋ねるように、私はこれらのエラーを与えるコードを書いています。非常にシンプルなコードです。そのほとんどはドキュメントの例で与えられています。
init.ml
let f x = print_string "f is applied to "; print_int x; print_newline() let rec fib n = if n < 2 then 1 else fib(n-1) + fib(n-2) let format_result n = Printf.sprintf "Result is: %d\n" let _ = Callback.register "Arbitrary Name" f; Callback.register "fib" fib; Callback.register "format_result" format_result
caml_func.c
#include <stdio.h> #include <string.h> #include <caml/mlvalues.h> #include <caml/callback.h> void call_caml_f(int x) { static value * closure_f = NULL; if (closure_f == NULL) /* First time around, look up by name */ closure_f = caml_named_value("Arbitrary Name"); caml_callback(*closure_f, Val_int(x)); } int fib(int n) { static value * fib_closure = NULL; if (fib_closure == NULL) fib_closure = caml_named_value("fib"); return Int_val(caml_callback(*fib_closure, Val_int(n))); } char * format_result(int n) { static value * format_result_closure = NULL; if (format_result_closure == NULL) format_result_closure = caml_named_value("format_result"); return strdup(String_val(caml_callback(*format_result_closure, Val_int(n)))); /* We copy the C string returned by String_val to the C heap so that it remains valid after garbage collection. */ }
interface.c
#include <stdio.h> #include "caml_func.c" #define BYTECODE int main(int argc, char **argv) { #ifdef BYTECODE caml_startup(argv); #else caml_main(argv); #endif /* Make sure that stdout is not block buffered. */ setbuf(stdout, NULL); /* Process GTP commands. */ //gtp_main_loop(commands, stdin, NULL); // CAML code here ? return 0; }
これだけです。明らかに、この単純な例のように意味のないものはすべてスキップしましたはとなるはずです。それは私の
Makefile
でなければなりません。ところで、それはかなり醜いです。この種のアプリケーション(Caml C)の提案やリファクタリングの提案がある場合は、それらをすべて取り上げます。
Makefile.ocaml
.PHONY: all clean mrproper # RULES and EXEC are magically set in Makefile.magic all: depend $(RULES) $(EXE) @echo [DONE] mli: $(CAML_ONLY:.ml=.mli) ml-byte: $(CAML_ONLY:.ml=.cmo) ml-called-byte: $(CAML_CALLED_BY_C:.ml=.$(OBJ)) ml-nativ: $(CAML_ONLY:.ml=.cmx) ml-called-nativ: $(CAML_CALLED_BY_C:.ml=.$(OBJ)) c-wrapper: $(C_WRAPPERS:.c=.oo) c-only: $(C_ONLY:.c=.o) $(EXE): $(CC) -o $(BIN)/$(EXE).exe \ $(FLAGS) \ -L$(OCAMLLIB) $(LINKED) -l$(RUNLIB) \ $(wildcard $(SRC)/*.$(OBJ)) $(wildcard $(SRC)/*.oo) # */ %.o: %.c $(CC) $(FLAGS_C) -c $< -o $(SRC)/$(*F).o %.mli: %.ml $(OCAMLC) $(FLAGS_ML) -i $< > $(SRC)/$(*F).mli %.cmi: %.mli $(OCAMLC) $(FLAGS_ML) -c $< -o $(SRC)/$(*F).cmi %.cmo: %.ml $(CAMLC) $(FLAGS_ML) -c $< -o $(SRC)/$(*F).cmo %.cmx: %.ml $(CAMLOPT) $(FLAGSOPT) -c $< -o $(SRC)/$(*F).cmx # native %.o: %.ml $(cd $(SRC)) $(OCAMLC) -output-obj -o $(*F)_camlcode.o \ $(FLAGS_MLC) \ $< # bytecode %.ob: %.ml $(cd $(SRC)) $(OCAMLOPT) -output-obj -o $(*F)_camlcode.ob \ $(FLAGS_MLC) \ $< %.oo: %.c $(CC) $(FLAGS_WRAP) -c $< -o $(SRC)/$(*F).oo clean_mli: rm -f $(SRC)/*.mli # */ clean: rm -f $(BIN)/*.{a,o,oo,cmi,cmo,cmx} # */ rm -f $(SRC)/*.{a,o,oo,cmi,cmo,cmx} # */ mrproper: clean, clean_mli rm -f $(BIN)/$(EXE) depend: $(OCAMLDEP) $(INCLUDES) $(SRC)/*.ml $(SRC)/*.mli > .depend # */ include .depend
stdlib.aとリンクしたくないと思います(-lasmrunと-lcamlrunによってデフォルトでロードされるはずです) – Thomas
そうです、それはテストビルドのログでした。削除されました。 –
コードを見ずにデバッグするのはかなり難しいです。バグを再現する小さな例がありますか? – Thomas