%module classes /* Automatically load JNI library. */ %pragma(java) jniclasscode=%{ static { System.loadLibrary("sigrok_java_core_classes"); } %} /* Documentation & importing interfaces. */ %pragma(java) jniclassimports=%{ /** * @mainpage API Reference * * Introduction * ------------ * * The sigrok-java API provides an object-oriented Java interface to the * functionality in libsigrok. It is built on top of the libsigrokcxx C++ API. * * Getting started * --------------- * * Usage of the sigrok-java API needs to begin with a call to Context.create(). * This will create the global libsigrok context and returns a Context object. * Methods on this object provide access to the hardware drivers, input and * output formats supported by the library, as well as means of creating other * objects such as sessions and triggers. * * Error handling * -------------- * * When any libsigrok C API call returns an error, an Error exception is raised, * which provides access to the error code and description. */ import org.sigrok.core.interfaces.LogCallback; import org.sigrok.core.interfaces.DatafeedCallback; %} /* Map Glib::VariantBase to a Variant class in Java */ %rename(Variant) VariantBase; namespace Glib { class VariantBase {}; } /* Map between std::vector and java.util.Vector */ %define VECTOR(CValue, JValue) %typemap(jni) std::vector< CValue > "jobject" %typemap(jtype) std::vector< CValue > "java.util.Vector" %typemap(jstype) std::vector< CValue > "java.util.Vector" %typemap(javain, pre=" $javaclassname temp$javainput = $javaclassname.convertVector($javainput);", pgcppname="temp$javainput") std::vector< CValue > "$javaclassname.getCPtr(temp$javainput)" %typemap(javacode) std::vector< CValue > %{ static $javaclassname convertVector(java.util.Vector in) { $javaclassname out = new $javaclassname(); for (JValue value : in) out.add(value); return out; } %} %typemap(javaout) std::vector< CValue > { return (java.util.Vector)$jnicall; } %typemap(out) std::vector< CValue > { jclass Vector = jenv->FindClass("java/util/Vector"); jmethodID Vector_init = jenv->GetMethodID(Vector, "", "()V"); jmethodID Vector_add = jenv->GetMethodID(Vector, "add", "(Ljava/lang/Object;)Z"); jclass Value = jenv->FindClass("org/sigrok/core/classes/" #JValue); jmethodID Value_init = jenv->GetMethodID(Value, "", "(JZ)V"); $result = jenv->NewObject(Vector, Vector_init); jlong value; for (auto entry : $1) { *(CValue **) &value = new CValue(entry); jenv->CallObjectMethod($result, Vector_add, jenv->NewObject(Value, Value_init, value, true)); } } %enddef VECTOR(std::shared_ptr, Channel) VECTOR(std::shared_ptr, HardwareDevice) /* Common macro for mapping between std::map and java.util.Map */ %define MAP_COMMON(CKey, CValue, JKey, JValue) %typemap(jstype) std::map< CKey, CValue > "java.util.Map" %typemap(javain, pre=" $javaclassname temp$javainput = $javaclassname.convertMap($javainput);", pgcppname="temp$javainput") std::map< CKey, CValue > "$javaclassname.getCPtr(temp$javainput)" %typemap(javacode) std::map< CKey, CValue > %{ static $javaclassname convertMap(java.util.Map in) { $javaclassname out = new $javaclassname(); for (java.util.Map.Entry entry : in.entrySet()) out.set(entry.getKey(), entry.getValue()); return out; } %} %typemap(javaout) std::map< CKey, CValue > { return (java.util.Map)$jnicall; } %enddef /* Specialisation for string->string maps. */ MAP_COMMON(std::string, std::string, String, String) %typemap(jni) std::map "jobject" %typemap(jtype) std::map "java.util.Map" %typemap(out) std::map { jclass HashMap = jenv->FindClass("java/util/HashMap"); jmethodID init = jenv->GetMethodID(HashMap, "", "()V"); jmethodID put = jenv->GetMethodID(HashMap, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); $result = jenv->NewObject(HashMap, init); for (auto entry : $1) jenv->CallObjectMethod($result, put, jenv->NewStringUTF(entry.first.c_str()), jenv->NewStringUTF(entry.second.c_str())); } /* Specialisation macro for string->shared_ptr maps. */ %define STRING_TO_SHARED_PTR_MAP(ClassName) %typemap(jni) std::map > "jobject" %typemap(jtype) std::map > "java.util.Map" MAP_COMMON(std::string, std::shared_ptr, String, ClassName) %typemap(out) std::map > { jclass HashMap = jenv->FindClass("java/util/HashMap"); jmethodID HashMap_init = jenv->GetMethodID(HashMap, "", "()V"); jmethodID HashMap_put = jenv->GetMethodID(HashMap, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); jclass Value = jenv->FindClass("org/sigrok/core/classes/" #ClassName); jmethodID Value_init = jenv->GetMethodID(Value, "", "(JZ)V"); $result = jenv->NewObject(HashMap, HashMap_init); jlong value; for (auto entry : $1) { *(std::shared_ptr< sigrok::ClassName > **)&value = new std::shared_ptr< sigrok::ClassName>(entry.second); jenv->CallObjectMethod($result, HashMap_put, jenv->NewStringUTF(entry.first.c_str()), jenv->NewObject(Value, Value_init, value, true)); } } %enddef STRING_TO_SHARED_PTR_MAP(Driver) STRING_TO_SHARED_PTR_MAP(InputFormat) STRING_TO_SHARED_PTR_MAP(OutputFormat) /* Specialisation for ConfigKey->Variant maps */ MAP_COMMON(const sigrok::ConfigKey *, Glib::VariantBase, ConfigKey, Variant) %typemap(jni) std::map "jobject" %typemap(jtype) std::map "java.util.Map" %typemap(out) std::map { jclass HashMap = jenv->FindClass("java/util/HashMap"); jmethodID HashMap_init = jenv->GetMethodID(HashMap, "", "()V"); jmethodID HashMap_put = jenv->GetMethodID(HashMap, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); jclass ConfigKey = jenv->FindClass("org/sigrok/core/classes/ConfigKey"); jmethodID ConfigKey_init = jenv->GetMethodID(ConfigKey, "", "(JZ)V"); jclass Variant = jenv->FindClass("org/sigrok/core/classes/Variant"); jmethodID Variant_init = jenv->GetMethodID(Variant, "", "(JZ)V"); $result = jenv->NewObject(HashMap, HashMap_init); jlong key; jlong value; for (auto entry : $1) { *(const sigrok::ConfigKey **) &key = entry.first; *(Glib::VariantBase **) &value = new Glib::VariantBase(entry.second); jenv->CallObjectMethod($result, HashMap_put, jenv->NewObject(ConfigKey, ConfigKey_init, key, false)); jenv->NewObject(Variant, Variant_init, value, true)); } } /* Support Driver.scan() with no arguments. */ %ignore sigrok::Driver::scan; %extend sigrok::Driver { std::vector > scan() { std::map options; return $self->scan(options); } std::vector > scan( std::map options) { return $self->scan(options); } } /* Support InputFormat.create_input() with or without options. */ %ignore sigrok::InputFormat::create_input; %extend sigrok::InputFormat { std::shared_ptr create_input() { return $self->create_input(); } std::shared_ptr create_input( std::map options) { return $self->create_input(options); } } /* Support OutputFormat.create_output() with or without options. */ %ignore sigrok::OutputFormat::create_output; %extend sigrok::OutputFormat { std::shared_ptr create_output( std::shared_ptr device) { return $self->create_output(device); } std::shared_ptr create_output( std::shared_ptr device, std::map options) { return $self->create_output(device, options); } std::shared_ptr create_output( std::string filename, std::shared_ptr device) { return $self->create_output(filename, device); } std::shared_ptr create_output( std::string filename, std::shared_ptr device, std::map options) { return $self->create_output(filename, device, options); } } /* Pass JNIEnv parameter to C++ extension methods requiring it. */ %typemap(in, numinputs=0) JNIEnv * %{ $1 = jenv; %} /* Support Java log callbacks. */ %typemap(javaimports) sigrok::Context "import org.sigrok.core.interfaces.LogCallback;" %inline { typedef jobject jlogcallback; } %typemap(jni) jlogcallback "jlogcallback" %typemap(jtype) jlogcallback "LogCallback" %typemap(jstype) jlogcallback "LogCallback" %typemap(javain) jlogcallback "$javainput" %extend sigrok::Context { void add_log_callback(JNIEnv *env, jlogcallback obj) { jclass obj_class = env->GetObjectClass(obj); jmethodID method = env->GetMethodID(obj_class, "run", "(Lorg/sigrok/core/classes/LogLevel;Ljava/lang/String;)V"); jclass LogLevel = (jclass) env->NewGlobalRef( env->FindClass("org/sigrok/core/classes/LogLevel")); jmethodID LogLevel_init = env->GetMethodID(LogLevel, "", "(JZ)V"); jobject obj_ref = env->NewGlobalRef(obj); $self->set_log_callback([=] ( const sigrok::LogLevel *loglevel, std::string message) { jlong loglevel_addr; *(const sigrok::LogLevel **) &loglevel_addr = loglevel; jobject loglevel_obj = env->NewObject( LogLevel, LogLevel_init, loglevel_addr, false); jobject message_obj = env->NewStringUTF(message.c_str()); env->CallVoidMethod(obj_ref, method, loglevel_obj, message_obj); if (env->ExceptionCheck()) throw sigrok::Error(SR_ERR); }); } } /* Support Java datafeed callbacks. */ %typemap(javaimports) sigrok::Session "import org.sigrok.core.interfaces.DatafeedCallback;" %inline { typedef jobject jdatafeedcallback; } %typemap(jni) jdatafeedcallback "jdatafeedcallback" %typemap(jtype) jdatafeedcallback "DatafeedCallback" %typemap(jstype) jdatafeedcallback "DatafeedCallback" %typemap(javain) jdatafeedcallback "$javainput" %extend sigrok::Session { void add_datafeed_callback(JNIEnv *env, jdatafeedcallback obj) { jclass obj_class = env->GetObjectClass(obj); jmethodID method = env->GetMethodID(obj_class, "run", "(Lorg/sigrok/core/classes/Device;Lorg/sigrok/core/classes/Packet;)V"); jclass Device = (jclass) env->NewGlobalRef( env->FindClass("org/sigrok/core/classes/Device")); jmethodID Device_init = env->GetMethodID(Device, "", "(JZ)V"); jclass Packet = (jclass) env->NewGlobalRef( env->FindClass("org/sigrok/core/classes/Packet")); jmethodID Packet_init = env->GetMethodID(Packet, "", "(JZ)V"); jobject obj_ref = env->NewGlobalRef(obj); $self->add_datafeed_callback([=] ( std::shared_ptr device, std::shared_ptr packet) { jlong device_addr; jlong packet_addr; *(std::shared_ptr **) &device_addr = new std::shared_ptr(device); *(std::shared_ptr **) &packet_addr = new std::shared_ptr(packet); jobject device_obj = env->NewObject( Device, Device_init, device_addr, true); jobject packet_obj = env->NewObject( Packet, Packet_init, packet_addr, true); env->CallVoidMethod(obj_ref, method, device_obj, packet_obj); if (env->ExceptionCheck()) throw sigrok::Error(SR_ERR); }); } } %include "doc.i" %define %attributevector(Class, Type, Name, Get) %attributeval(sigrok::Class, Type, Name, Get); %enddef %define %attributemap(Class, Type, Name, Get) %attributeval(sigrok::Class, Type, Name, Get); %enddef %define %enumextras(Class) %enddef /* Ignore this for now, needs a fix. */ %ignore sigrok::Context::create_analog_old_packet; %include "bindings/swig/classes.i"