आप "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 देखें), जो जावा पक्ष पर अधिक प्राकृतिक महसूस करेगा।जवाब दोहरा है:
- बड़ा घूँट
delete
बुला, जावा तरफ से छेड़छाड़ cPtr
आदि के लिए यांत्रिकी आपूर्ति करती है। यह interface
में बिल्कुल नहीं किया जा सका।
मामले में जहां हम निम्नलिखित समारोह लिपटे पर विचार करें:
Interface *find_interface();
यहाँ बड़ा घूँट वापसी प्रकार से है कि यह प्रकार Interface
की है बारे में कुछ नहीं अधिक जानता है। एक आदर्श दुनिया में यह पता चलेगा कि व्युत्पन्न प्रकार क्या है, लेकिन अकेले फ़ंक्शन हस्ताक्षर से इसे समझने का कोई तरीका नहीं है। इसका मतलब यह है कि उत्पन्न जावा कहीं पर new Interface
पर कॉल करने की आवश्यकता होगी, जो Interface
जावा पक्ष पर सार होने पर संभव/कानूनी नहीं होगा।
संभावित समाधान,
आप जावा में एकाधिक वंशानुक्रम यह काफी सीमित हो जाएगा के साथ एक प्रकार पदानुक्रम व्यक्त करने के लिए में एक अंतरफलक के रूप में प्रदान करने की उम्मीद कर रहे थे, तो।
public interface Interface {
public String foo();
}
बड़ा घूँट इंटरफ़ेस फ़ाइल को संशोधित करें:
मैन्युअल रूप से एक उचित जावा इंटरफेस के रूप में इंटरफ़ेस बारे में: वहाँ एक समाधान तथापि है
- सी का नाम बदलें ++ वर्ग
Interface
NativeInterface
होने के लिए जावा पक्ष पर। (हमें इसे केवल प्रश्न में पैकेज के लिए दृश्यमान बनाना चाहिए, हमारे पाइप कोड को "पागल" चीजों से लोगों से बचने के लिए अपने पैकेज में रहना चाहिए।
- हर जगह हमारे पास
Interface
सी ++ कोड एसडब्ल्यूआईजी में होगा जावा तरफ प्रकार के रूप में NativeInterface
इस्तेमाल करते हैं। हम Interface
जावा इंटरफ़ेस हम मैन्युअल रूप से जोड़ा पर समारोह मापदंडों में इस NativeInterface
मैप करने के लिए typemaps की जरूरत है।
- मार्क
NativeInterface
Interface
को लागू जावा पक्ष व्यवहार एक जावा उपयोगकर्ता के लिए प्राकृतिक और विश्वसनीय बनाने के लिए के रूप में
- हमें थोड़ी सी अतिरिक्त कोड की आपूर्ति करने की आवश्यकता है जो जावा
Interface
को लागू किए बिना उन चीजों के लिए प्रॉक्सी के रूप में कार्य कर सकता है NativeInterface
भी।
- क्या हम 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++ से एक अमूर्त वर्ग लपेटा गया है बिल्कुल के रूप में एक जावा प्रोग्रामर उम्मीद करेंगे
नमस्कार!
क्यों? जावा में पहले से ही JSON एपीआई है, बस उपलब्ध कई में से एक का उपयोग करें। –
@ChrisDennett: मैं पहले से ही इस पुस्तकालय का उपयोग C++ में अन्य उपयोगों के लिए कर रहा हूं। मुझे निकट भविष्य में बंदरगाह के लिए अन्य पुस्तकालय मिल गए हैं, इसलिए मुझे उनके साथ एक ही समस्या होगी। –
मुझे समझ में नहीं आता - आप यहां क्या उत्पन्न करना चाहते हैं? एसडब्ल्यूआईजी प्रॉक्सी उत्पन्न करता है जो आपके द्वारा दिखाए गए घोषणाओं और परिभाषाओं से मेल खाता है, जो यह यहां किया गया है। क्या यह [इस समस्या] का मामला है (http://www.swig.org/Doc1.3/Java.html#adding_downcasts)? यदि आप थोड़ा स्पष्ट दिख रहे हैं तो मैं आपको एक ठोस उदाहरण दे सकता हूं। – Flexo