]> sigrok.org Git - libsigrok.git/blame - bindings/java/org/sigrok/core/classes/classes.i
bindings/java: Fix build issue with SWIG 4.x.
[libsigrok.git] / bindings / java / org / sigrok / core / classes / classes.i
CommitLineData
9fcf4d0b
ML
1%module classes
2
3/* Automatically load JNI library. */
4%pragma(java) jniclasscode=%{
5 static {
6 System.loadLibrary("sigrok_java_core_classes");
7 }
8%}
9
8a314e90 10/* Documentation & importing interfaces. */
90bd7656 11%pragma(java) jniclassimports=%{
8a314e90
ML
12/**
13 * @mainpage API Reference
176d785d 14 *
8a314e90
ML
15 * Introduction
16 * ------------
176d785d 17 *
8a314e90 18 * The sigrok-java API provides an object-oriented Java interface to the
52ff4f6a 19 * functionality in libsigrok. It is built on top of the libsigrokcxx C++ API.
176d785d 20 *
8a314e90
ML
21 * Getting started
22 * ---------------
176d785d 23 *
8a314e90
ML
24 * Usage of the sigrok-java API needs to begin with a call to Context.create().
25 * This will create the global libsigrok context and returns a Context object.
26 * Methods on this object provide access to the hardware drivers, input and
27 * output formats supported by the library, as well as means of creating other
28 * objects such as sessions and triggers.
176d785d 29 *
8a314e90
ML
30 * Error handling
31 * --------------
176d785d 32 *
8a314e90
ML
33 * When any libsigrok C API call returns an error, an Error exception is raised,
34 * which provides access to the error code and description.
35 */
36
37import org.sigrok.core.interfaces.LogCallback;
38import org.sigrok.core.interfaces.DatafeedCallback;
90bd7656
ML
39%}
40
9fcf4d0b
ML
41/* Map Glib::VariantBase to a Variant class in Java */
42%rename(Variant) VariantBase;
43namespace Glib {
44 class VariantBase {};
45}
46
c7855def
ML
47%include "bindings/swig/templates.i"
48
9fcf4d0b
ML
49/* Map between std::vector and java.util.Vector */
50%define VECTOR(CValue, JValue)
51
52%typemap(jni) std::vector< CValue > "jobject"
53%typemap(jtype) std::vector< CValue > "java.util.Vector<JValue>"
54%typemap(jstype) std::vector< CValue > "java.util.Vector<JValue>"
55
56%typemap(javain,
f3095e7e
ML
57 pre=" $javaclassname temp$javainput = new $javaclassname();
58 for (JValue value : $javainput)
59 temp$javainput.add(value);",
9fcf4d0b
ML
60 pgcppname="temp$javainput")
61 std::vector< CValue > "$javaclassname.getCPtr(temp$javainput)"
62
9fcf4d0b
ML
63%typemap(javaout) std::vector< CValue > {
64 return (java.util.Vector<JValue>)$jnicall;
65}
66
67%typemap(out) std::vector< CValue > {
68 jclass Vector = jenv->FindClass("java/util/Vector");
69 jmethodID Vector_init = jenv->GetMethodID(Vector, "<init>", "()V");
70 jmethodID Vector_add = jenv->GetMethodID(Vector, "add",
71 "(Ljava/lang/Object;)Z");
72 jclass Value = jenv->FindClass("org/sigrok/core/classes/" #JValue);
73 jmethodID Value_init = jenv->GetMethodID(Value, "<init>", "(JZ)V");
74 $result = jenv->NewObject(Vector, Vector_init);
908aad38 75 jlong value = 0;
9fcf4d0b
ML
76 for (auto entry : $1)
77 {
32fd1edc 78 *(CValue **) &value = new CValue(entry);
e83a8f49 79 jenv->CallBooleanMethod($result, Vector_add,
9fcf4d0b
ML
80 jenv->NewObject(Value, Value_init, value, true));
81 }
82}
83
84%enddef
85
86VECTOR(std::shared_ptr<sigrok::Channel>, Channel)
87VECTOR(std::shared_ptr<sigrok::HardwareDevice>, HardwareDevice)
88
89/* Common macro for mapping between std::map and java.util.Map */
90
91%define MAP_COMMON(CKey, CValue, JKey, JValue)
92
93%typemap(jstype) std::map< CKey, CValue >
94 "java.util.Map<JKey, JValue>"
95
96%typemap(javain,
e8035741
UH
97/* SWIG 4.0.0 changed the std::map wrappers in an incompatible way. */
98#if SWIG_VERSION >= 0x040000
99 pre=" $javaclassname temp$javainput = new $javaclassname();
100 for (java.util.Map.Entry<JKey, JValue> entry : $javainput.entrySet())
101 temp$javainput.put(entry.getKey(), entry.getValue());",
102 pgcppname="temp$javainput")
103#else
f3095e7e
ML
104 pre=" $javaclassname temp$javainput = new $javaclassname();
105 for (java.util.Map.Entry<JKey, JValue> entry : $javainput.entrySet())
106 temp$javainput.set(entry.getKey(), entry.getValue());",
9fcf4d0b 107 pgcppname="temp$javainput")
e8035741 108#endif
9fcf4d0b
ML
109 std::map< CKey, CValue > "$javaclassname.getCPtr(temp$javainput)"
110
9fcf4d0b
ML
111%typemap(javaout) std::map< CKey, CValue > {
112 return (java.util.Map<JKey, JValue>)$jnicall;
113}
114
115%enddef
116
117/* Specialisation for string->string maps. */
118
119MAP_COMMON(std::string, std::string, String, String)
120
24287ea9
AJ
121%typemap(jni) std::map<std::string, std::string>
122 "jobject"
123%typemap(jtype) std::map<std::string, std::string>
124 "java.util.Map<String,String>"
125
9fcf4d0b
ML
126%typemap(out) std::map<std::string, std::string> {
127 jclass HashMap = jenv->FindClass("java/util/HashMap");
128 jmethodID init = jenv->GetMethodID(HashMap, "<init>", "()V");
129 jmethodID put = jenv->GetMethodID(HashMap, "put",
130 "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
131 $result = jenv->NewObject(HashMap, init);
132 for (auto entry : $1)
133 jenv->CallObjectMethod($result, put,
134 jenv->NewStringUTF(entry.first.c_str()),
135 jenv->NewStringUTF(entry.second.c_str()));
136}
137
138/* Specialisation macro for string->shared_ptr maps. */
139
140%define STRING_TO_SHARED_PTR_MAP(ClassName)
141
142%typemap(jni) std::map<std::string, std::shared_ptr<sigrok::ClassName> >
143 "jobject"
144%typemap(jtype) std::map<std::string, std::shared_ptr<sigrok::ClassName> >
145 "java.util.Map<String,ClassName>"
146
147MAP_COMMON(std::string, std::shared_ptr<sigrok::ClassName>, String, ClassName)
148
149%typemap(out) std::map<std::string, std::shared_ptr<sigrok::ClassName> > {
150 jclass HashMap = jenv->FindClass("java/util/HashMap");
151 jmethodID HashMap_init = jenv->GetMethodID(HashMap, "<init>", "()V");
152 jmethodID HashMap_put = jenv->GetMethodID(HashMap, "put",
153 "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
154 jclass Value = jenv->FindClass("org/sigrok/core/classes/" #ClassName);
155 jmethodID Value_init = jenv->GetMethodID(Value, "<init>", "(JZ)V");
156 $result = jenv->NewObject(HashMap, HashMap_init);
908aad38 157 jlong value = 0;
9fcf4d0b
ML
158 for (auto entry : $1)
159 {
32fd1edc
MC
160 *(std::shared_ptr< sigrok::ClassName > **)&value =
161 new std::shared_ptr< sigrok::ClassName>(entry.second);
9fcf4d0b
ML
162 jenv->CallObjectMethod($result, HashMap_put,
163 jenv->NewStringUTF(entry.first.c_str()),
164 jenv->NewObject(Value, Value_init, value, true));
165 }
166}
167
168%enddef
169
170STRING_TO_SHARED_PTR_MAP(Driver)
171STRING_TO_SHARED_PTR_MAP(InputFormat)
172STRING_TO_SHARED_PTR_MAP(OutputFormat)
173
174/* Specialisation for ConfigKey->Variant maps */
175
176MAP_COMMON(const sigrok::ConfigKey *, Glib::VariantBase, ConfigKey, Variant)
177
2928f47d
ML
178%typemap(jni) std::map<const sigrok::ConfigKey, Glib::VariantBase> "jobject"
179%typemap(jtype) std::map<const sigrok::ConfigKey, Glib::VariantBase>
180 "java.util.Map<ConfigKey,Variant>"
181
9fcf4d0b
ML
182%typemap(out) std::map<const sigrok::ConfigKey *, Glib::VariantBase> {
183 jclass HashMap = jenv->FindClass("java/util/HashMap");
184 jmethodID HashMap_init = jenv->GetMethodID(HashMap, "<init>", "()V");
185 jmethodID HashMap_put = jenv->GetMethodID(HashMap, "put",
186 "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
187 jclass ConfigKey = jenv->FindClass("org/sigrok/core/classes/ConfigKey");
188 jmethodID ConfigKey_init = jenv->GetMethodID(ConfigKey, "<init>", "(JZ)V");
189 jclass Variant = jenv->FindClass("org/sigrok/core/classes/Variant");
190 jmethodID Variant_init = jenv->GetMethodID(Variant, "<init>", "(JZ)V");
191 $result = jenv->NewObject(HashMap, HashMap_init);
908aad38
MC
192 jlong key = 0;
193 jlong value = 0;
9fcf4d0b
ML
194 for (auto entry : $1)
195 {
32fd1edc
MC
196 *(const sigrok::ConfigKey **) &key = entry.first;
197 *(Glib::VariantBase **) &value = new Glib::VariantBase(entry.second);
9fcf4d0b
ML
198 jenv->CallObjectMethod($result, HashMap_put,
199 jenv->NewObject(ConfigKey, ConfigKey_init, key, false));
200 jenv->NewObject(Variant, Variant_init, value, true));
201 }
202}
203
9fcf4d0b
ML
204/* Pass JNIEnv parameter to C++ extension methods requiring it. */
205
206%typemap(in, numinputs=0) JNIEnv * %{
207 $1 = jenv;
176d785d 208%}
9fcf4d0b 209
c470ae86
MC
210/* Thread safe JNIEnv handling */
211
212%inline {
213namespace {
214 class ScopedEnv {
215 public:
216 ScopedEnv(JavaVM *jvm);
c470ae86
MC
217 ~ScopedEnv();
218 JNIEnv* operator-> () { return env; }
219 operator bool () const { return (bool)env; }
220 private:
221 JavaVM *jvm;
222 JNIEnv *env;
223 int env_status;
224 };
225 ScopedEnv::ScopedEnv(JavaVM *jvm) : jvm(jvm), env(NULL) {
226 env_status = jvm->GetEnv((void **)&env, JNI_VERSION_1_2);
227 if (env_status == JNI_EDETACHED) {
228%#if defined(__ANDROID__)
229 jvm->AttachCurrentThread(&env, NULL);
230%#else
231 jvm->AttachCurrentThread((void **)&env, NULL);
232%#endif
233 }
234 }
235 ScopedEnv::~ScopedEnv() {
236 if (env_status == JNI_EDETACHED) {
237 jvm->DetachCurrentThread();
238 }
239 }
240}
241}
242
e13648d0
MC
243/* "Smartpointer" for Java references. */
244
245%inline {
246namespace {
247 class GlobalRefBase
248 {
249 protected:
250 GlobalRefBase (JavaVM *jvm, jobject ref);
e13648d0
MC
251 ~GlobalRefBase ();
252 JavaVM *jvm;
253 jobject jref;
254 };
255 GlobalRefBase::GlobalRefBase (JavaVM *jvm, jobject ref) : jvm(jvm), jref(0) {
256 ScopedEnv env(jvm);
257 if (env && ref)
258 jref = env->NewGlobalRef(ref);
259 }
260 GlobalRefBase::~GlobalRefBase () {
261 ScopedEnv env(jvm);
262 if(env && jref)
263 env->DeleteGlobalRef(jref);
264 }
265 template <class Jtype>
266 class GlobalRef : private GlobalRefBase
267 {
268 public:
269 GlobalRef (JavaVM *jvm, Jtype ref) : GlobalRefBase(jvm, ref) {}
270 GlobalRef (const GlobalRef &ref) : GlobalRefBase(ref.jvm, ref.jref) {}
271 operator Jtype () const { return static_cast<Jtype>(jref); }
272 };
273}
274}
275
9fcf4d0b
ML
276/* Support Java log callbacks. */
277
90bd7656
ML
278%typemap(javaimports) sigrok::Context
279 "import org.sigrok.core.interfaces.LogCallback;"
280
9fcf4d0b
ML
281%inline {
282typedef jobject jlogcallback;
283}
284
285%typemap(jni) jlogcallback "jlogcallback"
286%typemap(jtype) jlogcallback "LogCallback"
287%typemap(jstype) jlogcallback "LogCallback"
288%typemap(javain) jlogcallback "$javainput"
289
290%extend sigrok::Context
291{
292 void add_log_callback(JNIEnv *env, jlogcallback obj)
293 {
c470ae86
MC
294 JavaVM *jvm = NULL;
295 env->GetJavaVM(&jvm);
9fcf4d0b
ML
296 jclass obj_class = env->GetObjectClass(obj);
297 jmethodID method = env->GetMethodID(obj_class, "run",
298 "(Lorg/sigrok/core/classes/LogLevel;Ljava/lang/String;)V");
e13648d0 299 GlobalRef<jclass> LogLevel(jvm, env->FindClass("org/sigrok/core/classes/LogLevel"));
9fcf4d0b 300 jmethodID LogLevel_init = env->GetMethodID(LogLevel, "<init>", "(JZ)V");
e13648d0 301 GlobalRef<jobject> obj_ref(jvm, obj);
9fcf4d0b
ML
302
303 $self->set_log_callback([=] (
304 const sigrok::LogLevel *loglevel,
305 std::string message)
306 {
c470ae86
MC
307 ScopedEnv env(jvm);
308 if (!env)
309 throw sigrok::Error(SR_ERR);
908aad38 310 jlong loglevel_addr = 0;
32fd1edc 311 *(const sigrok::LogLevel **) &loglevel_addr = loglevel;
9fcf4d0b
ML
312 jobject loglevel_obj = env->NewObject(
313 LogLevel, LogLevel_init, loglevel_addr, false);
314 jobject message_obj = env->NewStringUTF(message.c_str());
315 env->CallVoidMethod(obj_ref, method, loglevel_obj, message_obj);
316 if (env->ExceptionCheck())
317 throw sigrok::Error(SR_ERR);
318 });
319 }
320}
321
322/* Support Java datafeed callbacks. */
323
90bd7656
ML
324%typemap(javaimports) sigrok::Session
325 "import org.sigrok.core.interfaces.DatafeedCallback;"
326
9fcf4d0b
ML
327%inline {
328typedef jobject jdatafeedcallback;
329}
330
331%typemap(jni) jdatafeedcallback "jdatafeedcallback"
332%typemap(jtype) jdatafeedcallback "DatafeedCallback"
333%typemap(jstype) jdatafeedcallback "DatafeedCallback"
334%typemap(javain) jdatafeedcallback "$javainput"
335
336%extend sigrok::Session
337{
338 void add_datafeed_callback(JNIEnv *env, jdatafeedcallback obj)
339 {
c470ae86
MC
340 JavaVM *jvm = NULL;
341 env->GetJavaVM(&jvm);
9fcf4d0b
ML
342 jclass obj_class = env->GetObjectClass(obj);
343 jmethodID method = env->GetMethodID(obj_class, "run",
344 "(Lorg/sigrok/core/classes/Device;Lorg/sigrok/core/classes/Packet;)V");
e13648d0 345 GlobalRef<jclass> Device(jvm, env->FindClass("org/sigrok/core/classes/Device"));
9fcf4d0b 346 jmethodID Device_init = env->GetMethodID(Device, "<init>", "(JZ)V");
e13648d0 347 GlobalRef<jclass> Packet(jvm, env->FindClass("org/sigrok/core/classes/Packet"));
9fcf4d0b 348 jmethodID Packet_init = env->GetMethodID(Packet, "<init>", "(JZ)V");
e13648d0 349 GlobalRef<jobject> obj_ref(jvm, obj);
9fcf4d0b
ML
350
351 $self->add_datafeed_callback([=] (
352 std::shared_ptr<sigrok::Device> device,
353 std::shared_ptr<sigrok::Packet> packet)
354 {
c470ae86
MC
355 ScopedEnv env(jvm);
356 if (!env)
357 throw sigrok::Error(SR_ERR);
908aad38
MC
358 jlong device_addr = 0;
359 jlong packet_addr = 0;
32fd1edc
MC
360 *(std::shared_ptr<sigrok::Device> **) &device_addr =
361 new std::shared_ptr<sigrok::Device>(device);
362 *(std::shared_ptr<sigrok::Packet> **) &packet_addr =
363 new std::shared_ptr<sigrok::Packet>(packet);
9fcf4d0b
ML
364 jobject device_obj = env->NewObject(
365 Device, Device_init, device_addr, true);
366 jobject packet_obj = env->NewObject(
367 Packet, Packet_init, packet_addr, true);
368 env->CallVoidMethod(obj_ref, method, device_obj, packet_obj);
369 if (env->ExceptionCheck())
370 throw sigrok::Error(SR_ERR);
371 });
372 }
373}
374
bd4fda24 375%include "doc.i"
062430a2 376
7a36ceac
ML
377%define %enumextras(Class)
378%enddef
379
c7855def 380/* Ignore these for now, need fixes. */
dd13d47a 381%ignore sigrok::Context::create_analog_packet;
c7855def 382%ignore sigrok::Context::create_meta_packet;
d0fa4ac1 383%ignore sigrok::Meta::config;
b71356d6 384
9fcf4d0b 385%include "bindings/swig/classes.i"
b71356d6 386