2011-11-17 4 views
18

के साथ जावा इंटरफ़ेस उत्पन्न करना मैं एंड्रॉइड पर इसका उपयोग करने के लिए एक सी ++ लाइब्रेरी (जेसन (डी) धारावाहिकता के जावा रैपर बनाने के लिए SWIG का उपयोग कर रहा हूं। मैं सी ++ में एक अमूर्त वर्ग में परिभाषित किया, (डी) एक वस्तु जो हो सकता है धारावाहिक का प्रतिनिधित्व:एसडब्ल्यूआईजी

class IJsonSerializable { 
public: 
    virtual void serialize(Value &root) = 0; 
    virtual void deserialize(Value &root) = 0; 
};

अब, मैं इस वर्ग से एक जावा इंटरफ़ेस उत्पन्न करने के लिए कोशिश कर रहा हूँ। यहाँ मेरी बड़ा घूँट इंटरफेस है:

%module JsonSerializable 
%{ 
#include "JsonSerializable.hpp" 
%} 

%import "JsonValue.i" 

class IJsonSerializable { 
public: 
    virtual void serialize(Value &root) = 0; 
    virtual void deserialize(Value &root) = 0; 
};

लेकिन उत्पन्न जावा कोड दो तरीकों और एक डिफ़ॉल्ट निर्माता के साथ एक सरल वर्ग, (के रूप में मैं पता लगाने के लिए बड़ा घूँट एक अंतरफलक है कि बताने के लिए सक्षम नहीं था जाहिर है,) है/नाशक:

public class IJsonSerializable { 
    private long swigCPtr; 
    protected boolean swigCMemOwn; 

    public IJsonSerializable(long cPtr, boolean cMemoryOwn) { 
    swigCMemOwn = cMemoryOwn; 
    swigCPtr = cPtr; 
    } 

    public static long getCPtr(IJsonSerializable obj) { 
    return (obj == null) ? 0 : obj.swigCPtr; 
    } 

    protected void finalize() { 
    delete(); 
    } 

    public synchronized void delete() { 
    if (swigCPtr != 0) { 
     if (swigCMemOwn) { 
     swigCMemOwn = false; 
     JsonSerializableJNI.delete_IJsonSerializable(swigCPtr); 
     } 
     swigCPtr = 0; 
    } 
    } 

    public void serialize(Value root) { 
    JsonSerializableJNI.IJsonSerializable_serialize(swigCPtr, this, Value.getCPtr(root), root); 
    } 

    public void deserialize(Value root) { 
    JsonSerializableJNI.IJsonSerializable_deserialize(swigCPtr, this, Value.getCPtr(root), root); 
    } 

}

मैं बड़ा घूँट के साथ एक मान्य इंटरफ़ेस कैसे बना सकता है?

+0

क्यों? जावा में पहले से ही JSON एपीआई है, बस उपलब्ध कई में से एक का उपयोग करें। –

+0

@ChrisDennett: मैं पहले से ही इस पुस्तकालय का उपयोग C++ में अन्य उपयोगों के लिए कर रहा हूं। मुझे निकट भविष्य में बंदरगाह के लिए अन्य पुस्तकालय मिल गए हैं, इसलिए मुझे उनके साथ एक ही समस्या होगी। –

+0

मुझे समझ में नहीं आता - आप यहां क्या उत्पन्न करना चाहते हैं? एसडब्ल्यूआईजी प्रॉक्सी उत्पन्न करता है जो आपके द्वारा दिखाए गए घोषणाओं और परिभाषाओं से मेल खाता है, जो यह यहां किया गया है। क्या यह [इस समस्या] का मामला है (http://www.swig.org/Doc1.3/Java.html#adding_downcasts)? यदि आप थोड़ा स्पष्ट दिख रहे हैं तो मैं आपको एक ठोस उदाहरण दे सकता हूं। – Flexo

उत्तर

44

आप "Directors" का उपयोग करके SWIG + Java के साथ जो खोज रहे हैं उसे प्राप्त कर सकते हैं, हालांकि यह सी ++ अमूर्त कक्षाओं से जावा पर जितना संभव हो उतना सरल मैपिंग नहीं है जैसा आप उम्मीद कर सकते हैं। इसलिए मेरा जवाब तीन भागों में विभाजित है - सबसे पहले जावा में एक सी ++ शुद्ध वर्चुअल फ़ंक्शन को लागू करने का सरल उदाहरण, दूसरी बात यह है कि आउटपुट ऐसा क्यों है और तीसरा "काम-आसपास" क्यों है।

जावा

में एक सी ++ इंटरफ़ेस एक हेडर फाइल (module.hh) को देखते हुए लागू करने:

#include <string> 
#include <iosfwd> 

class Interface { 
public: 
    virtual std::string foo() const = 0; 
    virtual ~Interface() {} 
}; 

inline void bar(const Interface& intf) { 
    std::cout << intf.foo() << std::endl; 
} 

हम इस लपेट और यह जावा की ओर से सहज काम करने के लिए करना चाहते हैं। पूरे मॉड्यूल के लिए

%module(directors="1") test 

%{ 
#include <iostream> 
#include "module.hh" 
%} 

%feature("director") Interface; 
%include "std_string.i" 

%include "module.hh" 

%pragma(java) jniclasscode=%{ 
    static { 
    try { 
     System.loadLibrary("module"); 
    } catch (UnsatisfiedLinkError e) { 
     System.err.println("Native code library failed to load. \n" + e); 
     System.exit(1); 
    } 
    } 
%} 

यहाँ हम सक्रिय कर दिया है निर्देशकों, और फिर अनुरोध किया है कि वे विशेष रूप से class Interface लिए इस्तेमाल किया जा: हम निम्नलिखित बड़ा घूँट इंटरफेस को परिभाषित करते हुए यह कर सकते हैं। इसके अलावा और मेरा पसंदीदा "साझा ऑब्जेक्ट स्वचालित रूप से लोड करें" कोड में विशेष रूप से उल्लेखनीय कुछ भी नहीं है।

public class Run extends Interface { 
    public static void main(String[] argv) { 
    test.bar(new Run());  
    } 

    public String foo() { 
    return "Hello from Java!"; 
    } 
} 

हम तो इस चलाने के लिए और यह उम्मीद के रूप में काम कर रहा है देख सकते हैं::

AJW @ रॅपन्ज़ेल: ~/कोड/खरोंच/बड़ा घूँट/javaintf> जावा हम निम्नलिखित जावा वर्ग के साथ इस परीक्षण कर सकते हैं रन
जावा से हैलो!

आप यह न तो abstract है और न ही एक interface आप यहाँ पढ़ने रोक सकता है किया जा रहा है के साथ खुश हैं, निर्देशकों सब कुछ आप की जरूरत है।

एसडब्ल्यूआईजी interface के बजाय class क्यों उत्पन्न करता है?

एसडब्ल्यूआईजी ने हालांकि एक ठोस वर्ग में एक अमूर्त वर्ग की तरह देखा है। इसका मतलब है जावा पक्ष पर हम कानूनी रूप से new Interface(); लिख सकते हैं, जो कोई समझ नहीं आता है। एसडब्ल्यूआईजी ऐसा क्यों करता है? class भी abstract नहीं है, अकेले interface देखें (बिंदु 4 here देखें), जो जावा पक्ष पर अधिक प्राकृतिक महसूस करेगा।जवाब दोहरा है:

  1. बड़ा घूँट delete बुला, जावा तरफ से छेड़छाड़ cPtr आदि के लिए यांत्रिकी आपूर्ति करती है। यह interface में बिल्कुल नहीं किया जा सका।
  2. मामले में जहां हम निम्नलिखित समारोह लिपटे पर विचार करें:

    Interface *find_interface(); 
    

    यहाँ बड़ा घूँट वापसी प्रकार से है कि यह प्रकार Interface की है बारे में कुछ नहीं अधिक जानता है। एक आदर्श दुनिया में यह पता चलेगा कि व्युत्पन्न प्रकार क्या है, लेकिन अकेले फ़ंक्शन हस्ताक्षर से इसे समझने का कोई तरीका नहीं है। इसका मतलब यह है कि उत्पन्न जावा कहीं पर new Interface पर कॉल करने की आवश्यकता होगी, जो Interface जावा पक्ष पर सार होने पर संभव/कानूनी नहीं होगा।

संभावित समाधान,

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

public interface Interface { 
    public String foo(); 
} 
  • बड़ा घूँट इंटरफ़ेस फ़ाइल को संशोधित करें:

    1. मैन्युअल रूप से एक उचित जावा इंटरफेस के रूप में इंटरफ़ेस बारे में: वहाँ एक समाधान तथापि है

      1. सी का नाम बदलें ++ वर्ग InterfaceNativeInterface होने के लिए जावा पक्ष पर। (हमें इसे केवल प्रश्न में पैकेज के लिए दृश्यमान बनाना चाहिए, हमारे पाइप कोड को "पागल" चीजों से लोगों से बचने के लिए अपने पैकेज में रहना चाहिए।
      2. हर जगह हमारे पास Interface सी ++ कोड एसडब्ल्यूआईजी में होगा जावा तरफ प्रकार के रूप में NativeInterface इस्तेमाल करते हैं। हम Interface जावा इंटरफ़ेस हम मैन्युअल रूप से जोड़ा पर समारोह मापदंडों में इस NativeInterface मैप करने के लिए typemaps की जरूरत है।
      3. मार्क NativeInterfaceInterface को लागू जावा पक्ष व्यवहार एक जावा उपयोगकर्ता के लिए प्राकृतिक और विश्वसनीय बनाने के लिए के रूप में
      4. हमें थोड़ी सी अतिरिक्त कोड की आपूर्ति करने की आवश्यकता है जो जावा Interface को लागू किए बिना उन चीजों के लिए प्रॉक्सी के रूप में कार्य कर सकता है NativeInterface भी।
      5. क्या हम C के पारित ++ हमेशा एक NativeInterface अभी भी होना चाहिए, नहीं सभी Interface रों एक यद्यपि होंगे (यद्यपि सभी NativeInterfaces जाएगा), तो हम NativeInterfaces रूप Interface रों व्यवहार बनाने के लिए कुछ गोंद, और कहा कि गोंद लागू करने के लिए एक typemap प्रदान ।(pgcppname की चर्चा के लिए this document देखें)

      यह एक मॉड्यूल फ़ाइल अब ऐसा दिखता है जैसे में परिणाम:

      // %inline = wrap and define at the same time 
      %inline %{ 
          const Interface& find_interface(const std::string& key) { 
          static class TestImpl : public Interface { 
           virtual std::string foo() const { 
           return "Hello from C++"; 
           } 
          } inst; 
          return inst; 
          } 
      %} 
      
      :

      %module(directors="1") test 
      
      %{ 
      #include <iostream> 
      #include "module.hh" 
      %} 
      
      %feature("director") Interface; 
      %include "std_string.i" 
      
      // (2.1) 
      %rename(NativeInterface) Interface; 
      
      // (2.2) 
      %typemap(jstype) const Interface& "Interface"; 
      
      // (2.3) 
      %typemap(javainterfaces) Interface "Interface" 
      
      // (2.5) 
      %typemap(javain,pgcppname="n", 
           pre=" NativeInterface n = makeNative($javainput);") 
           const Interface& "NativeInterface.getCPtr(n)" 
      
      %include "module.hh" 
      
      %pragma(java) modulecode=%{ 
          // (2.4) 
          private static class NativeInterfaceProxy extends NativeInterface { 
          private Interface delegate; 
          public NativeInterfaceProxy(Interface i) { 
           delegate = i; 
          } 
      
          public String foo() { 
           return delegate.foo(); 
          } 
          } 
      
          // (2.5) 
          private static NativeInterface makeNative(Interface i) { 
          if (i instanceof NativeInterface) { 
           // If it already *is* a NativeInterface don't bother wrapping it again 
           return (NativeInterface)i; 
          } 
          return new NativeInterfaceProxy(i); 
          } 
      %} 
      

    अब हम की तरह एक समारोह में लपेट कर सकते हैं

    और इसका उपयोग करें:

    import java.util.ArrayList; 
    
    public class Run implements Interface { 
        public static void main(String[] argv) { 
        ArrayList<Interface> things = new ArrayList<Interface>(); 
        // Implements the interface directly 
        things.add(new Run()); 
        // NativeInterface implements interface also 
        things.add(test.find_interface("My lookup key")); 
    
        // Will get wrapped in the proxy 
        test.bar(things.get(0)); 
    
        // Won't get wrapped because of the instanceOf test 
        test.bar(things.get(1)); 
        } 
    
        public String foo() { 
        return "Hello from Java!"; 
        } 
    } 
    

    यह अब चलाता है आप आशा करता हूँ के रूप में:

    AJW @ रॅपन्ज़ेल: ~/कोड/खरोंच/बड़ा घूँट/javaintf> जावा भागो
    जावा से नमस्कार! से सी ++

    और हम जावा में एक अंतरफलक के रूप C++ से एक अमूर्त वर्ग लपेटा गया है बिल्कुल के रूप में एक जावा प्रोग्रामर उम्मीद करेंगे
    नमस्कार!

  • +0

    आप शायद [N] (http://stackoverflow.com/questions/3291637/alternatives-to-java-lang-reflect-proxy-for-creating-proxies- जैसे कुछ का उपयोग करके 'NativeIntefaceProxy' क्लास के लेखन को स्वचालित कर सकते हैं। ऑफ-अमूर्त-कक्षाएं) – Flexo

    +3

    बिल्कुल वही जो मुझे चाहिए, और बहुत अच्छी तरह से समझाया गया! बहुत बहुत धन्यवाद। –

    +2

    मुझे लगता है कि एसडब्ल्यूआईजी 3.1 जारी होने पर पर्याप्त रूप से इस जवाब को बदलने की संभावना है: https://github.com/swig/swig/blob/master/Lib/java/swiginterface.i – Flexo

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