2014-04-22 10 views
5

मैं एक बाहरी सी पुस्तकालय द्वारा बाद में उपयोग के लिए एक OCaml बंद संग्रहीत करना चाहते हैं। मैं निम्न कार्य करने में सक्षम हूँ:मैं ओकैमल बंद करने की प्रतिलिपि कैसे बना सकता हूं?

<TARGET> = caml_alloc(Wosize_val(<SOURCE>), Tag_val(<SOURCE>)); 
caml_register_global_root(<TARGET>); 
Code_val(<TARGET>) = Code_val(<SOURCE>); 

लेकिन जैसा कि नाम से "बंद" पता चलता है, यह सिर्फ कोड स्थान कॉपी करने के लिए पर्याप्त नहीं है।

मैं एक (कचरा कलेक्टर के अनुकूल) <SOURCE> की प्रतिलिपि कैसे करूं?

+1

जब आप कहते हैं कि "बाद में", आप बाद में इसी प्रक्रिया में क्या मतलब है? यदि ऐसा है, तो आपको बंद करने की प्रतिलिपि बनाने की आवश्यकता नहीं है (मुझे लगता है)। आपको बस यह सुनिश्चित करना होगा कि आप इसे इस्तेमाल करने से पहले जीसीड नहीं है। आप 'caml_register_global_root' के साथ क्या कर रहे हैं। –

+0

क्या आप इसका विस्तृत उत्तर दे सकते हैं, इसलिए मैं इसे स्वीकार कर सकता हूं? – choeger

+0

ऐसा करने में खुशी :-) यह जीएमटी में देर हो चुकी है - 7, इसे कल होना होगा। सादर, –

उत्तर

4

आईओएस में OCaml के प्रयोग पर हमारे काम में, हम अक्सर OCaml बंद को बचाने और उन्हें बाद में फोन (जब CocoaTouch पुस्तकालयों के लिए इंटरफ़ेस) की जरूरत है। तो मेरे पास कोड है जो वर्षों से काम कर रहा है। हालांकि, यह एक अच्छा उदाहरण बनाने के लिए बहुत जटिल है (और यह उद्देश्य सी में लिखा गया है)। यहां कुछ कोड है जो मैंने अभी लिखा है जो हम कर रहे हैं के सार को पकड़ लेते हैं।

पहले कुछ सी कोड है कि प्रकार unit -> unit के बंद होने से कुछ संख्या बचता है और आपको कालानुक्रमिक सूचकांक द्वारा बाद में उन्हें फोन कर सकते हैं। (यह सिर्फ एक उदाहरण है।)

$ cat saveclo.c 
#include "caml/mlvalues.h" 
#include "caml/memory.h" 
#include "caml/callback.h" 

static value saved_closures[10]; 
static int saved_closure_count = 0; 


value save_closure(value clo) 
{ 
    CAMLparam1(clo); 
    saved_closures[saved_closure_count] = clo; 
    caml_register_global_root(&saved_closures[saved_closure_count]); 
    saved_closure_count++; 
    CAMLreturn(Val_unit); 
} 


value call_closure(value index) 
{ 
    CAMLparam1(index); 
    int ix = Int_val(index); 
    // For simplicity assume closure : unit -> unit 
    (void) caml_callback(saved_closures[ix], Val_unit); 
    CAMLreturn(Val_unit); 
} 

फिर कुछ OCaml कोड है कि इन कार्यों व्यायाम:

$ cat clo.ml 
external save_closure : (unit -> unit) -> unit = "save_closure" 
external call_closure : int -> unit = "call_closure" 

let save alist = 
    let howlong() = 
     Printf.printf "list length %d\n" (List.length alist) 
    in 
    save_closure howlong 

let call() = 
    call_closure 1; 
    call_closure 0 

let() = 
    save [1;2;3;4;5]; 
    save ['a'; 'b'; 'c'; 'd'; 'e'; 'f']; 
    Gc.full_major(); 
    call() 

एक परीक्षण चलाने इस तरह दिखता है:

$ cc -I /usr/local/lib/ocaml -c -o saveclo.o saveclo.c 
$ ocamlopt -c clo.ml 
$ ocamlopt -o clo clo.cmx saveclo.o 
$ ./clo 
list length 6 
list length 5 
$ 

मैं मुख्य बिंदु हैं लगता है (ए) ओकैमल ऑब्जेक्ट में बंद होने का प्रतिनिधित्व करने में पहले से ही शामिल है (किसी प्रकार का कोड संदर्भ, और डेटा)। (बी) आपको इसकी प्रतिलिपि बनाने की आवश्यकता नहीं है, आपको बस यह सुनिश्चित करने की ज़रूरत है कि उसे कचरा नहीं मिला है। (सी) caml_register_global_root पर कॉल बंद करने का संदर्भ बनाता है ताकि जीसी इसे एकत्र न करने के बारे में जानता हो।

मुझे आशा है कि यह उपयोगी है। अगर कोई इस कोड के साथ समस्याएं देखता है, तो मुझे बताएं और त्रुटियों को सही करने के लिए मैं खुश रहूंगा। लेकिन मेरा मानना ​​है कि यह सही है।

संबंधित मुद्दे

 संबंधित मुद्दे