2012-10-05 13 views
6

: https://developer.spotify.com/technologies/libspotify/yudum arayüzü fonksiyonu argüman yoluyla Java opak yapı referansını almak için Android için Spotify API (libspotify) kullanmak için SWIG kullanmaya çalışıyorum

sorun için yudum arayüz dosyasını tanımlayan yaşıyorum

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

Ama Java I:

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

C böyle adlandırılacak olan hangisi: başarıyla aşağıdaki doğal C işlevi çağırmak mümkün olabilir Böyle aramak gerekir:

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

sp_session opak yapı ve sadece olarak libspotify en API.h dosyasında tanımlanır:

typedef struct sp_session sp_session; 

Bunu oluşturmak için libspotify kütüphane bekliyor ve ben bana bir referans ver. O zaman bu referansa ihtiyacım olan tek şey API'daki diğer işlevlere geçmek.

Yanıtın SWIG arabiriminde ve tipemarlarında bulunduğuna inanıyorum, ancak belgelere examples I found uygulamasını denemede başarısız oldum.

cevap

5

En temel düzeyde, Java'da oluşturulacak bir "işaretçiye gösterici" nesnesine izin vermek için SWIG kitaplığının cpointer.i bölümünü kullanarak çalışan bir kod oluşturabilirsiniz. başlık dosyası Verilen örnek için

: Java

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)); 
    } 
} 

: o zaman bize böyle bir şey yazmasına olanak tanır

%module spotify 

%{ 
#include "test.h" 
%} 

%include "test.h" 

%include <cpointer.i> 

%pointer_functions(sp_session *, SessionHandle) 

:

#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) {} 

Sen ile sarın. Biz bizim için bir çift işaretçi nesne oluşturmak için SessionHandle_value() çift işaretçi ve new_SessionHandle() derleyici kullanmak için kullanın. (Çift işaretçi nesnesiyle çalışmak için başka işlevler vardır).


yukarıdaki işler ve sarmak için çok basit, ama bir Java programcısı için pek "sezgisel" var ve ideal daha Java gibi görünen bir şey bütün kütüphane maruz istiyorum. Bir Java programcısı, yeni oturum tanıtıcısı nesnesinin yaratıcı işlevinden döndürülmesini ve arızaları belirtmek için bir istisnanın kullanılmasını bekler.

%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" 

sayılı yorumların aşağıdaki noktalara karşılık gelir:

  1. Biz sp_session istiyoruz Biz, biraz arayüz dosyasını değiştirerek yudum birkaç typemaps ve %exception bazı dikkatli kullanımı ile bu arayüz oluşturmak yapabilirsiniz "güzel" bir Java türüne eşlemek için opak tiptir, ancak doğrudan Java içinde türün oluşturulmasına/silinmesine izin vermez.(Javadestruct typemap kullanılarak istenirse, Java nesnesi yok olduğunda otomatik olarak çağrılacak şekilde ayarlanabilecek bir sp_session_destroy işlevi varsa). fake, empty definition combined with %nodefaultctor and %nodefaultdtor bunun için düzenler.
  2. Bir dönüş yapmakta olduğumuz giriş parametresi için, onu Java arabiriminden (numinputs=0 kullanarak) gizlememiz ve sonra arabirimin oluşturulan C bölümünde yerini almak için bir şeyler sağlamamız gerekir.
  3. Hata kodu yerine sp_session'u döndürmek için, işlevden geri dönüş için tip haritalarını ayarlamamız gerekir - bu, işlev döndürme olarak bildirildiyse kullanılmayacak olan tip haritalarının yerini alacak en basit yoldur. $typemap kullanarak bir sp_session.
  4. Bildiğim kadarıyla çıkış biz genellikle konmasını hiçbir şeyi istemiyoruz ilgilidir, ama biz 2.
  5. ekstra girdi parametresi için bir yer tutucu olarak kullanılan işaretçi dönmek istiyorum yok gibi Son olarak, tüm geri dönüşleri gerçek dönüş değerini kontrol edecek ve bir Java istisnasının başarısızlık belirtisi olduğunu gösteren bir kodla sp_session_create'a dahil etmek istiyoruz. Ben de bunun için elle aşağıdaki istisna sınıfını yazdığı şu şekildedir:

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

Java kodunda kullanan bir konumda şu an olduğumuz tüm bu işleri yapmış olan:

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);  
    } 
} 

Orijinalden çok daha basit ve sezgisel olan, ancak daha kolay yazılabilir arayüz. Eğilimim, yazım isimlerinin "daha fazla Java" da görünmesi için advanced renaming feature'u kullanmak olacaktır.

+0

Arabirim dosyanızda bir hata var, 'pointer_functions (sp_session *, SessionHandle)'. '*' Çıkarın. Varsa derleme hataları alıyorum. Ancak, onu kaldırırken, artık bir işaretçi oluşturmuyorum. Eğer '% pointer_functions (sp_session *, SessionHandle) 'işlevi çalışmıyorsa, bu –

+0

'u nasıl çözebiliriz?" Sp_session "veya arabiriminizde başka bir sorun var demektir. Sadece iki kez kontrol ettim ve bu kesinlikle SWIG 2.0.11 ile kesinlikle düzgün çalışıyor. – Flexo

+0

Teşekkürler. _wrap kaynağını elle düzenleyerek çalışabilirim. SWIG 2.0.7.3 kullanıyorum. Yeni bir SWIG kurmayı deneyeceğim. Çift işaretçi ile asla başarılı olmadı. Bazı const * & casts ekler –

0

typedef beyannameniz hakkında bilgi vermelisiniz. herhangi sp_session (Ben API.h dahil etmeden önce ortalama) görmeden

typedef struct sp_session sp_session; 

Ama typedef hakkında SWIG bilgilendirmek için dikkatli olun: birlikte arayüz dosyasını düzenlemek gerektiğini yapmak için. Yazım hatası tanıma ile aynı sorunu yaşadım. Belki bu link yardımcı olacaktır.

İlgili konular