Classdesc  3.D29
javaClass_base.h
Go to the documentation of this file.
1 /*
2  @copyright Russell Standish 2000-2013
3  @author Russell Standish
4  This file is part of Classdesc
5 
6  Open source licensed under the MIT license. See LICENSE for details.
7 */
8 
14 #ifndef JAVACLASS_BASE_H
15 #define JAVACLASS_BASE_H
16 
17 #include "javaClass.h"
18 #include "javaClassDescriptor.h"
19 #include "object.h"
20 #include "poly.h"
21 #include <memory>
22 #include <jni.h>
23 
24 // for debugging use
25 //namespace std
26 //{
27 // template <class T, class C, class traits>
28 // basic_ostream<C,traits>& operator<<(basic_ostream<C,traits>& o, const T& x)
29 // {o<<"<unknown type>"; return o;}
30 //}
31 
32 namespace classdesc
33 {
34  template <class T> const char* javaClassName();
35  template <> inline const char* javaClassName<int>() {return "java/lang/Integer";}
36  template <> inline const char* javaClassName<float>() {return "java/lang/Float";}
37 
38  template <class T> T getJavaVal(JNIEnv *env, jobject o);
39  template <> inline int getJavaVal<int>(JNIEnv *env, jobject o) {
40  return env->CallIntMethod(o,
41  env->GetMethodID(env->GetObjectClass(o), "intValue", "()I"));
42  }
43  template <> inline float getJavaVal<float>(JNIEnv *env, jobject o) {
44  return env->CallFloatMethod(o,
45  env->GetMethodID(env->GetObjectClass(o), "floatValue", "()F"));
46  }
47  template <> inline std::string getJavaVal<std::string>(JNIEnv *env,jobject o)
48  {
49  return std::string(env->GetStringUTFChars(static_cast<jstring>(o),NULL));
50  }
51 
52  template <class T> T getJavaVal(jvalue v);
53  template <> inline bool getJavaVal<bool>(jvalue v) {return v.z;}
54  template <> inline char getJavaVal<char>(jvalue v) {return v.b;}
55  template <> inline unsigned short getJavaVal<unsigned short>(jvalue v) {return v.c;}
56  template <> inline short getJavaVal<short>(jvalue v) {return v.s;}
57  template <> inline int getJavaVal<int>(jvalue v) {return v.i;}
58  template <> inline long getJavaVal<long>(jvalue v) {return v.j;}
59  template <> inline float getJavaVal<float>(jvalue v) {return v.f;}
60  template <> inline double getJavaVal<double>(jvalue v) {return v.d;}
61 
63  struct ArgRef_base: virtual public object //Object<ArgRef_base,0>
64  {
65  virtual jobject get_jobject(JNIEnv *env) const=0;
66  virtual jint get_jint(JNIEnv *env) const {return 0;}
67  virtual jfloat get_jfloat(JNIEnv *env) const {return 0;}
68  virtual ~ArgRef_base() {};
69  };
70 
76  template <class T>
77  class ArgRef: virtual public Object<ArgRef<T>,ArgRef_base>
78  {
79  T value;
80  friend class RetRef;
81  public:
82  ArgRef() {}
83  ArgRef(const T& x): value(x) {}
84  jobject get_jobject(JNIEnv *env) const {
85  jclass clss=env->FindClass(javaClassName<T>());
86  return env->NewObject(clss,
87  env->GetMethodID(
88  clss,"<init>",
89  (std::string("(")+descriptor<T>()+")V").c_str()),
90  value);
91  }
92  jint get_jint(JNIEnv *env) const {return jint(value);}
93  jfloat get_jfloat(JNIEnv *env) const {return jfloat(value);}
94 
95  T* getRef() {return &value;}
96  };
97 
98  template <>
99  class ArgRef<void>: virtual public Object<ArgRef<void>,ArgRef_base>
100  {
101  public:
102  jobject get_jobject(JNIEnv *env) const {return NULL;}
103  void* getRef() {return NULL;}
104  };
105 }
106 #ifdef _CLASSDESC
107 #pragma omit pack classdesc::ArgRef
108 #pragma omit unpack classdesc::ArgRef
109 #pragma omit javaClass classdesc::ArgRef
110 #pragma omit javaClass classdesc::ArgRef_base
111 #endif
112 
113 namespace classdesc_access
114 {
115  //no sensible serialisation for this
116  template <class T>
117  struct access_pack<classdesc::ArgRef<T> >:
118  public classdesc::NullDescriptor<classdesc::pack_t> {};
119 
120  template <class T>
121  struct access_unpack<classdesc::ArgRef<T> >:
122  public classdesc::NullDescriptor<classdesc::unpack_t> {};
123 }
124 
125 namespace classdesc
126 {
127  //utility class for casting jobjects into C++ types
128  class Arg
129  {
130  JNIEnv *env;
131  jvalue val;
132  bool is_jobject;
133  public:
134 
135  Arg(): env(NULL), is_jobject(true) {val.l=NULL;}
136  Arg(JNIEnv *env, jobject object): env(env), is_jobject(true) {val.l=object;}
137  // Arg(JNIEnv *env, jboolean v): env(env), is_jobject(false) {val.z=v;}
138  Arg(JNIEnv *env, jbyte v): env(env), is_jobject(false) {val.b=v;}
139  Arg(JNIEnv *env, jchar v): env(env), is_jobject(false) {val.c=v;}
140  Arg(JNIEnv *env, jint v): env(env), is_jobject(false) {val.i=v;}
141  Arg(JNIEnv *env, jlong v): env(env), is_jobject(false) {val.j=v;}
142  Arg(JNIEnv *env, jfloat v): env(env), is_jobject(false) {val.f=v;}
143  Arg(JNIEnv *env, jdouble v): env(env), is_jobject(false) {val.d=v;}
144 
145  template <class T> T get() const {
146  if (is_jobject)
147  return getJavaVal<T>(env,val.l);
148  else
149  return getJavaVal<T>(val);
150  }
151 
152  //TODO: factor out get<T>()
153  operator float() {return get<float>();}
154  operator int() {return get<int>();}
155  operator std::string() {return get<std::string>();}
156 
157  //TODO: handle reference arguments
158  };
159 
161  class RetVal: public poly<ArgRef_base>
162  {
163  public:
164  template <class T> T* getRef() {
165  addObject<ArgRef<T> >();
166  return cast<ArgRef<T> >().getRef();
167  }
168  };
169 
171  template <class Jtype>
172  struct JNItype
173  {
174  template <class CppType>
175  static Jtype from(JNIEnv *env, const CppType& x) {return JNItype(x);}
176  };
177 
180  template <>
181  struct JNItype<jobject>
182  {
183  template <class CppType>
184  static jobject from(JNIEnv *env, const CppType& x)
185  {
186  jclass cls=env->FindClass("ConcreteCppObject");
187  jmethodID constructor=env->GetMethodID(cls,"<init>","()V");
188  jobject obj=env->NewObject(cls,constructor);
189  jfieldID fld=env->GetFieldID(cls,"register","Ljava/lang/Object;");
190  env->SetObjectField(obj,fld,reinterpret_cast<jobject>(new CppType(x)));
191  return obj;
192  }
193  template <class CppType>
194  static jobject from(JNIEnv *env, CppType& x)
195  {
196  jclass cls=env->FindClass("ConcreteCppObject");
197  jmethodID constructor=env->GetMethodID(cls,"<init>","()V");
198  jobject obj=env->NewObject(cls,constructor);
199  jfieldID fld=env->GetFieldID(cls,"register","Ljava/lang/Object;");
200  env->SetObjectField(obj,fld,reinterpret_cast<jobject>(&x));
201  return obj;
202  }
203  };
204 
206  template <>
207  struct JNItype<jstring>
208  {
209  static jstring from(JNIEnv *env, const char* x)
210  {
211  std::vector<jchar> tmp(x, x+strlen(x));
212  return env->NewString(&tmp[0], strlen(x));
213  }
214  static jstring from(JNIEnv *env, const std::string& x)
215  {
216  return from(env, x.c_str());
217  }
218  };
219 }
220 
221 #ifdef _CLASSDESC
222 #pragma omit pack classdesc::Arg
223 #pragma omit unpack classdesc::Arg
224 #endif
225 
226 namespace classdesc_access
227 {
228  //no sensible serialisation for this
229  template <>
230  struct access_pack<classdesc::Arg>
231  {
232  void operator()(classdesc::pack_t& t, const classdesc::string& d, classdesc::Arg& a) {}
233  };
234 
235  template <>
236  struct access_unpack<classdesc::Arg>
237  {
238  void operator()(classdesc::pack_t& t, const classdesc::string& d, classdesc::Arg& a) {}
239  };
240 }
241 
242 namespace classdesc
243 {
248  class ArgVector: public std::vector<Arg>
249  {
250  public:
251  ArgVector(size_t n=0): std::vector<Arg>(n) {}
252  ArgVector(JNIEnv* env, jobjectArray& args)
253  {
254  for (size_t i=0; args && i<size_t(env->GetArrayLength(args)); ++i)
255  push_back(classdesc::Arg(env, env->GetObjectArrayElement(args,i)));
256  }
257  };
258 
260  {
261  virtual void operator()(RetVal& ret, ArgVector& args)=0;
262  };
263 
265 
270  template <class F>
271  class Functional: public Object<Functional<F>, Functional_base>
272  {
273  F f;
274 public:
275  Functional(const F& f): f(f) {}
276  void operator()(RetVal& r, ArgVector& args) {
277  apply(r.getRef<typename functional::Return<F>::T>(), f, args);}
278  };
279 }
280 
281 #ifdef _CLASSDESC
282 #pragma omit pack classdesc::Functional
283 #pragma omit unpack classdesc::Functional
284 #endif
285 
286 namespace classdesc_access
287 {
288  //no sensible serialisation for this
289  template <class F>
290  struct access_pack<classdesc::Functional<F> >:
291  public classdesc::NullDescriptor<classdesc::pack_t> {};
292 
293  template <class F>
294  struct access_unpack<classdesc::Functional<F> >:
295  public classdesc::NullDescriptor<classdesc::unpack_t> {};
296 
297 }
298 
299 namespace classdesc
300 {
301  struct javaClass_t: public ClassFile
302  {
303  javaClass_t() {magic=0xCAFEBABE; minor_version=0; major_version=50;}
304  // add a functor to the method database
305  virtual void add_functor(const std::string& name, Functional_ptr f,
306  const std::string& sig)
307  {}
308  };
309 
310 #ifdef _CLASSDESC
311 #pragma omit javaClass classdesc::javaClass_t
312 #endif
313 
314  template <class C, class M>
315  typename enable_if<is_member_function_pointer<M>, void>::T
316  javaClass(javaClass_t& cl, const string& desc, C& obj, M mem)
317  {
318  using namespace classdesc;
319  std::string method_name(desc);
320  if (method_name.find('.')!=std::string::npos)
321  method_name=method_name.substr(method_name.rfind('.')+1);
322  cl.addMethod(method_name, descriptor<M>());
323 // cl.addMethod(method_name, std::string("([Ljava/lang/Object;)")+
324 // descriptor<typename functional::Return<M>::T>());
325  cl.add_functor(std::string(desc),
326  Functional_ptr().addObject<Functional<
329  descriptor<M>()
330  );
331  }
332 
333  template <class T, class B>
334  void javaClass(javaClass_t& cl, const string& desc, Object<T,B>& obj)
335  {
336  //TODO: maybe we want to add some default object properties here
337  }
338 
339  template <class T>
340  class getter_setter: public Object<getter_setter<T>,Functional_base>
341  {
342  T& m;
343  public:
344  getter_setter(T& m): m(m) {}
345  void operator()(RetVal& r, ArgVector& args) {
346  if (args.size()) m=args[0].get<T>(); *r.getRef<T>()=m;
347  }
348  };
349 }
350 
351 #ifdef _CLASSDESC
352 #pragma omit pack classdesc::getter_setter
353 #pragma omit unpack classdesc::getter_setter
354 #pragma omit javaClass classdesc::object
355 #pragma omit javaClass classdesc::Object
356 #endif
357 
358 namespace classdesc_access
359 {
360  //no sensible serialisation for this
361  template <class F>
362  struct access_pack<classdesc::getter_setter<F> >:
363  classdesc::NullDescriptor<classdesc::pack_t> {};
364 
365  template <class F>
366  struct access_unpack<classdesc::getter_setter<F> >:
367  classdesc::NullDescriptor<classdesc::unpack_t> {};
368 }
369 
370 namespace classdesc
371 {
372  // handle data members
373  template <class T>
374  typename enable_if<is_fundamental<T>, void>::T
375  javaClass(javaClass_t& cl, const string& desc, T& obj, dummy<1> d=0)
376  {
377  std::string desc1(desc), ivar_name, class_name;
378  std::string::size_type last_dot=desc1.rfind('.');
379 
380  if (last_dot==std::string::npos)
381  ivar_name=desc1;
382  else
383  {
384  ivar_name=desc1.substr(last_dot+1);
385  class_name=desc1.substr(0,last_dot);
386  }
387  cl.addMethod(ivar_name, classdesc::descriptor<T (*)(T)>());
388  cl.add_functor(desc1, getter_setter<T>(obj), descriptor<T (*)(T)>());
389 
390  //capitalise for java getter/setter conventions
391  ivar_name[0]=toupper(ivar_name[0]);
392  cl.addMethod(std::string("get")+ivar_name, descriptor<T (*)()>());
393  cl.add_functor(class_name+".get"+ivar_name, getter_setter<T>(obj), descriptor<T (*)()>());
394  cl.addMethod(std::string("set")+ivar_name, descriptor<void (*)(T)>());
395  cl.add_functor(class_name+".set"+ivar_name, getter_setter<T>(obj), descriptor<void (*)(T)>());
396 }
397 
398  // helper class to indicate specific javaClass not provided in this file
399  template <class T>
400  struct is_leftOver {static const bool value=!is_fundamental<T>::value;};
401 
402  template <class T>
403  typename enable_if< is_leftOver<T>, void>::T
404  javaClass(javaClass_t& cl, const string& desc, T& arg, dummy<0> d=0);
405 
406  template <class T>
407  void javaClass(javaClass_t& cl,const string& d, const T& a)
408  {javaClass(cl,d,const_cast<T&>(a));}
409 
410  template <class T>
411  void javaClass(javaClass_t& cl,const string& d, is_const_static i, T a)
412  {
413  T tmp(a);
414  javaClass(cl,d,tmp);
415  }
416 
417  template <class T>
418  void javaClass_onbase(javaClass_t& cl,const string& d,T a)
419  {javaClass(cl,d,a);}
420 
421 }
422  // const members, just discard constness as we're just doing descriptors
423 // template <class C, class R>
424 // void javaClass(javaClass_t& cl, const string& desc, C& obj, R (C::*mem)() const)
425 // {
426 // typedef R (C::*NonConstMember)();
427 // javaClass(cl,desc,obj,NonConstMember(0));
428 // }
429 
430 // template <class C, class R>
431 // void javaClass(javaClass_t& cl, const string& desc, C& obj, R (C::*mem)())
432 // {
433 // method_info mi;
434 // mi.access_flags=JVM_ACC_PUBLIC;
435 // mi.name_index=cl->constant_pool.size();
436 // cl->constant_pool.push_back(
437 // cp_info(JVM_CONSTANT_Utf8, std::string(desc)));
438 // mi.descriptor_index=cl->constant_pool.size();
439 // cl->constant_pool.push_back(
440 // cp_info(JVM_CONSTANT_Utf8, descriptor<R (C::*)()>()));
441 // cl->methods.push_back(mi);
442 // }
443 
444  //ignore anything we don't know
445 namespace classdesc_access
446 {
447  template <class T> struct access_javaClass
448  {
449  void operator()(classdesc::javaClass_t& cl, const classdesc::string& desc, T& arg) {}
450  };
451 }
452 
453 
454 
455 using classdesc::javaClass;
456 
457 #endif
void addMethod(const std::string &method_name, const std::string &descriptor)
add a method
Definition: javaClass.h:699
Java classfile representation.
Definition: poly.h:43
support for Java signatures
Definition: javaClass_base.h:259
Definition: javaClass_base.h:128
Definition: javaClass_base.h:400
Convert a C++ type to a Java JNI type.
Definition: javaClass_base.h:172
Handle the return value.
Definition: javaClass_base.h:161
Definition: function.h:70
Definition: javaClass_base.h:447
class to allow access to private members
Definition: classdesc_access.h:21
Definition: classdesc.h:610
helper for constructing null descriptors
Definition: classdesc.h:768
Definition: javaClass_base.h:248
class to allow access to private members
Definition: classdesc_access.h:22
Return::T (or ::type) is the return type of F
Definition: function.h:33
Definition: object.h:28
Definition: javaClass.h:676
Definition: javaClass_base.h:271
Definition: object.h:76
Definition: javaClass_base.h:77
Definition: javaClass_base.h:301
Definition: pack_base.h:124
controlled template specialisation: stolen from boost::enable_if.
Definition: classdesc.h:274
base class for ArgRef
Definition: javaClass_base.h:63
Definition: classdesc.h:291
Definition: javaClass_base.h:340