2010-11-04 14 views
9

मैं सी में एक समारोह जो मैं JNA साथ जावा से कॉल करने के लिए कोशिश कर रहा हूँ के साथ पैरामीटर पासिंग:एक जावा वर्ग एक शून्य में * JNA

int myCfunc(void *s, int *ls); 

JNA documentation के अनुसार शून्य * एक com.sun.jna.Pointer हो की आवश्यकता है समारोह में पारित किया गया। JNA के साथ जावा में मुझे विश्वास है ऊपर समारोह के रूप में निम्नानुसार लिपटे किया जाएगा:

:

public interface myWrapper extends Library{ 
    public int myCfunc(Pointer s, IntByReference ls); 
} 

जैसे वस्तुओं जो करने के लिए सूचक से जुड़ा हुआ है, और पैरामीटर s में पारित वर्ग है जो JNA संरचना को लागू किया जाएगा की जरूरत है,

public class myClass extends Structure{ 
    public int x; 
    public int y; 
    public int z; 
} 

दुर्भाग्यवश, पैरामीटर ls बाइट्स में कक्षा की लंबाई का प्रतिनिधित्व करने वाला एक पूर्णांक है। जावा में sizeof फ़ंक्शन नहीं है, इसलिए यह जटिलता का एक अतिरिक्त बिट जोड़ता है। मेरी दूसरी बड़ी समस्या यह सुनिश्चित कर रही है कि मैं ऑब्जेक्ट की सामग्री को मूल स्मृति और पीछे से सही ढंग से पास कर रहा हूं।

मेरी कोड निम्न के समान है:

import com.sun.jna.Native; 
import com.sun.jna.Pointer; 
import com.sun.jna.Structure; 
import com.sun.jna.ptr.IntByReference; 

public void foo(){ 
    myWrapper wrapper = (myWrapper) Native.loadLibrary("SomeDllWithLegacyCode", myWrapper.class); 

    myClass myObj = new myClass(); 
    myObj.x = 1; 
    myObj.y = 2; 
    Pointer myPointer = myObj.getPointer(); 

    int size = Native.getNativeSize(myClass.class); 
    IntByReference len = new IntByReference(size); 

    myObj.write(); //is this required to write the values in myObj into the native memory?? 
    wrapper.myCfunc(myPointer, len); 
    myObj.read(); //does this read in the native memory and push the values into myObj?? 

    myPointer.clear(size); //is this required to clear the memory and release the Pointer to the GC?? 
} 

मैं एक त्रुटि कि डेटा पारित कर दिया हो रही है की तुलना में होने की उम्मीद है सी समारोह से एक बड़े आकार का है।

उपर्युक्त कोड लगभग उसी तरह के चरणों का पालन करने के लिए as provided out in this answer एक ही मुद्दे से निपटने वाले प्रश्न के लिए, लेकिन सी # में। मैंने कोशिश की और परीक्षण किया है कि यह सी # में काम करता है।

मेरा प्रश्न another on Stackoverflow के समान है, लेकिन यह एक क्लाइंट के पॉइंटर की बजाय इंटिबीरेंसेंस के पॉइंटर से संबंधित है।

उत्तर

6

सबसे पहले सभी JNA स्वचालित रूप से संभाल अपने आप स्मृति आवंटन जिसका अर्थ है कि निम्नलिखित के लिए लाइन बेकार है (और स्मृति ढेर नुकसान पहुंचा सकता है):

myPointer.clear(size); //is this required to clear the memory and release the Pointer to the GC?? 

अगला यह भी स्वतः देशी सूचक प्रकार है कि जिसका अर्थ है के साथ सौदा नीचे दोनों लाइनों अपने मामले में बराबर हैं:

public int myCfunc(Pointer s, IntByReference ls); 
public int myCfunc(myClass s, IntByReference ls); 

और इस तरह JNA आप के लिए myObj.write(); और read करेंगे।

निम्नलिखित 100% सही है, लेकिन मेरा सुझाव है कि आप myCfunc के पहले और बाद में अपने कॉल len.getValue() लॉग इन करें (सकता था जो 3 * 4 = 12 दे, 4 बाइट्स की 3 पूर्णांक):

int size = Native.getNativeSize(myClass.class); 
IntByReference len = new IntByReference(size); 

सब तो यह सही है तो आपको शायद आपकी संरचना के प्रोटोटाइप में एक त्रुटि हो।

मेरे अनुभव से यह ज्यादातर एक पुरानी सी हेडर फाइल या किसी पुराने पुस्तकालय की वजह से है:

  • आप जिसमें कहा गया है कि struct के मूल्यों पूर्णांक हैं हैडर संस्करण 2.0 लेकिन पुस्तकालय v1.0 के खिलाफ अपने को जोड़ने का उपयोग कर रहे हैं जो एक बाइट संरचना लेता है
  • आप हेडर संस्करण 2 का उपयोग कर रहे हैं।0 जिसमें कहा गया है कि struct के मूल्यों पूर्णांक हैं, लेकिन पुस्तकालय v1.9 जो अंत में दो ints और एक बाइट

लेता है के खिलाफ अपने को जोड़ने के लिए अपने कोड इस तरह दिखना चाहिए:

public void foo(){ 
    myWrapper wrapper = (myWrapper) Native.loadLibrary("SomeDllWithLegacyCode", myWrapper.class); 

    myClass myObj = new myClass(); 
    myObj.x = 1; 
    myObj.y = 2; 

    int size = Native.getNativeSize(myClass.class); 
    IntByReference len = new IntByReference(size); 

    //log len.getValue 
    wrapper.myCfunc(myObj, len); 
    //log len.getValue 
} 

तुम भी कोशिश कर सकते हैं को स्वेच्छा से कमी डीबगिंग उद्देश्यों उदाहरण के लिए लेन का मूल्य:

IntByReference len = new IntByReference(size-1); 
IntByReference len = new IntByReference(size-2); 
IntByReference len = new IntByReference(size-3); 
//... 
IntByReference len = new IntByReference(size-11); 

यह तुम क्या wan't नहीं करेंगे लेकिन कम से कम यह आप देना चाहिए सही "अधिकतम लेन"

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