2012-04-20 13 views
8

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

  • bağlayıcı ait

    • Ç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 
      
  • +0

    Sanırım stdlib.a ile bağlantı kurmak istemiyorsunuz (varsayılan olarak -lasmrun ve -lcamlrun ile yüklenmelidir) – Thomas

    +0

    Evet, haklısınız, test yapmanın bir kaydıydı. Silindi. –

    +0

    Kodunuzu görmeden hata ayıklamak oldukça zordur. Hatayı yeniden üreten küçük bir örneğiniz var mı? – Thomas

    cevap