diff --git a/include/javabind/advanced/get_peer.hpp b/include/javabind/advanced/get_peer.hpp index 160d639..3510876 100644 --- a/include/javabind/advanced/get_peer.hpp +++ b/include/javabind/advanced/get_peer.hpp @@ -15,7 +15,7 @@ namespace javabind { template T& get_peer(object obj, const char* class_name) { - javabind::class_ class_ = env(obj.env).find_class(class_name); + javabind::class_ class_ = env(obj.environment()).find_class(class_name); field peer_field = class_.find_field("peer"); long_ peer = peer_field.get(obj); assert(peer != 0); diff --git a/include/javabind/array.hpp b/include/javabind/array.hpp index fbf9b29..05a0d16 100644 --- a/include/javabind/array.hpp +++ b/include/javabind/array.hpp @@ -6,6 +6,7 @@ #define JAVABIND_ARRAY_HPP #include +#include #include #include @@ -43,12 +44,16 @@ struct array_region std::size_t size; }; +template +struct array; + namespace array_detail { template struct array_impl { typedef JavaArray java_type; + typedef array_impl self_type; array_impl() : ar(0), env(0) {} array_impl(JavaArray ar, JNIEnv* env) @@ -61,17 +66,40 @@ struct array_impl JavaT* raw = env->GetCharArrayElements(ar, 0); if(!raw) throw std::runtime_error("A exception was thrown"); - return region_type(raw, ar, env, env->GetArrayLength(ar)); + return region_type(raw, ar, env, length()); + } + + JavaArray raw() const { return ar; } + std::size_t length() const + { + return env->GetArrayLength(ar); + } + + typedef bool(self_type::*test_type)() const; + operator test_type() const + { + return test()? &self_type::test : test_type(0); } private: + bool test() const { return ar != 0; } + JavaArray ar; JNIEnv* env; }; } -template -struct array; +template <> +struct array : array_detail::array_impl +{ + typedef array_detail::array_impl base_type; + + array() {} + array(jbyteArray ar, JNIEnv* env) + : base_type(ar, env) + { + } +}; template <> struct array : array_detail::array_impl @@ -85,6 +113,18 @@ struct array : array_detail::array_impl } }; +template <> +struct array : array_detail::array_impl +{ + typedef array_detail::array_impl base_type; + + array() {} + array(jobjectArray ar, JNIEnv* env) + : base_type(ar, env) + { + } +}; + } #endif diff --git a/include/javabind/class.hpp b/include/javabind/class.hpp index 8a352b9..15f1567 100644 --- a/include/javabind/class.hpp +++ b/include/javabind/class.hpp @@ -6,10 +6,12 @@ #define JAVABIND_CLASS_HPP #include +#include #include #include #include #include +#include #include #include @@ -55,6 +57,61 @@ struct class_ template javabind::method method(const char* name, S s) const + { + typedef typename boost::function_types::parameter_types::type + parameter_types; + + typedef typename boost::function_types::result_type::type result_type; + typedef boost::mpl::single_view result_type_sequence; + typedef detail::create_primitive_type_descriptor + ::type + , typename boost::mpl::end::type> result_type_descriptor; + typedef detail::split_descriptors split_descriptors_type; + typename split_descriptors_type::template my_result::type + sequences = split_descriptors_type::split(s); + + typedef detail::create_primitive_type_descriptor + ::type + , typename boost::mpl::end::type> create_descriptor; + + std::size_t parameters_length = create_descriptor::length + (boost::fusion::begin(sequences.second), boost::fusion::end(sequences.second)); + std::cout << "parameters_length: " << parameters_length << std::endl; + + std::vector type + (parameters_length + result_type_descriptor::length + (boost::fusion::begin(sequences.first), boost::fusion::end(sequences.first)) + +3); + type[0] = '('; + type[parameters_length+1] = ')'; + type[type.size()-1] = 0; + create_descriptor::run(&type[1], boost::fusion::begin(sequences.second) + , boost::fusion::end(sequences.second)); + result_type_descriptor::run(&type[parameters_length+2] + , boost::fusion::begin(sequences.first) + , boost::fusion::end(sequences.first)); + assert(type[type.size()-1] == 0); + std::cout << "S Using as type: " << &type[0] << std::endl; + jmethodID id = env->GetMethodID(cls, name, &type[0]); + if(id == 0) + throw std::runtime_error("Couldn't find method"); + return javabind::method(id); + } + + template + javabind::method method(const char* name, const char* d) const + { + return method(name, javabind::descriptors(d)); + } + + template + javabind::static_method static_method(const char* name) const + { + return this->template static_method(name, boost::fusion::vector0<>()); + } + + template + javabind::static_method static_method(const char* name, S s) const { typedef typename boost::function_types::parameter_types::type parameter_types; @@ -72,17 +129,16 @@ struct class_ create_descriptor::run(&type[1], boost::fusion::begin(s), boost::fusion::end(s)); type[type.size()-1] = 0; std::cout << "S Using as type: " << &type[0] << std::endl; - jmethodID id = env->GetMethodID(cls, name, &type[0]); + jmethodID id = env->GetStaticMethodID(cls, name, &type[0]); if(id == 0) throw std::runtime_error("Couldn't find method"); - return javabind::method - (id, env); + return javabind::static_method(id, env); } template - javabind::method method(const char* name, const char* d) const + javabind::static_method static_method(const char* name, const char* d) const { - return method(name, javabind::descriptors(d)); + return static_method(name, javabind::descriptors(d)); } template @@ -112,7 +168,7 @@ struct class_ jmethodID id = env->GetMethodID(cls, "", &type[0]); if(id == 0) throw std::runtime_error("Couldn't find method"); - return javabind::constructor(id, env); + return javabind::constructor(id); } template @@ -158,7 +214,9 @@ struct class_ } ::jclass raw() const { return cls; } + JNIEnv* environment() const { return env; } +private: ::jclass cls; JNIEnv* env; }; diff --git a/include/javabind/constructor.hpp b/include/javabind/constructor.hpp index 8089b9d..4f4ca12 100644 --- a/include/javabind/constructor.hpp +++ b/include/javabind/constructor.hpp @@ -44,8 +44,8 @@ struct constructor : detail::overload_set , typename boost::function_types::result_type::type , detail::new_object_functor::type> const > base_type; - constructor( ::jmethodID id, JNIEnv* env) - : base_type(functor_type(id, env)) {} + constructor( ::jmethodID id) + : base_type(functor_type(id)) {} }; } diff --git a/include/javabind/detail/call_array_byte_method_functor.hpp b/include/javabind/detail/call_array_byte_method_functor.hpp new file mode 100644 index 0000000..d3b27f0 --- /dev/null +++ b/include/javabind/detail/call_array_byte_method_functor.hpp @@ -0,0 +1,57 @@ +// (c) Copyright 2012 Felipe Magno de Almeida +// +// All rights reserved + +#if !defined(BOOST_PP_IS_ITERATING) + +#ifndef JAVABIND_DETAIL_CALL_ARRAY_BYTE_METHOD_FUNCTOR_HPP +#define JAVABIND_DETAIL_CALL_ARRAY_BYTE_METHOD_FUNCTOR_HPP + +#include +#include +#include +#include + +#include +#include +#include + +#include + +namespace javabind { namespace detail { + +struct call_array_byte_method_functor +{ + call_array_byte_method_functor(jmethodID id) + : id(id) {} + typedef javabind::array result_type; + +#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, BOOST_PP_DEC (JAVABIND_MAX_ARGS), "javabind/detail/call_array_byte_method_functor.hpp")) +#include BOOST_PP_ITERATE () + + jmethodID raw() const { return id; } + + jmethodID id; +}; + +} } + +#endif +#else + +template +result_type operator()(O o BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(BOOST_PP_ITERATION(), A, a)) const +{ + jbyteArray r + = static_cast(static_cast + (o.environment()->CallObjectMethod(o.raw(), id + BOOST_PP_REPEAT(BOOST_PP_ITERATION() + , JAVABIND_TRAILING_UNWRAP, a)))); + if(o.environment()->ExceptionCheck()) + { + throw std::runtime_error("Exception was thrown"); + } + return result_type(r, o.environment()); +} + +#endif diff --git a/include/javabind/detail/call_array_object_method_functor.hpp b/include/javabind/detail/call_array_object_method_functor.hpp new file mode 100644 index 0000000..9c0677e --- /dev/null +++ b/include/javabind/detail/call_array_object_method_functor.hpp @@ -0,0 +1,57 @@ +// (c) Copyright 2012 Felipe Magno de Almeida +// +// All rights reserved + +#if !defined(BOOST_PP_IS_ITERATING) + +#ifndef JAVABIND_DETAIL_CALL_ARRAY_OBJECT_METHOD_FUNCTOR_HPP +#define JAVABIND_DETAIL_CALL_ARRAY_OBJECT_METHOD_FUNCTOR_HPP + +#include +#include +#include +#include + +#include +#include +#include + +#include + +namespace javabind { namespace detail { + +struct call_array_object_method_functor +{ + call_array_object_method_functor(jmethodID id) + : id(id) {} + typedef javabind::array result_type; + +#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, BOOST_PP_DEC (JAVABIND_MAX_ARGS), "javabind/detail/call_array_object_method_functor.hpp")) +#include BOOST_PP_ITERATE () + + jmethodID raw() const { return id; } + + jmethodID id; +}; + +} } + +#endif +#else + +template +result_type operator()(O o BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(BOOST_PP_ITERATION(), A, a)) const +{ + jobjectArray r + = static_cast(static_cast + (o.environment()->CallObjectMethod(o.raw(), id + BOOST_PP_REPEAT(BOOST_PP_ITERATION() + , JAVABIND_TRAILING_UNWRAP, a)))); + if(o.environment()->ExceptionCheck()) + { + throw std::runtime_error("Exception was thrown"); + } + return result_type(r, o.environment()); +} + +#endif diff --git a/include/javabind/detail/call_boolean_method_functor.hpp b/include/javabind/detail/call_boolean_method_functor.hpp index 5f031ce..b3cc487 100644 --- a/include/javabind/detail/call_boolean_method_functor.hpp +++ b/include/javabind/detail/call_boolean_method_functor.hpp @@ -20,8 +20,8 @@ namespace javabind { namespace detail { struct call_boolean_method_functor { - call_boolean_method_functor(jmethodID id, JNIEnv* env) - : id(id), env(env) {} + call_boolean_method_functor(jmethodID id) + : id(id) {} typedef bool result_type; #define BOOST_PP_ITERATION_PARAMS_1 (3, (0, BOOST_PP_DEC (JAVABIND_MAX_ARGS), "javabind/detail/call_boolean_method_functor.hpp")) @@ -30,7 +30,6 @@ struct call_boolean_method_functor jmethodID raw() const { return id; } jmethodID id; - JNIEnv* env; }; } } @@ -39,12 +38,13 @@ struct call_boolean_method_functor #else template -bool operator()(O o BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(BOOST_PP_ITERATION(), A, a)) const +result_type operator()(O o BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(BOOST_PP_ITERATION(), A, a)) const { jboolean r - = env->CallBooleanMethod(o.raw(), id - BOOST_PP_REPEAT(BOOST_PP_ITERATION(), JAVABIND_TRAILING_UNWRAP, a)) != 0; - if(env->ExceptionCheck()) + = o.environment()->CallBooleanMethod(o.raw(), id + BOOST_PP_REPEAT(BOOST_PP_ITERATION() + , JAVABIND_TRAILING_UNWRAP, a)) != 0; + if(o.environment()->ExceptionCheck()) { throw std::runtime_error("Exception was thrown"); } diff --git a/include/javabind/detail/call_int_method_functor.hpp b/include/javabind/detail/call_int_method_functor.hpp new file mode 100644 index 0000000..f96fdc7 --- /dev/null +++ b/include/javabind/detail/call_int_method_functor.hpp @@ -0,0 +1,55 @@ +// (c) Copyright 2012 Felipe Magno de Almeida +// +// All rights reserved + +#if !defined(BOOST_PP_IS_ITERATING) + +#ifndef JAVABIND_DETAIL_CALL_INT_METHOD_FUNCTOR_HPP +#define JAVABIND_DETAIL_CALL_INT_METHOD_FUNCTOR_HPP + +#include +#include +#include + +#include +#include +#include + +#include + +namespace javabind { namespace detail { + +struct call_int_method_functor +{ + call_int_method_functor(jmethodID id) + : id(id) {} + typedef javabind::int_ result_type; + +#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, BOOST_PP_DEC (JAVABIND_MAX_ARGS), "javabind/detail/call_int_method_functor.hpp")) +#include BOOST_PP_ITERATE () + + jmethodID raw() const { return id; } + + jmethodID id; +}; + +} } + +#endif +#else + +template +result_type operator()(O o BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(BOOST_PP_ITERATION(), A, a)) const +{ + jint r + = o.environment()->CallIntMethod(o.raw(), id + BOOST_PP_REPEAT(BOOST_PP_ITERATION() + , JAVABIND_TRAILING_UNWRAP, a)); + if(o.environment()->ExceptionCheck()) + { + throw std::runtime_error("Exception was thrown"); + } + return r; +} + +#endif diff --git a/include/javabind/detail/call_object_method_functor.hpp b/include/javabind/detail/call_object_method_functor.hpp new file mode 100644 index 0000000..5ec696c --- /dev/null +++ b/include/javabind/detail/call_object_method_functor.hpp @@ -0,0 +1,55 @@ +// (c) Copyright 2012 Felipe Magno de Almeida +// +// All rights reserved + +#if !defined(BOOST_PP_IS_ITERATING) + +#ifndef JAVABIND_DETAIL_CALL_OBJECT_METHOD_FUNCTOR_HPP +#define JAVABIND_DETAIL_CALL_OBJECT_METHOD_FUNCTOR_HPP + +#include +#include +#include + +#include +#include +#include + +#include + +namespace javabind { namespace detail { + +struct call_object_method_functor +{ + call_object_method_functor(jmethodID id) + : id(id) {} + typedef object result_type; + +#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, BOOST_PP_DEC (JAVABIND_MAX_ARGS), "javabind/detail/call_object_method_functor.hpp")) +#include BOOST_PP_ITERATE () + + jmethodID raw() const { return id; } + + jmethodID id; +}; + +} } + +#endif +#else + +template +result_type operator()(O o BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(BOOST_PP_ITERATION(), A, a)) const +{ + jobject r + = o.environment()->CallObjectMethod(o.raw(), id + BOOST_PP_REPEAT(BOOST_PP_ITERATION() + , JAVABIND_TRAILING_UNWRAP, a)); + if(o.environment()->ExceptionCheck()) + { + throw std::runtime_error("Exception was thrown"); + } + return result_type(r, o.environment()); +} + +#endif diff --git a/include/javabind/detail/call_static_boolean_method_functor.hpp b/include/javabind/detail/call_static_boolean_method_functor.hpp new file mode 100644 index 0000000..b65c7a4 --- /dev/null +++ b/include/javabind/detail/call_static_boolean_method_functor.hpp @@ -0,0 +1,54 @@ +// (c) Copyright 2012 Felipe Magno de Almeida +// +// All rights reserved + +#if !defined(BOOST_PP_IS_ITERATING) + +#ifndef JAVABIND_DETAIL_CALL_STATIC_BOOLEAN_METHOD_FUNCTOR_HPP +#define JAVABIND_DETAIL_CALL_STATIC_BOOLEAN_METHOD_FUNCTOR_HPP + +#include +#include + +#include +#include +#include + +#include + +namespace javabind { namespace detail { + +struct call_static_boolean_method_functor +{ + call_static_boolean_method_functor(jmethodID id, JNIEnv* env) + : id(id), env(env) {} + typedef bool result_type; + +#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, BOOST_PP_DEC (JAVABIND_MAX_ARGS), "javabind/detail/call_static_boolean_method_functor.hpp")) +#include BOOST_PP_ITERATE () + + jmethodID raw() const { return id; } + + jmethodID id; + JNIEnv* env; +}; + +} } + +#endif +#else + +template +bool operator()(C c BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(BOOST_PP_ITERATION(), A, a)) const +{ + jboolean r + = env->CallStaticBooleanMethod(c.raw(), id + BOOST_PP_REPEAT(BOOST_PP_ITERATION(), JAVABIND_TRAILING_UNWRAP, a)) != 0; + if(env->ExceptionCheck()) + { + throw std::runtime_error("Exception was thrown"); + } + return r; +} + +#endif diff --git a/include/javabind/detail/call_static_void_method_functor.hpp b/include/javabind/detail/call_static_void_method_functor.hpp new file mode 100644 index 0000000..59ce704 --- /dev/null +++ b/include/javabind/detail/call_static_void_method_functor.hpp @@ -0,0 +1,52 @@ +// (c) Copyright 2012 Felipe Magno de Almeida +// +// All rights reserved + +#if !defined(BOOST_PP_IS_ITERATING) + +#ifndef JAVABIND_DETAIL_CALL_STATIC_VOID_METHOD_FUNCTOR_HPP +#define JAVABIND_DETAIL_CALL_STATIC_VOID_METHOD_FUNCTOR_HPP + +#include +#include + +#include +#include +#include + +#include + +namespace javabind { namespace detail { + +struct call_static_void_method_functor +{ + call_static_void_method_functor(jmethodID id, JNIEnv* env) + : id(id), env(env) {} + typedef void result_type; + +#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, BOOST_PP_DEC (JAVABIND_MAX_ARGS), "javabind/detail/call_static_void_method_functor.hpp")) +#include BOOST_PP_ITERATE () + + jmethodID raw() const { return id; } + + jmethodID id; + JNIEnv* env; +}; + +} } + +#endif +#else + +template +void operator()(C c BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(BOOST_PP_ITERATION(), A, a)) const +{ + env->CallStaticVoidMethod(c.raw(), id + BOOST_PP_REPEAT(BOOST_PP_ITERATION(), JAVABIND_TRAILING_UNWRAP, a)); + if(env->ExceptionCheck()) + { + throw std::runtime_error("Exception was thrown"); + } +} + +#endif diff --git a/include/javabind/detail/call_void_method_functor.hpp b/include/javabind/detail/call_void_method_functor.hpp index 6c05644..385baa9 100644 --- a/include/javabind/detail/call_void_method_functor.hpp +++ b/include/javabind/detail/call_void_method_functor.hpp @@ -20,8 +20,8 @@ namespace javabind { namespace detail { struct call_void_method_functor { - call_void_method_functor(jmethodID id, JNIEnv* env) - : id(id), env(env) {} + call_void_method_functor(jmethodID id) + : id(id) {} typedef void result_type; #define BOOST_PP_ITERATION_PARAMS_1 (3, (0, BOOST_PP_DEC (JAVABIND_MAX_ARGS), "javabind/detail/call_void_method_functor.hpp")) @@ -30,7 +30,6 @@ struct call_void_method_functor jmethodID raw() const { return id; } jmethodID id; - JNIEnv* env; }; } } @@ -39,11 +38,12 @@ struct call_void_method_functor #else template -void operator()(O o BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(BOOST_PP_ITERATION(), A, a)) const +result_type operator()(O o BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(BOOST_PP_ITERATION(), A, a)) const { - env->CallVoidMethod(o.raw(), id - BOOST_PP_REPEAT(BOOST_PP_ITERATION(), JAVABIND_TRAILING_UNWRAP, a)); - if(env->ExceptionCheck()) + o.environment()->CallVoidMethod(o.raw(), id + BOOST_PP_REPEAT(BOOST_PP_ITERATION() + , JAVABIND_TRAILING_UNWRAP, a)); + if(o.environment()->ExceptionCheck()) { throw std::runtime_error("Exception was thrown"); } diff --git a/include/javabind/detail/create_primitive_type_descriptor.hpp b/include/javabind/detail/create_primitive_type_descriptor.hpp index c912f9e..1e0fa54 100644 --- a/include/javabind/detail/create_primitive_type_descriptor.hpp +++ b/include/javabind/detail/create_primitive_type_descriptor.hpp @@ -44,6 +44,7 @@ struct create_primitive_type_descriptor }; }; + // Used by split_descriptors typedef typename boost::is_same < typename boost::mpl::find_if @@ -92,19 +93,19 @@ struct create_primitive_type_descriptor return 1 + length_array_aux(first, last, tag()); } - template - static std::size_t length_aux(DescriptorFirst first, DescriptorLast last - , tag< ::jintArray>) - { - return length_aux(first, last, tag >()); - } + // template + // static std::size_t length_aux(DescriptorFirst first, DescriptorLast last + // , tag< ::jintArray>) + // { + // return length_aux(first, last, tag >()); + // } - template - static std::size_t length_aux(DescriptorFirst first, DescriptorLast last - , tag< ::jcharArray>) - { - return length_aux(first, last, tag >()); - } + // template + // static std::size_t length_aux(DescriptorFirst first, DescriptorLast last + // , tag< ::jcharArray>) + // { + // return length_aux(first, last, tag >()); + // } template static std::size_t length_aux(DescriptorFirst first, DescriptorLast last @@ -170,19 +171,19 @@ struct create_primitive_type_descriptor ::run(v + 1, first, last); } - template - static void run_aux(char* v, DescriptorFirst first, DescriptorLast last - , tag< ::jintArray>) - { - run_aux(v, first, last, tag >()); - } + // template + // static void run_aux(char* v, DescriptorFirst first, DescriptorLast last + // , tag< ::jintArray>) + // { + // run_aux(v, first, last, tag >()); + // } - template - static void run_aux(char* v, DescriptorFirst first, DescriptorLast last - , tag< ::jcharArray>) - { - run_aux(v, first, last, tag >()); - } + // template + // static void run_aux(char* v, DescriptorFirst first, DescriptorLast last + // , tag< ::jcharArray>) + // { + // run_aux(v, first, last, tag >()); + // } template static void run_aux(char* v, DescriptorFirst first, DescriptorLast last @@ -204,6 +205,7 @@ struct create_primitive_type_descriptor run_aux(v, first, last, tag()); } + template static void run_aux(char* v, DescriptorFirst first, DescriptorLast last , tag) diff --git a/include/javabind/detail/new_object_functor.hpp b/include/javabind/detail/new_object_functor.hpp index 3036d26..cb06cb4 100644 --- a/include/javabind/detail/new_object_functor.hpp +++ b/include/javabind/detail/new_object_functor.hpp @@ -8,6 +8,7 @@ #define JAVABIND_DETAIL_NEW_OBJECT_FUNCTOR_HPP #include +#include #include #include @@ -18,14 +19,13 @@ namespace javabind { namespace detail { template struct new_object_functor { - new_object_functor(jmethodID id, JNIEnv* env) - : id(id), env(env) {} + new_object_functor(jmethodID id) + : id(id) {} #define BOOST_PP_ITERATION_PARAMS_1 (3, (0, BOOST_PP_DEC (JAVABIND_MAX_ARGS), "javabind/detail/new_object_functor.hpp")) #include BOOST_PP_ITERATE () jmethodID id; - JNIEnv* env; }; } } @@ -36,10 +36,11 @@ struct new_object_functor template R operator()(C c BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(BOOST_PP_ITERATION(), A, a)) const { - jobject o = env->NewObject - (c.raw(), id BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), a)); + jobject o = c.environment()->NewObject + (c.raw(), id BOOST_PP_REPEAT(BOOST_PP_ITERATION() + , JAVABIND_TRAILING_UNWRAP, a)); if(o) - return R(o, env); + return R(o, c.environment()); else throw std::runtime_error("Exception throw while constructing a object"); } diff --git a/include/javabind/detail/select_call_functor.hpp b/include/javabind/detail/select_call_functor.hpp index a022cf3..d315d6f 100644 --- a/include/javabind/detail/select_call_functor.hpp +++ b/include/javabind/detail/select_call_functor.hpp @@ -7,6 +7,10 @@ #include #include +#include +#include +#include +#include #include namespace javabind { namespace detail { @@ -26,6 +30,30 @@ struct select_call_functor typedef call_boolean_method_functor type; }; +template <> +struct select_call_functor +{ + typedef call_object_method_functor type; +}; + +template <> +struct select_call_functor +{ + typedef call_int_method_functor type; +}; + +template <> +struct select_call_functor > +{ + typedef call_array_byte_method_functor type; +}; + +template <> +struct select_call_functor > +{ + typedef call_array_object_method_functor type; +}; + } } #endif diff --git a/include/javabind/detail/select_static_call_functor.hpp b/include/javabind/detail/select_static_call_functor.hpp new file mode 100644 index 0000000..2e20086 --- /dev/null +++ b/include/javabind/detail/select_static_call_functor.hpp @@ -0,0 +1,31 @@ +// (c) Copyright 2012 Felipe Magno de Almeida +// +// All rights reserved + +#ifndef JAVABIND_DETAIL_SELECT_STATIC_CALL_FUNCTOR_HPP +#define JAVABIND_DETAIL_SELECT_STATIC_CALL_FUNCTOR_HPP + +#include +#include +#include + +namespace javabind { namespace detail { + +template +struct select_static_call_functor; + +template <> +struct select_static_call_functor +{ + typedef call_static_void_method_functor type; +}; + +template <> +struct select_static_call_functor +{ + typedef call_static_boolean_method_functor type; +}; + +} } + +#endif diff --git a/include/javabind/detail/set_field.hpp b/include/javabind/detail/set_field.hpp index 61070d7..5d977f4 100644 --- a/include/javabind/detail/set_field.hpp +++ b/include/javabind/detail/set_field.hpp @@ -6,52 +6,46 @@ #define JAVABIND_DETAIL_FIELD_SET_FIELD_HPP #include +#include #include +#include #include #include namespace javabind { namespace detail { -inline void set_field(JNIEnv* env, jobject o, jfieldID id, jint v) +inline void set_field(JNIEnv* env, jobject o, jfieldID id, int_ v) { assert(!env->ExceptionCheck()); - env->SetIntField(o, id, v); + env->SetIntField(o, id, unwrap(v)); if(env->ExceptionCheck()) throw std::runtime_error("Exception thrown in SetIntField"); assert(env->GetIntField(o, id) == v); } -inline void set_field(JNIEnv* env, jobject o, jfieldID id, jdouble v) +inline void set_field(JNIEnv* env, jobject o, jfieldID id, double_ v) { assert(!env->ExceptionCheck()); - env->SetDoubleField(o, id, v); + env->SetDoubleField(o, id, unwrap(v)); if(env->ExceptionCheck()) throw std::runtime_error("Exception thrown in SetDoubleField"); assert(env->GetDoubleField(o, id) == v); } -inline void set_field(JNIEnv* env, jobject o, jfieldID id, jlong v) +inline void set_field(JNIEnv* env, jobject o, jfieldID id, long_ v) { assert(!env->ExceptionCheck()); - env->SetLongField(o, id, v); + env->SetLongField(o, id, unwrap(v)); if(env->ExceptionCheck()) throw std::runtime_error("Exception thrown in SetLongField"); assert(env->GetLongField(o, id) == v); } -inline void set_field(JNIEnv* env, jobject o, jfieldID id, jobject v) -{ - assert(!env->ExceptionCheck()); - env->SetObjectField(o, id, v); - if(env->ExceptionCheck()) - throw std::runtime_error("Exception thrown in SetObjectField"); -} - inline void set_field(JNIEnv* env, jobject o, jfieldID id, object v) { assert(!env->ExceptionCheck()); - env->SetObjectField(o, id, v.raw()); + env->SetObjectField(o, id, unwrap(v)); if(env->ExceptionCheck()) throw std::runtime_error("Exception thrown in SetObjectField"); } diff --git a/include/javabind/detail/set_static_field.hpp b/include/javabind/detail/set_static_field.hpp index f86cfff..003f7e8 100644 --- a/include/javabind/detail/set_static_field.hpp +++ b/include/javabind/detail/set_static_field.hpp @@ -9,19 +9,39 @@ namespace javabind { namespace detail { -inline void set_static_field(JNIEnv* env, jclass cls, jfieldID id, jint v) +inline void set_static_field(JNIEnv* env, jclass c, jfieldID id, int_ v) { - env->SetStaticIntField(cls, id, v); + assert(!env->ExceptionCheck()); + env->SetStaticIntField(c, id, unwrap(v)); + if(env->ExceptionCheck()) + throw std::runtime_error("Exception thrown in SetStaticIntField"); + assert(env->GetStaticIntField(c, id) == unwrap(v)); } -// inline void set_static_field(JNIEnv* env, jclass cls, jfieldID id, jdouble v) -// { -// env->SetStaticDoubleField(cls, id, v); -// } +inline void set_static_field(JNIEnv* env, jclass c, jfieldID id, double_ v) +{ + assert(!env->ExceptionCheck()); + env->SetStaticDoubleField(c, id, unwrap(v)); + if(env->ExceptionCheck()) + throw std::runtime_error("Exception thrown in SetStaticDoubleField"); + assert(env->GetStaticDoubleField(c, id) == unwrap(v)); +} + +inline void set_static_field(JNIEnv* env, jclass c, jfieldID id, long_ v) +{ + assert(!env->ExceptionCheck()); + env->SetStaticLongField(c, id, unwrap(v)); + if(env->ExceptionCheck()) + throw std::runtime_error("Exception thrown in SetStaticLongField"); + assert(env->GetStaticLongField(c, id) == unwrap(v)); +} -inline void set_static_field(JNIEnv* env, jclass cls, jfieldID id, object v) +inline void set_static_field(JNIEnv* env, jclass c, jfieldID id, object v) { - env->SetStaticObjectField(cls, id, v.raw()); + assert(!env->ExceptionCheck()); + env->SetStaticObjectField(c, id, unwrap(v)); + if(env->ExceptionCheck()) + throw std::runtime_error("Exception thrown in SetStaticObjectField"); } } } diff --git a/include/javabind/detail/split_descriptors.hpp b/include/javabind/detail/split_descriptors.hpp new file mode 100644 index 0000000..21dea25 --- /dev/null +++ b/include/javabind/detail/split_descriptors.hpp @@ -0,0 +1,74 @@ +// (c) Copyright 2012 Felipe Magno de Almeida +// +// All rights reserved + +#ifndef JAVABIND_DETAIL_SPLIT_DESCRIPTORS_HPP +#define JAVABIND_DETAIL_SPLIT_DESCRIPTORS_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace javabind { namespace detail { + +template +struct split_descriptors +{ + typedef typename ResultDescriptor::all_primitives all_primitives; + + template + struct my_result + { + typedef typename boost::mpl::if_ + + , S> + , std::pair::type>::type>::type> + , typename boost::fusion::result_of::pop_front::type + > >::type type; + }; + + template + static typename my_result::type split_aux(S const& s, boost::mpl::false_) + { + typedef typename my_result::type result_type; + return result_type(boost::fusion::vector1 + ::type>::type>::type> + (boost::fusion::deref(boost::fusion::begin(s))) + , boost::fusion::pop_front(s)); + } + + template + static typename my_result::type split_aux(S const& s, boost::mpl::true_) + { + typedef typename my_result::type result_type; + return result_type(boost::fusion::vector0<>(), s); + } + + template + static typename my_result::type split(S const& s) + { + return split_aux(s, typename all_primitives::type()); + } +}; + +} } + +#endif diff --git a/include/javabind/detail/unwrap.hpp b/include/javabind/detail/unwrap.hpp index 42e13e0..53a7c3d 100644 --- a/include/javabind/detail/unwrap.hpp +++ b/include/javabind/detail/unwrap.hpp @@ -5,6 +5,7 @@ #ifndef JAVABIND_DETAIL_UNWRAP_HPP #define JAVABIND_DETAIL_UNWRAP_HPP +#include #include #include #include @@ -26,6 +27,15 @@ inline ::jfloat unwrap(float_ o) { return o.raw(); } inline ::jdouble unwrap(double_ o) { return o.raw(); } inline ::jobject unwrap(object o) { return o.raw(); } inline ::jstring unwrap(string s) { return s.raw(); } +inline ::jbyteArray unwrap(array a) { return a.raw(); } +inline ::jcharArray unwrap(array a) { return a.raw(); } +// inline ::jshortArray unwrap(array a) { return a.raw(); } +// inline ::jintArray unwrap(array a) { return a.raw(); } +// inline ::jlongArray unwrap(array a) { return a.raw(); } +// inline ::jfloatArray unwrap(array a) { return a.raw(); } +// inline ::jdoubleArray unwrap(array a) { return a.raw(); } +inline ::jobjectArray unwrap(array a) { return a.raw(); } +// inline ::jstringArray unwrap(array a) { return a.raw(); } } } diff --git a/include/javabind/field.hpp b/include/javabind/field.hpp index 9c306f0..e5fc5c3 100644 --- a/include/javabind/field.hpp +++ b/include/javabind/field.hpp @@ -25,11 +25,11 @@ struct static_field T get(class_ const& cls) const { - return detail::get_static_field(cls.env, cls.raw(), id, detail::tag()); + return detail::get_static_field(cls.environment(), cls.raw(), id, detail::tag()); } void set(class_ const& cls, T v) { - detail::set_static_field(cls.env, cls.raw(), id, v); + detail::set_static_field(cls.environment(), cls.raw(), id, v); } jfieldID raw() const { return id; } @@ -47,12 +47,12 @@ struct field T get(object const& o) const { - return detail::get_field(o.env, o.raw(), id, detail::tag()); + return detail::get_field(o.environment(), o.raw(), id, detail::tag()); } void set(object const& o, T v) { - detail::set_field(o.env, o.raw(), id, v); - assert(detail::get_field(o.env, o.raw(), id, detail::tag()) == v); + detail::set_field(o.environment(), o.raw(), id, v); + assert(detail::get_field(o.environment(), o.raw(), id, detail::tag()) == v); } jfieldID raw() const { return id; } diff --git a/include/javabind/field_descriptor_traits.hpp b/include/javabind/field_descriptor_traits.hpp index d812509..c1506a0 100644 --- a/include/javabind/field_descriptor_traits.hpp +++ b/include/javabind/field_descriptor_traits.hpp @@ -36,29 +36,35 @@ struct field_descriptor_traits }; template <> -struct field_descriptor_traits +struct field_descriptor_traits { static const char* value; }; template <> -struct field_descriptor_traits +struct field_descriptor_traits { static const char* value; }; template <> -struct field_descriptor_traits +struct field_descriptor_traits { static const char* value; }; template <> -struct field_descriptor_traits > +struct field_descriptor_traits { static const char* value; }; +// template <> +// struct field_descriptor_traits > +// { +// static const char* value; +// }; + template <> struct field_descriptor_traits { diff --git a/include/javabind/method.hpp b/include/javabind/method.hpp index 43505d3..dc8d144 100644 --- a/include/javabind/method.hpp +++ b/include/javabind/method.hpp @@ -50,8 +50,8 @@ struct method : detail::overload_set , typename boost::function_types::result_type::type , functor_type > base_type; - method( ::jmethodID id, JNIEnv* env) - : base_type(functor_type(id, env)) {} + method( ::jmethodID id ) + : base_type(functor_type(id)) {} jmethodID raw() const { return base_type::functor().raw(); } }; diff --git a/include/javabind/object.hpp b/include/javabind/object.hpp index b1e6d34..f51339f 100644 --- a/include/javabind/object.hpp +++ b/include/javabind/object.hpp @@ -8,6 +8,7 @@ #include #include +#include namespace javabind { @@ -24,10 +25,24 @@ struct object typedef ::jobject java_type; + typedef bool(object::*test_type)() const; + operator test_type() const + { + return test()? &object::test : test_type(0); + } + + string to_string() const; + static object nil(JNIEnv* env) { return object(0, env); } + JNIEnv* environment() const { return env; } +private: + bool test() const { return o != 0; } + jobject o; JNIEnv* env; }; +std::ostream& operator<<(std::ostream& os, object o); + } #endif diff --git a/include/javabind/register_class.hpp b/include/javabind/register_class.hpp index aa72556..7a3dbb5 100644 --- a/include/javabind/register_class.hpp +++ b/include/javabind/register_class.hpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -110,54 +111,6 @@ struct initialize_native_method typedef boost::mpl::size_t type; }; - template - struct split_descriptors - { - typedef typename ResultDescriptor::all_primitives all_primitives; - - template - struct my_result - { - typedef typename boost::mpl::if_ - - , S> - , std::pair::type>::type>::type> - , typename boost::fusion::result_of::pop_front::type - > >::type type; - }; - - template - static typename my_result::type split_aux(S const s, boost::mpl::false_) - { - typedef typename my_result::type result_type; - return result_type(boost::fusion::vector1 - ::type>::type>::type> - (boost::fusion::deref(boost::fusion::begin(s))) - , boost::fusion::pop_front(s)); - } - - template - static typename my_result::type split_aux(S const s, boost::mpl::true_) - { - typedef typename my_result::type result_type; - return result_type(boost::fusion::vector0<>(), s); - } - - template - static typename my_result::type split(S s) - { - return split_aux(s, typename all_primitives::type()); - } - }; - template boost::mpl::size_t operator() (boost::mpl::size_t @@ -204,7 +157,7 @@ struct initialize_native_method ::type , typename boost::mpl::end::type> result_type_descriptor; - typedef split_descriptors split_descriptors_type; + typedef detail::split_descriptors split_descriptors_type; typename split_descriptors_type::template my_result::type sequences = split_descriptors_type::split(entry.s); @@ -274,7 +227,8 @@ void register_class(reg::class_ cls) (static_cast (static_cast (info.get())))); - if(cls.cls.env->RegisterNatives(cls.cls.raw(), methods, size_type::value+1) < 0) + if(cls.cls.environment() + ->RegisterNatives(cls.cls.raw(), methods, size_type::value+1) < 0) { throw std::runtime_error("Error registering native function"); } @@ -318,7 +272,8 @@ void register_class(reg::class_ cls) (static_cast (static_cast (info.get())))); - if(cls.cls.env->RegisterNatives(cls.cls.raw(), methods, size_type::value+1) < 0) + if(cls.cls.environment() + ->RegisterNatives(cls.cls.raw(), methods, size_type::value+1) < 0) { throw std::runtime_error("Error registering native function"); } diff --git a/include/javabind/static_method.hpp b/include/javabind/static_method.hpp new file mode 100644 index 0000000..bd3bfda --- /dev/null +++ b/include/javabind/static_method.hpp @@ -0,0 +1,61 @@ +// (c) Copyright 2012 Felipe Magno de Almeida +// +// All rights reserved + +#ifndef JAVABIND_STATIC_METHOD_HPP +#define JAVABIND_STATIC_METHOD_HPP + +#include +#include +#include + +#include +#include +#include + +#include + +#include + +namespace javabind { + +template +struct static_method : detail::overload_set +, boost::function_types::function_arity::type::value+1 + , + typename boost::mpl::push_front + < + typename boost::function_types::parameter_types::type + , javabind::class_ + >::type + , typename boost::function_types::result_type::type + , typename detail::select_static_call_functor + < + typename boost::function_types::result_type::type + >::type + > +{ + typedef typename detail::select_static_call_functor + < + typename boost::function_types::result_type::type + >::type functor_type; + typedef detail::overload_set + , boost::function_types::function_arity::type::value+1 + , + typename boost::mpl::push_front + < + typename boost::function_types::parameter_types::type + , javabind::class_ + >::type + , typename boost::function_types::result_type::type + , functor_type + > base_type; + static_method( ::jmethodID id, JNIEnv* env) + : base_type(functor_type(id, env)) {} + + jmethodID raw() const { return base_type::functor().raw(); } +}; + +} + +#endif diff --git a/include/javabind/type_mapping.hpp b/include/javabind/type_mapping.hpp index c7f6c24..6a5d87b 100644 --- a/include/javabind/type_mapping.hpp +++ b/include/javabind/type_mapping.hpp @@ -129,7 +129,7 @@ template <> struct type_mapping > { typedef jbyteArray java_type; - typedef boost::mpl::false_ is_primitive; + typedef boost::mpl::true_ is_primitive; typedef boost::mpl::true_ is_array; }; @@ -181,6 +181,14 @@ struct type_mapping > typedef boost::mpl::true_ is_array; }; +template <> +struct type_mapping > +{ + typedef jobjectArray java_type; + typedef boost::mpl::false_ is_primitive; + typedef boost::mpl::true_ is_array; +}; + } #endif diff --git a/src/field_descriptor_traits.cpp b/src/field_descriptor_traits.cpp index b15944f..8f0cd00 100644 --- a/src/field_descriptor_traits.cpp +++ b/src/field_descriptor_traits.cpp @@ -14,6 +14,7 @@ const char* field_descriptor_traits::value = "D"; const char* field_descriptor_traits::value = "V"; const char* field_descriptor_traits::value = "J"; const char* field_descriptor_traits::value = "Z"; -const char* field_descriptor_traits >::value = "[I"; +const char* field_descriptor_traits::value = "B"; + //const char* field_descriptor_traits >::value = "[I"; } diff --git a/src/object.cpp b/src/object.cpp index 54fc182..8ef9dcc 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -6,6 +6,8 @@ #include +#include + namespace javabind { javabind::class_ object::class_() const @@ -13,6 +15,32 @@ javabind::class_ object::class_() const return javabind::class_(env->GetObjectClass(o), env); } +string object::to_string() const +{ + const char sig[] = "()Ljava/lang/String;"; + jmethodID to_string_id = env->GetMethodID(env->GetObjectClass(o), "toString", sig); + assert(to_string_id != 0); + jstring s = static_cast(static_cast(env->CallObjectMethod(o, to_string_id))); + return string(s, env); +} + +std::ostream& operator<<(std::ostream& os, object o) +{ + std::ostream::sentry sen(os); + JNIEnv* env = o.environment(); + assert(env != 0); + if(o != object::nil(o.environment())) + { + string str = o.to_string(); + os << str; + } + else + { + os << "[nil]"; + } + return os; +} + }