-
Notifications
You must be signed in to change notification settings - Fork 13
/
JniForwards.h
174 lines (136 loc) · 5.23 KB
/
JniForwards.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
#pragma once
#ifndef JNI_FORWARDS_H
#define JNI_FORWARDS_H
#include <string>
#include <vector>
#include <functional>
#include <utility>
#include <algorithm>
#include <jni.h>
/*
Инструкция по передаче user-defined типа T в и из java.
I. Связывание c++ класса T с java-классом (на примере связывания std::string и java.lang.String)
1) Для построения JNI сигнатуры в JniSignatureBuilder.h реализовать структуру JniSignatureBuilder<T>:
template<>
struct JniSignatureBuilder<std::string> {
static std::string Signature() {
return "Ljava/lang/String;";
}
};
2) Для конвертации из T в joblect в JniProxy.h реализовать структуру JniToJavaProxy<T>:
// воспользуемся готовым классом JavaString, обертывающим java.lang.String напрямую через встроенные JNI функции.
template<>
struct JniToJavaProxy<std::string> {
JniToJavaProxy(JavaEnv env, const std::string& v) : val(env, v) {}
jstring Val() const { return val.Val(); }
JavaString val;
};
3) Для конвертации jobject в T в JniProxy.h реализовать структуру JniFromJavaProxy<T>:
// воспользуемся готовым классом JavaString, обертывающим java.lang.String напрямую через встроенные JNI функции.
template<>
struct JniFromJavaProxy<std::string> {
JniFromJavaProxy(JavaEnv env, jobject obj) : _env(env), _obj((jstring) obj) {}
std::string Val() const { return JavaString(_env, _obj).Value(); }
JavaEnv _env;
jstring _obj;
};
II. Связывание c++ класса T с примитивным java типом (на примере связывания класса TestJniInt с jint)
struct TestJniInt {
TestJniInt(int val) : _val(val) {}
int Val() const { return _val; }
int _val;
};
1,2,3) Выполнить вышеописанные действия для связывания с классом.
template<>
struct JniSignatureBuilder<TestJniInt> {
static std::string Signature() {
return "I";
}
};
template<>
struct JniToJavaProxy<TestJniInt> {
JniToJavaProxy(JavaEnv, const TestJniInt& v) : val(v) {}
jint Val() const { return val.Val(); }
const TestJniInt& val;
};
template<>
struct JniFromJavaProxy<TestJniInt> {
JniFromJavaProxy(JavaEnv, jint obj) : _obj(obj) {}
TestJniInt Val() const { return TestJniInt(_obj); }
jint _obj;
};
4) Для возвращения TestJniInt java методами, возвращающими jint необходимо в JniJavaMethod.h
реализовать структуры JavaMethodCaller<T> и JavaStaticMethodCaller<T>:
template<>
struct JavaMethodCaller<TestJniInt> {
typedef TestJniInt R;
template<typename ... Args>
R Call(const JavaMethod<R(Args...)>& self, Args&& ... args) {
return FromJavaProxy<R>(self.Env(), self.Env().Val()->CallIntMethod(self.GetObject().Val(), self.Val(), ToJavaProxy(self.Env(), std::forward<Args>(args)).Val()...)).Val();
}
};
template<>
struct JavaStaticMethodCaller<TestJniInt> {
typedef TestJniInt R;
template<typename ... Args>
R Call(const JavaStaticMethod<R(Args...)>& self, Args&& ... args) {
return FromJavaProxy<R>(self.Env(), self.Env().Val()->CallStaticIntMethod(self.GetObject().Val(), self.Val(), ToJavaProxy(self.Env(), std::forward<Args>(args)).Val()...)).Val();
}
};
5) Для получения и установки jint полей значением класса TestJniInt необходимо в JniJavaField.h
реализовать структуры JavaFieldHelper<T> и JavaStaticFieldHelper<T>:
template<>
struct JavaFieldHelper<TestJniInt> {
typedef TestJniInt T;
T Get(const JavaField<T>& self) {
return FromJavaProxy<T>(self.Env(), self.Env().Val()->GetIntField(self.GetObject().Val(), self.Val())).Val();
}
void Set(const JavaField<T>& self, T&& val) {
self.Env().Val()->SetIntField(self.GetObject().Val(), self.Val(), ToJavaProxy<T>(self.Env(), std::forward<T>(val)).Val());
}
};
template<>
struct JavaStaticFieldHelper<TestJniInt> {
typedef TestJniInt T;
T Get(const JavaStaticField<T>& self) {
return FromJavaProxy<T>(self.Env(), self.Env().Val()->GetStaticIntField(self.GetClass().Val(), self.Val())).Val();
}
void Set(const JavaStaticField<T>& self, T&& val) {
self.Env().Val()->SetStaticIntField(self.GetClass().Val(), self.Val(), ToJavaProxy<T>(self.Env(), std::forward<T>(val)).Val());
}
};
*/
namespace JNI {
class JniHelper;
class JniJavaVM;
class JavaEnv;
class JavaObject;
class JavaException;
class JavaClass;
class JavaString;
template<typename T>
class JavaArray;
template<typename R, typename ... Args>
class JavaMethod;
template<typename R, typename ... Args>
class JavaStaticMethod;
template<typename T>
class JavaField;
template<typename T>
class JavaStaticField;
template<typename R, typename ... Args>
struct JniSignatureBuilder;
class JavaBoolean;
template<typename T>
struct JniFromJavaProxy;
template<typename T, typename J>
static inline JniFromJavaProxy<T> FromJavaProxy(JavaEnv env, J v);
} // namespace JNI
// namespace JNI {
// struct TestJniInt {
// TestJniInt(int val) : _val(val) {}
// int Val() const { return _val; }
// int _val;
// };
// }
#endif