के साथ क्लोजर में मूल्य के आधार पर structs प्राप्त करना और पास करना मेरे पास एक सी एपीआई है जिसे मैं जेएनए एपीआई के माध्यम से क्लोजर के भीतर उपयोग करने की कोशिश कर रहा हूं। मेरा मुद्दा निम्नलिखित उदाहरण के साथ सबसे अच्छा प्रदर्शन किया जा सकता है। मैं एक पुस्तकालय में इस सी कोड है कहते हैं:जेएनए
typedef struct {
int foo;
int bar;
double baz;
} MyStruct;
MyStruct createStruct() {
MyStruct myStruct;
myStruct.foo = 3;
myStruct.bar = 4;
myStruct.baz = 3.14;
return myStruct;
}
double addStruct(MyStruct myStruct) {
return myStruct.foo + myStruct.bar + myStruct.baz;
}
इस उदाहरण में, मैं createStruct
कॉल करने के लिए, और फिर addStruct
है कि परिणाम से पारित करना चाहते हैं। यहां महत्वपूर्ण बात यह है कि MyStruct
मूल्य द्वारा पारित प्रकार और एक तर्क दोनों के रूप में पारित किया गया है। मुझे किसी भी समय MyStruct
में फ़ील्ड के मानों को वास्तव में पढ़ने की आवश्यकता नहीं है।
साथ ही, अपने सिस्टम में, देशी कार्यों इस तरह लिपटे रहे हैं:
; `quux` is defined in `some-lib` and returns an `int`
(let [fn- (com.sun.jna.Function/getFunction "some-lib" "quux")]
(fn [& args]
(.invoke fn- Integer (to-array args))))
लक्ष्य है कि इसके बाद के संस्करण Integer
के लिए स्थानापन्न करने के लिए एक मूल्य के रूप में MyStruct
लपेटो जाएगा एक प्रकार प्राप्त करने के लिए है।
इस विषय को कवर करने वाला एकमात्र संसाधन this article है, लेकिन यह केवल चर्चा करता है कि संदर्भ द्वारा structs को कैसे पास किया जाए।
यह देखते हुए कि, यहाँ विभिन्न दृष्टिकोणों मैं इस समस्या को हल करने के लिए लेने के लिए कोशिश की है इस प्रकार हैं:
एक वर्ग है, जो JNA के built-in mechanism for creating and using structs है कि
Structure
से विरासत बनाएँ। उस पृष्ठ पर जानकारी को देखते हुए, मैं सिर्फ Clojure का उपयोग कर निम्नलिखित वर्ग बनाने की कोशिश की:class MyStruct extends Structure implements Structure.ByValue { int foo; int bar; double baz; }
deftype
इस परिदृश्य के लिए काम नहीं करता है, के बाद से वर्ग सार वर्गStructure
से विरासत की जरूरत है, औरgen-class
नहीं करता ' टी काम नहीं करता क्योंकि कक्षा में सार्वजनिक गैर स्थैतिक फ़ील्डfoo
,bar
औरbaz
होना आवश्यक है।जो मैं बता सकता हूं, मानक क्लोजर जावा इंटरऑप सुविधाओं में से कोई भी उपरोक्त वर्ग नहीं बना सकता है।
एक वर्ग है कि
Structure
से विरासत बनाएँ और struct क्षेत्र गेटर/सेटर तरीकों ओवरराइड। चूंकिgen-class
(मुझे विश्वास है) केवल क्लोजर निर्माण है जो प्रत्यक्ष विरासत की अनुमति देता है, और यह कई सार्वजनिक गैर स्थैतिक क्षेत्रों का समर्थन नहीं करता है, अगला विकल्प केवल फ़ील्ड का उपयोग नहीं करना है। Looking at theStructure
abstract class documentation, ऐसा लगता है कि 'आभासी' संरचना फ़ील्ड का उपयोग करने के लिए ओवरराइड का एक मिश्रण होता है, जैसे कि यह वास्तव में एक अलग स्रोत (such as thestate
field fromgen-class
) से डेटा प्राप्त करता है और सेट करता है। प्रलेखन के माध्यम से देखकर, यहreadField
,writeField
ओवरराइड करने जैसा लगता है, और कुछ अन्य विधियों का इरादा प्रभाव हो सकता है, लेकिन मुझे अस्पष्ट था कि दस्तावेज़ को पढ़ने से ऐसा कैसे किया जाए, और मुझे ऑनलाइन कोई भी उदाहरण नहीं मिल सका।एक अलग भंडारण वर्ग का उपयोग करें। देशी प्रकारों को लपेटने के लिए जेएनए में कक्षाओं का असंख्य वर्ग है।मैं सोच रहा हूं कि
Structure
कक्षा को परिभाषित करने और उपयोग करने के बजाय, मैं एक और जेनेरिक क्लास का उपयोग कर सकता हूं जो बिट्स की मनमानी संख्या ले सकता है (जैसेInteger
4 बिट्स चौड़ा कुछ भी हो सकता है, इस पर ध्यान दिए बिना कि स्रोत 'वास्तव में' है)। उदाहरण के लिए, यह कहना संभव है कि एक फ़ंक्शन लंबाई 16 के बाइट्स की सरणी देता है (sizeof(MyStruct)
16 है)?NativeMapped
लागू करने वाले कंटेनर क्लास में एक निश्चित-आकार सरणी को लपेटने के बारे में क्या? मुझे या तो कैसे करना है इसके उदाहरण नहीं मिल सका।
JNA के रूप में ब्लॉक स्मृति आवंटन प्रदान करता है 'com.sun.jna.Memory'। वहां से, आप 'Pointer.getXXX()' विधियों का उपयोग करके स्मृति में मनमाने ढंग से ऑफसेट से मनमाने ढंग से प्रकार निकाल सकते हैं। – technomage
@technomage 'createStruct' के लिए रिटर्न प्रकार के रूप में 'मेमोरी' का उपयोग करके' पॉइंटर 'लौटाता है, जिसका पता' 0x0000000400000003' है। दूसरे शब्दों में, यह एक सूचक के रूप में संरचना के कच्चे स्मृति मूल्य का इलाज करता है। जब dereferencing (किसी भी 'read' या' getXXX' विधियों के माध्यम से) के माध्यम से, यह वीएम दुर्घटनाग्रस्त हो जाता है। –
समस्या यह है कि 'स्ट्रक्चर' पैरामीटर और रिटर्न वैल्यू सेमेन्टिक्स कंपाइलर द्वारा भिन्न होते हैं और 'स्ट्रक्चर' लेआउट वास्तव में मूल कोड द्वारा उपयोग किया जाता है ताकि यह निर्धारित किया जा सके कि स्टैक को सही तरीके से कैसे सेट किया जाए। मैं सुझाव दे रहा था कि आप मौजूदा 'संरचना। ByValue' उदाहरण में स्मृति के मनमाने ढंग से ब्लॉक को असाइन करने के लिए' मेमोरी 'का उपयोग करने में सक्षम हो सकते हैं। – technomage