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:
- 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.
- 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.
- 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
.
- Bildiğim kadarıyla çıkış biz genellikle konmasını hiçbir şeyi istemiyoruz ilgilidir, ama biz 2.
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.
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 –
'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
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 –