Browse Source

completing C++ message

JNI-44
Volker Birk 10 years ago
parent
commit
5afe57ad02
  1. 13
      src/Test.java
  2. 115
      src/gen_cpp_Message.ysl2
  3. 96
      src/jniutils.cc
  4. 31
      src/jniutils.hh

13
src/Test.java

@ -1,13 +0,0 @@
import org.pEp.jniadapter.*;
public class Test {
public static void main(String[] args) {
try (Engine pEp = new Engine()) {
// using pEp engine
}
catch (pEpException e) {
}
}
}

115
src/gen_cpp_Message.ysl2

@ -3,7 +3,7 @@ include yslt.yml2
tstylesheet {
include ./types_c.ysl2
template "/namespace[@name='pEp']" apply "struct|interface", 0;
template "/namespace[@name='pEp']" apply "struct", 0;
template "struct" {
const "jname" call "CamelCase" with "text", "@name";
@ -11,6 +11,7 @@ tstylesheet {
document("org_pEp_jniadapter_{$jname}.cc", "text")
||
#include <exception>
#include <new>
#include <stdint.h>
#include <assert.h>
#include <pEp/«@name».h>
@ -18,74 +19,112 @@ tstylesheet {
#include "jniutils.hh"
#include "org_pEp_jniadapter_«$jname».h"
using namespace std;
namespace pEp {
namespace JNIAdapter {
static ::«@name» *«@name»_ptr(JNIEnv *env, jobject me) {
jfieldID handle;
try {
handle = getFieldID(env, "org/pEp/jniadapter/«$jname»", "handle", "J");
}
catch (std::exception& ex) {
assert(0);
return NULL;
}
return (::«@name» *) (intptr_t) (int64_t) env->GetLongField(me, handle);
}
};
};
extern "C" {
using namespace pEp::JNIAdapter;
JNIEXPORT jlong JNICALL
Java_org_pEp_jniadapter_«$jname»_init(JNIEnv *env, jobject obj) {
::«@name» * _obj = ::new_«@name»(PEP_dir_incoming);
// BUG: test for out of memory missing
if (!_obj) {
outOfMemory(env);
return (jlong) 0;
}
return (jlong) (int64_t) (intptr_t) _obj;
}
JNIEXPORT void JNICALL
Java_org_pEp_jniadapter_«$jname»_release(JNIEnv *env, jobject obj, jlong value) {
::«@name» *_obj = (::«@name» *) (intptr_t) (int64_t) value;
::free_«@name»(_obj);
}
static ::«@name» *ptr(JNIEnv *env, jobject me) {
jfieldID handle;
try {
handle = getFieldID(env, "org/pEp/jniadapter/«$jname»", "handle", "J");
}
catch (std::exception& ex) {
assert(0);
return NULL;
if (value) {
::«@name» *_obj = (::«@name» *) (intptr_t) (int64_t) value;
::free_«@name»(_obj);
}
return (::«@name» *) (intptr_t) (int64_t) env->GetLongField(me, handle);
}
`` apply "*[name(.)!='enum']", 0, mode=entry with "class" call "CamelCase" with "text", "@name";
||
}
template "interface" {
const "jname" call "CamelCase" with "text", "@name";
document("org_pEp_jniadapter_{$jname}.cc", "text")
||
#include "org_pEp_jniadapter_«$jname».h"
`` apply "*[name(.)!='enum']", 0, mode=entry with "name", "@name", with "class" call "CamelCase" with "text", "@name";
} // extern "C"
||
}
template "*", mode=entry {
param "name";
param "class";
const "_class" call "lcase" with "text", "$class";
const "ctype" call "toC" with "type", "name(.)";
const "jname" call "CamelCase" with "text", "name(*[1])";
const "cname" call "lcase" with "text", "name(*[1])";
const "type", "name(.)";
||
JNIEXPORT jobject JNICALL
JNIEXPORT `call "jni_type" with "type", "name(.)"` JNICALL
Java_org_pEp_jniadapter_«$class»_get«$jname»(JNIEnv *env, jobject obj) {
«$_class» *_obj = ptr(env, obj);
jobject result = NULL;
_obj->«$cname»;
return result;
«$name» *_obj = «$name»_ptr(env, obj);
||
choose {
when "../enum[@name=$type]"
|> return (jint) _obj->«$cname»;
otherwise
|> return from_«$type»(env, _obj->«$cname»);
}
||
}
JNIEXPORT void JNICALL
Java_org_pEp_jniadapter_Message_set«$jname»(JNIEnv *env, jobject obj, jobject value) {
«$_class» *_obj = ptr(env, obj);
«$ctype» *_value;
_obj->«$cname»;
Java_org_pEp_jniadapter_Message_set«$jname»(JNIEnv *env, jobject obj, `call "jni_type" with "type", "name(.)"` value) {
«$name» *_obj = «$name»_ptr(env, obj);
||
choose {
when "../enum[@name=$type]"
|> _obj->«$cname» = («$ctype») (int) value;
when "$type = 'string'" {
|> free(_obj->«$cname»);
|> _obj->«$cname» = to_«$type»(env, value);
}
otherwise {
const "free" choose {
when "$ctype = 'pEp_identity'" > identity
when "contains($ctype, '_t')" value "substring-before($ctype, '_t')";
otherwise value "$ctype";
}
|> free_«$free»(_obj->«$cname»);
|> _obj->«$cname» = to_«$type»(env, value);
}
}
||
}
||
}
function "jni_type" {
param "type";
choose {
when "../enum[@name=$type]" > jint
when "$type = 'string'" > jbyteArray
otherwise > jobject
}
}
}

96
src/jniutils.cc

@ -7,24 +7,31 @@
namespace pEp {
namespace JNIAdapter {
jfieldID getFieldID(
JNIEnv *env,
const char *classname,
const char *fieldname,
const char *signature
)
jclass findClass(JNIEnv *env, const char *classname)
{
jclass engine = env->FindClass(classname);
assert(engine);
jclass clazz = env->FindClass(classname);
assert(clazz);
if (engine == NULL) {
if (clazz == NULL) {
jclass ex = env->FindClass("java/lang/NoClassDefFoundError");
assert(ex);
env->ThrowNew(ex, classname);
throw std::bad_cast();
}
return clazz;
}
jfieldID field = env->GetFieldID(engine, fieldname, signature);
jfieldID getFieldID(
JNIEnv *env,
const char *classname,
const char *fieldname,
const char *signature
)
{
jclass clazz = findClass(env, classname);
jfieldID field = env->GetFieldID(clazz, fieldname, signature);
assert(field);
if (field == NULL) {
@ -36,6 +43,75 @@ namespace pEp {
return field;
}
jlong callLongMethod(
JNIEnv *env,
jobject obj,
const char *methodname
)
{
jclass clazz = env->GetObjectClass(obj);
assert(clazz);
jmethodID method = env->GetMethodID(clazz, methodname, "()J");
if (method == NULL) {
jclass ex = env->FindClass("java/lang/NoSuchMethodError");
assert(ex);
env->ThrowNew(ex, methodname);
throw std::invalid_argument(std::string(methodname));
}
return env->CallLongMethod(obj, method);
}
jint outOfMemory(JNIEnv *env)
{
jclass ex;
const char *ex_name = "java/lang/OutOfMemoryError";
ex = env->FindClass(ex_name);
assert(ex);
return env->ThrowNew(ex, ex_name);
}
jbyteArray from_string(JNIEnv *env, const char *str)
{
if (str && str[0]) {
bool isCopy;
jbyteArray _str = NewByteArray(env, strlen(str));
jbyte *b = GetByteArrayElements(env, str, &isCopy);
strcpy((char *)b, str);
ReleaseByteArrayElements(env, str, b, 0);
return _str;
}
else {
return NewByteArray(env, 0);
}
}
char *to_string(JNIEnv *env, jbyteArray str)
{
bool isCopy;
jbyte *b = GetByteArrayElements(env, str, &isCopy);
char *_str = strndup((char *)b, (size_t)GetArrayLength(env, str));
ReleaseByteArrayElements(env, str, b, JNI_ABORT);
return _str;
}
jobject from_timestamp(JNIEnv *env, timestamp *ts)
{
time_t t = timegm(ts);
jclass clazz = findClass(env, "java/util/Date");
jmethodID constructor = env->GetMethodID(clazz, "<init>", "(J)V");
assert(constructor);
return env->NewObject(clazz, constructor, (jlong) t);
}
timestamp *to_timestamp(JNIEnv *env, jobject date)
{
time_t t = (time_t) callLongMethod(env, date, "getTime");
return new_timestamp(t);
}
};
};

31
src/jniutils.hh

@ -4,12 +4,43 @@
namespace pEp {
namespace JNIAdapter {
jclass findClass(JNIEnv *env, const char *classname);
jfieldID getFieldID(
JNIEnv *env,
const char *classname,
const char *fieldname,
const char *signature
);
jlong callLongMethod(
JNIEnv *env,
jobject obj,
const char *methodname
);
jint outOfMemory(JNIEnv *env);
jbyteArray from_string(JNIEnv *env, const char *str);
char *to_string(JNIEnv *env, jbyteArray str);
jobject from_stringlist(JNIEnv *env, stringlist_t *sl);
stringlist_t *to_stringlist(JNIEnv *env, jobject sl);
jobject from_stringpairlist(JNIEnv *env, stringpair_list_t *sl);
stringpair_list_t *to_stringpairlist(JNIEnv *env, jobject sl);
jobject from_timestamp(JNIEnv *env, timestamp *ts);
timestamp *to_timestamp(JNIEnv *env, jobject date);
jobject from_identity(JNIEnv *env, pEp_identity *ident);
pEp_identity *to_identity(JNIEnv *env, jobject ident);
jobject from_identitylist(JNIEnv *env, identity_list *il);
identity_list *to_identitylist(JNIEnv *env, jobject il);
jobject from_bloblist(JNIEnv *env, bloblist_t *bl);
bloblist_t *to_bloblist(JNIEnv *env, jobject bl);
};
};

Loading…
Cancel
Save