C ve Ocaml kaynaklarını kullanarak bir program derlemeye çalışıyorum, C uygulamasında bazı OCaml kodlarını çağırıyor. Pekala, burada sorun yok, Standart Ocaml araçlarıyla yapılabilecek ortak bir işlem olan fully documented görünüyor.C: içine yerleştirme OCaml: bağlantı hatası
Biraz açıklayayım, bu tür bir derleme 4 adımda ayrılır: Caml nesnelerine derleme, ardından C nesnelerini derleme, sonra C dosyalarını derleme ve son olarak tüm C nesnelerini derleme ve alma yürütülebilir.
teoridir, otomatik Caml çalışma zamanını, GC, ve tüm eşyalarını gömmek ve biz sadece hangisi ocaml baytkodu (-lcamlrun
referans) ya da yerli ikili kullandığımız takdirde belirtmek gerekir Ocaml derleyici (-lasmrun
referans) .
Yani, oldukça basit görünüyor, hadi yapalım. Adım 1, 2 ve 3 beklendiği gibi gitti, iyi! Sadece 4. adım sorunludur. Sadece bir göz atın: modülünü Pervasive
bulamazsa main
- Çoklu tanımları:
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
IMHO, iki hata var gibi görünüyor Bunu nasıl düzelteceğime dair hiçbir fikrim yok, belki başka bir dosyayı bağlamalıyım. Birisi bir fikri var mı?
Sorulduğunda, bu hataları veren kodu koydum. Oldukça basit olacak, çünkü çok az kod var, çoğunun belgelerinde bir örnek verildi.
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; }
Ve hepsi bu. Açıkçası, tüm anlamsız şeyleri atladım bu basit örnek olarak çalışmalı ve çalışmıyor. Takip eden benim
Makefile
olmalı.Bu arada, oldukça çirkin. Bu tür bir uygulama için önerileriniz varsa ( C içinde Caml ) veya önerileri yeniden okuduktan sonra, hepsini alacağım.
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
Sanırım stdlib.a ile bağlantı kurmak istemiyorsunuz (varsayılan olarak -lasmrun ve -lcamlrun ile yüklenmelidir) – Thomas
Evet, haklısınız, test yapmanın bir kaydıydı. Silindi. –
Kodunuzu görmeden hata ayıklamak oldukça zordur. Hatayı yeniden üreten küçük bir örneğiniz var mı? – Thomas