Skip to content

Instantly share code, notes, and snippets.

@kkirby
Created December 1, 2015 22:34
Show Gist options
  • Save kkirby/cae573932d0edfc7e361 to your computer and use it in GitHub Desktop.
Save kkirby/cae573932d0edfc7e361 to your computer and use it in GitHub Desktop.
#include "JavaClass.h"
size_t allocations;
map<int,JavaClass*> JavaClass::instances;
JavaClass::JavaClass(const char* inputJavaClassName): javaClassName(inputJavaClassName), refid(allocations++) {
JavaClass::instances.insert(std::pair<int,JavaClass*>(refid,this));
JNIEnv *env = ofGetJNIEnv();
jclass clazz = getJavaClass();
jmethodID javaConstructor = JavaClass::getMethodID(clazz,"<init>","I","V");
if(!javaConstructor){
ofLogError("JavaClass") << " couldn't find constructor for " << javaClassName << ".\n";
return;
}
javaObject = env->NewObject(clazz,javaConstructor,refid);
if(!javaObject){
ofLogError("JavaClass") << " couldn't create instance for " << javaClassName << ".\n";
return;
}
javaObject = (jobject)env->NewGlobalRef(javaObject);
}
JavaClass::~JavaClass(){
ofGetJNIEnv()->DeleteGlobalRef(javaObject);
JavaClass::instances.erase(refid);
}
jclass JavaClass::getJavaClass(){
jclass javaClass = ofGetJNIEnv()->FindClass(javaClassName);
if(!javaClass){
ofLogError("JavaObject::getJavaClass") << "unable to find " << javaClassName << " class.";
}
return javaClass;
}
// Static
/*static*/ const char* JavaClass::createSignature(const char* params,const char* returnType){
char* result = new char[strlen(params) + 2 + strlen(returnType)];
sprintf(result,"(%s)%s",params,returnType);
return result;
}
//- getMethodID
//--- With class
/*static*/ jmethodID JavaClass::getMethodID(jclass clazz,const char* name,const char* signature){
return ofGetJNIEnv()->GetMethodID(clazz,name,signature);
}
/*static*/ jmethodID JavaClass::getMethodID(jclass clazz,const char* name,const char* params,const char* returnType){
return JavaClass::getMethodID(clazz,name,JavaClass::createSignature(params,returnType));
}
//--- With object
/*static*/ jmethodID JavaClass::getMethodID(jobject object,const char* name,const char* signature){
return JavaClass::getMethodID(ofGetJNIEnv()->GetObjectClass(object),name,signature);
}
/*static*/ jmethodID JavaClass::getMethodID(jobject object,const char* name,const char* params,const char* returnType){
return JavaClass::getMethodID(ofGetJNIEnv()->GetObjectClass(object),name,params,returnType);
}
//- getFieldID
//--- With class
/*static*/ jfieldID JavaClass::getFieldID(jclass clazz,const char* name,const char* type){
return ofGetJNIEnv()->GetFieldID(clazz,name,type);
}
//--- With object
/*static*/ jfieldID JavaClass::getFieldID(jobject object,const char* name,const char* type){
return ofGetJNIEnv()->GetFieldID(ofGetJNIEnv()->GetObjectClass(object),name,type);
}
//-Other
/*static*/ jobject JavaClass::getObjectField(jobject object,const char* fieldName,const char* returnType){
return ofGetJNIEnv()->GetObjectField(object,JavaClass::getFieldID(object,fieldName,returnType));
}
/*static*/ void JavaClass::setObjectField(jobject object,const char* fieldName,const char* returnType,jobject value){
ofGetJNIEnv()->SetObjectField(object,JavaClass::getFieldID(object,fieldName,returnType),value);
}
// Members
jmethodID JavaClass::getMethodID(const char* name,const char* signature){
return JavaClass::getMethodID(javaObject,name,signature);
}
jmethodID JavaClass::getMethodID(const char* name,const char* params,const char* returnType){
return JavaClass::getMethodID(javaObject,name,params,returnType);
}
jfieldID JavaClass::getFieldID(const char* name,const char* type){
return JavaClass::getFieldID(javaObject,name,type);
}
jobject JavaClass::getObjectField(const char* fieldName,const char* returnType){
return JavaClass::getObjectField(javaObject,fieldName,returnType);
}
void JavaClass::setObjectField(const char* fieldName,const char* returnType,jobject value){
JavaClass::setObjectField(javaObject,fieldName,returnType,value);
}
// Macros
createGetSetFieldMethod(jboolean,Boolean,"Z");
createGetSetFieldMethod(jbyte,Byte,"B");
createGetSetFieldMethod(jchar,Char,"C");
createGetSetFieldMethod(jshort,Short,"S");
createGetSetFieldMethod(jint,Int,"I");
createGetSetFieldMethod(jfloat,Float,"J");
createGetSetFieldMethod(jdouble,Double,"D");
#pragma once
#include <jni.h>
#include <ofMain.h>
#include "ofxAndroid.h"
// CallMethod
#define createCallMethod(returnType,type,shortType) \
template<typename... Args> static returnType call ## type ## Method(jobject object,const char* method,const char* params,Args... args){ \
return ofGetJNIEnv()->Call ## type ## Method(object,JavaClass::getMethodID(object,method,params,shortType),args...); \
} \
template<typename... Args> returnType call ## type ## Method(const char* method,const char* params,Args... args){ \
return JavaClass::call ## type ## Method(javaObject,method,params,args...); \
}
// GetField
#define createGetFieldMethodHeader(returnType,type) \
static returnType get ## type ## Field(jobject object,const char* fieldName); \
returnType get ## type ## Field(const char* fieldName);
#define createGetFieldMethod(returnType,type,shortType) \
/*static*/ returnType JavaClass::get ## type ## Field(jobject object,const char* fieldName){ \
return ofGetJNIEnv()->Get ## type ## Field(object,JavaClass::getFieldID(object,fieldName,shortType)); \
} \
returnType JavaClass::get ## type ## Field(const char* fieldName){ \
return JavaClass::get ## type ## Field(javaObject,fieldName); \
}
// SetField
#define createSetFieldMethodHeader(returnType,type) \
static void set ## type ## Field(jobject object,const char* fieldName,returnType value); \
void set ## type ## Field(const char* fieldName,returnType value);
#define createSetFieldMethod(fieldType,type,shortType) \
/*static*/ void JavaClass::set ## type ## Field(jobject object,const char* fieldName,fieldType value){ \
ofGetJNIEnv()->Set ## type ## Field(object,JavaClass::getFieldID(object,fieldName,shortType),value); \
} \
void JavaClass::set ## type ## Field(const char* fieldName,fieldType value){ \
JavaClass::set ## type ## Field(javaObject,fieldName,value); \
}
// GetSet
#define createGetSetFieldMethodHeader(returnType,type) \
createGetFieldMethodHeader(returnType,type); \
createSetFieldMethodHeader(returnType,type);
#define createGetSetFieldMethod(returnType,type,shortType) \
createGetFieldMethod(returnType,type,shortType); \
createSetFieldMethod(returnType,type,shortType);
class JavaClass {
private:
static map<int,JavaClass*> instances;
size_t refid;
protected:
const char* javaClassName;
jobject javaObject;
jclass getJavaClass();
public:
JavaClass(const char* javaClassName);
~JavaClass();
// Static
static const char* createSignature(const char* params,const char* returnType);
static jmethodID getMethodID(jclass clazz,const char* name,const char* signature);
static jmethodID getMethodID(jclass clazz,const char* name,const char* params,const char* returnType);
static jmethodID getMethodID(jobject object,const char* name,const char* signature);
static jmethodID getMethodID(jobject object,const char* name,const char* params,const char* returnType);
static jfieldID getFieldID(jclass clazz,const char* name,const char* type);
static jfieldID getFieldID(jobject object,const char* name,const char* type);
template<typename... Args> static jobject callObjectMethod(jobject object,const char* method,const char* params,const char* returnType,Args... args){
return ofGetJNIEnv()->CallObjectMethod(object,JavaClass::getMethodID(object,method,params,returnType),args...);
}
static jobject getObjectField(jobject object,const char* fieldName,const char* returnType);
static void setObjectField(jobject object,const char* fieldName,const char* type,jobject value);
// Instance
jmethodID getMethodID(const char* name,const char* signature);
jmethodID getMethodID(const char* name,const char* params,const char* returnType);
jfieldID getFieldID(const char* name,const char* type);
template<typename... Args> jobject callObjectMethod(const char* method,const char* params,const char* returnType,Args... args){
return JavaClass::callObjectMethod(javaObject,method,params,returnType,args...);
}
jobject getObjectField(const char* fieldName,const char* returnType);
void setObjectField(const char* fieldName,const char* type,jobject value);
// Macros
createCallMethod(void,Void,"V");
createCallMethod(jboolean,Boolean,"Z");
createCallMethod(jbyte,Byte,"B");
createCallMethod(jchar,Char,"C");
createCallMethod(jshort,Short,"S");
createCallMethod(jint,Int,"I");
createCallMethod(jfloat,Float,"J");
createCallMethod(jdouble,Double,"D");
createGetSetFieldMethodHeader(jboolean,Boolean);
createGetSetFieldMethodHeader(jbyte,Byte);
createGetSetFieldMethodHeader(jchar,Char);
createGetSetFieldMethodHeader(jshort,Short);
createGetSetFieldMethodHeader(jint,Int);
createGetSetFieldMethodHeader(jfloat,Float);
createGetSetFieldMethodHeader(jdouble,Double);
template<typename Type> static Type* getNative(jobject object){
int id = JavaClass::getIntField(object,"refid");
try {
return (Type*)JavaClass::instances[id];
}
catch(out_of_range e){
ofLogError("JavaClass") << " couldn't find instance for id " << id << " it has probably been destroyed.\n";
}
return nullptr;
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment