मैं मिश्रित सी और ओकंपल स्रोतों का उपयोग करके एक प्रोग्राम संकलित करने की कोशिश कर रहा हूं, सी में आवेदन के मुख्य भाग के साथ ओकैमल कोड के कुछ टुकड़े बुला रहे हैं। ठीक है, यहां कोई समस्या नहीं है, यह एक सामान्य ऑपरेशन प्रतीत होता है, 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
मुझे लगता है कि आप stdlib.a साथ लिंक करने के लिए (के रूप में यह -lasmrun और -lcamlrun द्वारा डिफ़ॉल्ट रूप से लोड किया जा चाहिए) – Thomas
हाँ, तुम सही हो, यह एक परीक्षण के निर्माण का एक लॉग था नहीं करना चाहती। हटाए गए। –
अपना कोड देखे बिना डीबग करना मुश्किल है। क्या आपके पास एक छोटा सा उदाहरण है जो बग को पुन: उत्पन्न करता है? – Thomas