2012-04-20 12 views
8

मैं मिश्रित सी और ओकंपल स्रोतों का उपयोग करके एक प्रोग्राम संकलित करने की कोशिश कर रहा हूं, सी में आवेदन के मुख्य भाग के साथ ओकैमल कोड के कुछ टुकड़े बुला रहे हैं। ठीक है, यहां कोई समस्या नहीं है, यह एक सामान्य ऑपरेशन प्रतीत होता है, fully documented, मानक Ocaml उपकरण के साथ आसान है।सी में ओकैम एम्बेड करना: लिंकिंग त्रुटि

मुझे थोड़ा सा समझाएं, इस तरह के संकलन को 4 चरणों में विभाजित किया गया है: कैमल ऑब्जेक्ट्स को संकलित करने के लिए कैमल, फिर कैमल को सी ऑब्जेक्ट्स को संकलित करना, फिर सी फाइलों को संकलित करना, और आखिरकार सभी सी ऑब्जेक्ट्स को एक साथ संकलित करना और प्राप्त करना निष्पादन योग्य

सिद्धांत है, OCaml संकलक स्वचालित रूप से CAML क्रम, जीसी, और अपने सभी सामान एम्बेड कर देंगे, और हम बस जो भी ocaml बाईटकोड (-lcamlrun संदर्भित) या देशी बाइनरी अगर हम का उपयोग इंगित करने के लिए है (-lasmrun संदर्भित) ।

तो, यह काफी सरल प्रतीत होता है, चलिए इसे करते हैं। चरण 1, 2 और 3 उम्मीद के अनुसार चला गया, अच्छा! केवल चौथा चरण समस्याग्रस्त है। बस एक बार देख ले:

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, ऐसा लगता है दो त्रुटियों है कि वहाँ:

  • main
  • लिंकर की कई परिभाषाएं मॉड्यूल Pervasive

नहीं मिल रहा है मुझे वास्तव में पता नहीं है कि इसे कैसे ठीक किया जाए, शायद मुझे एक अन्य फाइल को लिंक करना होगा। क्या किसी के पास कोई विचार है?

जैसा कि पूछा गया, मैंने कोड डाला जो इन त्रुटियों को देता है। यह काफी सरल होगा क्योंकि बहुत कम कोड है, इसमें से अधिकांश दस्तावेज में एक उदाहरण में दिया गया था।

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 होना चाहिए, जो निम्नानुसार है।

वैसे, यह काफी बदसूरत है। यदि आपके पास इस तरह के आवेदन के लिए प्रस्ताव हैं ( सी के अंदर), या सुझावों को दोबारा करने के लिए, मैं उन्हें सब कुछ ले जाऊंगा।

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

मुझे लगता है कि आप stdlib.a साथ लिंक करने के लिए (के रूप में यह -lasmrun और -lcamlrun द्वारा डिफ़ॉल्ट रूप से लोड किया जा चाहिए) – Thomas

+0

हाँ, तुम सही हो, यह एक परीक्षण के निर्माण का एक लॉग था नहीं करना चाहती। हटाए गए। –

+0

अपना कोड देखे बिना डीबग करना मुश्किल है। क्या आपके पास एक छोटा सा उदाहरण है जो बग को पुन: उत्पन्न करता है? – Thomas

उत्तर

6

आपका लिंक आदेश को दो तरह से गलत है:

  1. आप dlopen के लिए -ldl साथ लिंक करने की आवश्यकता, आदि
  2. आप पुस्तकालयों के बाद करना होगा ऑब्जेक्ट्स जो उन्हें संदर्भित करती हैं (यानी आपके -lcamlrun तर्क वें हैं लिंक लाइन पर गलत स्थान)। लिंक लाइन matters पर तर्कों का क्रम।
संबंधित मुद्दे