2012-10-05 9 views
6

मैं आदेश एंड्रॉयड के लिए Spotify एपीआई (libspotify) का उपयोग करने के बड़ा घूँट उपयोग करने के लिए कोशिश कर रहा हूँ: https://developer.spotify.com/technologies/libspotify/बड़ा घूँट इंटरफ़ेस समारोह तर्क के माध्यम से जावा में एक अपारदर्शी struct संदर्भ प्राप्त करने के लिए

मैं मुसीबत के लिए बड़ा घूँट इंटरफ़ेस फ़ाइल को परिभाषित कर रहा हूँ

//config struct defined previously 
sp_session *sess; 
sp_session_create(&config, &sess); 

लेकिन जावा मैं में:

sp_error sp_session_create(const sp_session_config * config, sp_session ** sess); 

सी में इस तरह कहा जा सकता है कौन सा: सफलतापूर्वक निम्नलिखित देशी सी फ़ंक्शन को कॉल करने में सक्षम हो इसे इस तरह कॉल करने के लिए की आवश्यकता होगी:

//config object defined previously 
sp_session javaSess = new sp_session(); 
sp_session_create(config, javaSess); 

sp_session एक अपारदर्शी struct है और केवल के रूप में libspotify के API.h फ़ाइल में परिभाषित किया गया है:

typedef struct sp_session sp_session; 

मैं इसे बनाने के लिए libspotify पुस्तकालय की उम्मीद कर रहा हूँ और मुझे इसका संदर्भ दो। इसके लिए मुझे केवल उस संदर्भ की आवश्यकता है जो एपीआई में अन्य कार्यों को पास करना है।

मुझे विश्वास है कि उत्तर SWIG इंटरफ़ेस और टाइपमैप के भीतर है, लेकिन मैं प्रलेखन में examples I found लागू करने का प्रयास करने में असफल रहा हूं।

उत्तर

5

सबसे बुनियादी स्तर पर आप कोड बना सकते हैं जो SWIG लाइब्रेरी के cpointer.i भाग का उपयोग करके काम करता है ताकि जावा में सीधे "पॉइंटर टू पॉइंटर" ऑब्जेक्ट को बनाया जा सके।

हेडर फाइल दिया उदाहरण के लिए:

%module spotify 

%{ 
#include "test.h" 
%} 

%include "test.h" 

%include <cpointer.i> 

%pointer_functions(sp_session *, SessionHandle) 

कौन सा फिर हमें की तरह कुछ लिखने के लिए अनुमति देता है::

public class run { 
    public static void main(String[] argv) { 
    System.loadLibrary("test"); 
    SWIGTYPE_p_p_sp_session session = spotify.new_SessionHandle(); 
    spotify.sp_session_create(new sp_session_config(), session); 
    spotify.do_something(spotify.SessionHandle_value(session)); 
    } 
} 
जावा में

#include <stdlib.h> 

typedef struct sp_session sp_session; 

typedef struct {} sp_session_config; 

typedef int sp_error; 

inline sp_error sp_session_create(const sp_session_config *config, sp_session **sess) { 
    // Just for testing, would most likely be internal to the library somewhere 
    *sess = malloc(1); 
    (void)config; 
    return sess != NULL; 
} 

// Another thing that takes just a pointer 
inline void do_something(sp_session *sess) {} 

आप इसे के साथ रैप कर सकते हैं। हम डबल पॉइंटर और new_SessionHandle() को हमारे लिए डबल पॉइंटर ऑब्जेक्ट बनाने के लिए SessionHandle_value() का उपयोग करने के लिए उपयोग करते हैं। (डबल पॉइंटर ऑब्जेक्ट के साथ काम करने के लिए अन्य फ़ंक्शन हैं)।


ऊपर काम करता है और रैप करने के लिए बहुत आसान है, लेकिन यह एक जावा प्रोग्रामर के लिए शायद ही "सहज" है और आदर्श हम कुछ है कि अधिक जावा की तरह दिखता है में पूरे पुस्तकालय का पर्दाफाश होगा।

एक जावा प्रोग्रामर उम्मीद करेगा कि नया सत्र हैंडल ऑब्जेक्ट निर्माता फ़ंक्शन से वापस कर दिया जाएगा और असफलताओं को इंगित करने के लिए एक अपवाद का उपयोग किया जाएगा।

%module spotify 

%{ 
#include "test.h" 
%} 

// 1: 
%nodefaultctor sp_session; 
%nodefaultdtor sp_session; 
struct sp_session {}; 

// 2: 
%typemap(in,numinputs=0) sp_session ** (sp_session *tptr) { 
    $1 = &tptr; 
} 

// 3: 
%typemap(jstype) sp_error sp_session_create "$typemap(jstype,sp_session*)" 
%typemap(jtype) sp_error sp_session_create "$typemap(jtype,sp_session*)" 
%typemap(jni) sp_error sp_session_create "$typemap(jni,sp_session*)"; 
%typemap(javaout) sp_error sp_session_create "$typemap(javaout,sp_session*)"; 

// 4: 
%typemap(out) sp_error sp_session_create "" 
%typemap(argout) sp_session ** { 
    *(sp_session **)&$result = *$1; 
} 

// 5: 
%javaexception("SpotifyException") sp_session_create { 
    $action 
    if (!result) { 
    jclass clazz = JCALL1(FindClass, jenv, "SpotifyException"); 
    JCALL2(ThrowNew, jenv, clazz, "Failure creating session"); 
    return $null; 
    } 
} 

%include "test.h" 

गिने टिप्पणियां इन अंकों के साथ अनुरूप:

  1. हम sp_session चाहते हम, कुछ हद तक इंटरफेस फ़ाइल को बदलकर बड़ा घूँट में कुछ typemaps और %exception के कुछ सावधान उपयोग के साथ कि इंटरफ़ेस उत्पन्न कर सकते हैं अपारदर्शी प्रकार को "अच्छा" जावा प्रकार पर मैप करने के लिए, लेकिन जावा के भीतर सीधे प्रकार के निर्माण/हटाने की अनुमति नहीं है।(यदि sp_session_destroy फ़ंक्शन है, तो जब जावा ऑब्जेक्ट नष्ट हो जाता है तो उसे स्वचालित रूप से कॉल करने के लिए व्यवस्थित किया जा सकता है यदि यह जावाडस्ट्रक्चर टाइपमैप का उपयोग करने के लिए वांछनीय है)। fake, empty definition combined with %nodefaultctor and %nodefaultdtor इसके लिए व्यवस्था करता है।
  2. इनपुट पैरामीटर के लिए जिसे हम रिटर्न में बना रहे हैं, इसके बजाय हमें इसे जावा इंटरफ़ेस से छिपाने की आवश्यकता है (numinputs=0 का उपयोग करके) और फिर इंटरफ़ेस के जेनरेट सी भाग में अपनी जगह लेने के लिए कुछ आपूर्ति करें।
  3. त्रुटि कोड के बजाय sp_session वापस करने के लिए हमें फ़ंक्शन से वापसी के लिए टाइपमैप को समायोजित करने की आवश्यकता है - ऐसा करने का सबसे आसान तरीका उन टाइपमैप के लिए उन्हें प्रतिस्थापित करना है जो फ़ंक्शन को लौटने के रूप में घोषित किया गया था $typemap का उपयोग कर sp_session
  4. जहां तक ​​उत्पादन का सवाल है हम कुछ भी है, जहां यह आमतौर पर मार्शल किया जाएगा करने के लिए नहीं करना चाहते हैं, लेकिन हम सूचक हम 2.
  5. में अतिरिक्त इनपुट पैरामीटर के लिए एक प्लेसहोल्डर के रूप में इस्तेमाल वापस करना चाहते हैं अंत में हम पूरे कॉल को sp_session_create पर कुछ कोड में संलग्न करना चाहते हैं जो वास्तविक रिटर्न वैल्यू की जांच करेगा और जावा अपवाद के लिए मानचित्र को यह विफलता का संकेत देगा। मैं भी उस के लिए हाथ से निम्न अपवाद वर्ग ने लिखा है:

    public class SpotifyException extends Exception { 
        public SpotifyException(String reason) { 
        super(reason); 
        } 
    } 
    

इस प्रकार के रूप में उपयोग करने के लिए कि जावा कोड में एक स्थिति में यह सब काम अब हम कर रहे हैं किया करने के बाद:

public class run { 
    public static void main(String[] argv) throws SpotifyException { 
    System.loadLibrary("test"); 
    sp_session handle = spotify.sp_session_create(new sp_session_config()); 
    spotify.do_something(handle);  
    } 
} 

इंटरफ़ेस लिखने के लिए मूल लेकिन सरल से अधिक सरल और अधिक सहज ज्ञान युक्त है। मेरा झुकाव advanced renaming feature का उपयोग करने के लिए प्रकार के नाम "अधिक जावा देखें" का उपयोग करना होगा।

+0

आपको अपनी इंटरफ़ेस फ़ाइल, 'पॉइंटर_फंक्शन (sp_session *, सत्रहैंडल)' में कोई त्रुटि है। '*' निकालें। अगर उपस्थित हो तो मुझे संकलन त्रुटियां मिलती हैं। हालांकि, इसे हटाते समय, मैं अब सूचक नहीं बना रहा हूं। इस –

+0

को हल करने के लिए कैसे करें यदि '% पॉइंटर_फंक्शन (sp_session *, सत्रहैंडल)' काम नहीं करता है तो संभवतः 'sp_session' या आपके इंटरफ़ेस में कुछ और समस्या है। मैंने बस डबल चेक किया है और वह बिट निश्चित रूप से SWIG 2.0.11 के साथ अभी भी सही तरीके से काम करता है। – Flexo

+0

धन्यवाद। _wrap स्रोत मैन्युअल रूप से संपादित करके मैं इसे काम कर सकता हूं। मैं SWIG 2.0.7.3 का उपयोग करता हूं। मुझे लगता है कि मैं एक नया SWIG स्थापित करने की कोशिश करूंगा। डबल पॉइंटर्स के साथ कभी सफल नहीं हुआ। यह कुछ कॉन्स * और कास्ट करता है –

0

आपको अपने typedef घोषणा के बारे में सूचित करना चाहिए।

typedef struct sp_session sp_session; 

लेकिन अपने typedef के बारे में सूचित करने के लिए बड़ा घूँट सावधान रहना होगा इससे पहले कि यह किसी भी sp_session (मैं API.h शामिल करने से पहले मतलब) देखता है: आदेश है कि आप के साथ अपने इंटरफेस फ़ाइल को संपादित करना चाहिए करने के लिए। मुझे टाइपपीफ मान्यता के साथ एक ही समस्या थी। शायद यह link मदद करेगा।

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