Skip to content

Commit

Permalink
feat(java): returning std::function
Browse files Browse the repository at this point in the history
  • Loading branch information
Boris-Rasin committed Mar 8, 2022
1 parent fe11fd4 commit 48c34a9
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 44 deletions.
17 changes: 17 additions & 0 deletions source/com/scapix/Function.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
com/scapix/Function.java
Copyright (c) 2022 Boris Rasin (boris@scapix.com)
*/

package com.scapix;

public class Function
{
private long ptr;

@SuppressWarnings("deprecation")
protected native void finalize();

protected Function(long p) { ptr = p; }
}
113 changes: 113 additions & 0 deletions source/scapix/bridge/java/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ namespace bridge {
namespace java {

class object_base;
class function_base;

namespace detail {

Expand All @@ -43,6 +44,24 @@ class bridge : public link::java::object<SCAPIX_META_STRING("com/scapix/Bridge")

};

class function : public link::java::object<SCAPIX_META_STRING("com/scapix/Function")>
{
public:

using ptr = SCAPIX_META_STRING("ptr");

template <typename ClassName>
static link::java::local_ref<ClassName> create(function_base* p) { return link::java::static_pointer_cast<ClassName>(link::java::object<meta::concat_t<ClassName, SCAPIX_META_STRING("Impl")>>::template new_object<void(jlong)>(reinterpret_cast<jlong>(p))); }

void set_ptr(function_base* p) { set_field<ptr>(reinterpret_cast<jlong>(p)); }
function_base* get_ptr() { return reinterpret_cast<function_base*>(get_field<ptr, jlong>()); }

protected:

function(handle_type h) : object_type(h) {}

};

} // namespace detail

class object_base
Expand Down Expand Up @@ -146,6 +165,46 @@ class init

};

class function_base
{
public:

virtual ~function_base() = default;

void finalize()
{
delete this;
}

};

template <typename T>
class function;

template <typename R, typename ...Args>
class function<R(Args...)> : public function_base
{
public:

template <typename ClassName>
static link::java::ref<ClassName> create(std::function<R(Args...)>&& func)
{
return detail::function::create<ClassName>(new function<R(Args...)>(std::move(func)));
}

function(std::function<R(Args...)>&& f) : func(std::move(f)) {}

R call(Args... args)
{
return func(std::forward<Args>(args)...);
}

private:

std::function<R(Args...)> func;

};

inline jint on_load(JavaVM *vm, void *reserved)
{
auto result = link::java::on_load(vm, reserved);
Expand All @@ -157,6 +216,13 @@ inline jint on_load(JavaVM *vm, void *reserved)
>
::register_();

link::java::native_methods
<
detail::function::class_name,
link::java::native_method<SCAPIX_META_STRING("finalize"), void(), void(function_base::*)(), &function_base::finalize>
>
::register_();

return result;
}

Expand All @@ -178,6 +244,18 @@ struct class_name<bridge::java::init<T>>
using type = class_name_t<T>;
};

template <>
struct class_name<bridge::java::function_base>
{
using type = bridge::java::detail::function::class_name;
};

template <typename T>
struct class_name<bridge::java::function<T>>
{
using type = bridge::java::detail::function::class_name;
};

// used to convert 'this'

template <typename Jni, typename T>
Expand All @@ -200,6 +278,28 @@ struct convert<Jni, T, std::enable_if_t<bridge::is_object<T>>>
}
};

// used to convert 'this'

template <typename Jni, typename T>
struct convert<Jni, bridge::java::function<T>>
{
static bridge::java::function<T>& cpp(ref<bridge::java::detail::function> v)
{
return *static_cast<bridge::java::function<T>*>(v->get_ptr());
}
};

// used to convert 'this'

template <typename Jni>
struct convert<Jni, bridge::java::function_base>
{
static bridge::java::function_base& cpp(ref<bridge::java::detail::function> v)
{
return *v->get_ptr();
}
};

template <typename Jni, typename T>
struct convert_shared<Jni, T, std::enable_if_t<bridge::is_object<T>>>
{
Expand All @@ -221,6 +321,19 @@ struct convert_shared<Jni, T, std::enable_if_t<bridge::is_object<T>>>
}
};

template <typename T>
struct function_impl;

template <typename ClassName, typename JniR, typename ...JniArgs>
struct function_impl<function<ClassName, JniR(JniArgs...)>>
{
template <typename R, typename ...Args>
static link::java::ref<ClassName> create(std::function<R(Args...)>&& func)
{
return bridge::java::function<R(Args...)>::template create<ClassName>(std::move(func));
}
};

} // namespace java
} // namespace link
} // namespace scapix
Expand Down
12 changes: 7 additions & 5 deletions source/scapix/link/java/convert.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ namespace scapix {
namespace link {
namespace java {

template <typename T>
struct function_impl;

template <typename Jni, typename Cpp, typename = void>
struct convert_shared;

Expand Down Expand Up @@ -431,11 +434,10 @@ struct convert<ref<function<ClassName, JniR(JniArgs...), Name>>, std::function<R
});
}

// static ref<function<ClassName, JniR(JniArgs...), Name>> jni(const std::function<R(Args...)>& f)
// {
// auto c = std::make_shared<callback<J, R, Args...>>(f);
// return c.get_ref();
// }
static ref<function<ClassName, JniR(JniArgs...), Name>> jni(std::function<R(Args...)> f)
{
return function_impl<function<ClassName, JniR(JniArgs...), Name>>::create(std::move(f));
}
};

template <typename Jni, typename Struct>
Expand Down
38 changes: 4 additions & 34 deletions source/scapix/link/js/bind.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,6 @@ namespace scapix {
namespace link {
namespace js {

//template <typename T>
//using param = std::conditional_t<std::experimental::is_detected_v<has_convert_cpp_t<emscripten::val, T>>, emscripten::val, T>;

template <typename T>
struct param
{
using type = emscripten::val;
};

template<>
struct param<void>
{
using type = void;
};

template <typename T>
using param_t = typename param<T>::type;

// Clang bug:
// https://bugs.llvm.org/show_bug.cgi?id=42805

Expand Down Expand Up @@ -67,13 +49,9 @@ struct function_impl
static param_t<R> func(class_type& obj, param_t<Args>... args)
{
if constexpr (std::is_void_v<R>)
{
return (obj.*Function)(convert_cpp<Args>(std::forward<param_t<Args>>(args))...);
}
else
{
return convert_js<param_t<R>>((obj.*Function)(convert_cpp<Args>(std::forward<param_t<Args>>(args))...));
}
}
};

Expand All @@ -83,13 +61,9 @@ struct function_impl
static param_t<R> func(param_t<Args>... args)
{
if constexpr (std::is_void_v<R>)
{
return Function(convert_cpp<Args>(std::forward<param_t<Args>>(args))...);
}
else
{
return convert_js<param_t<R>>(Function(convert_cpp<Args>(std::forward<param_t<Args>>(args))...));
}
}
};
};
Expand All @@ -109,14 +83,10 @@ class wrapper : public emscripten::wrapper<T>
template<typename R, typename... Args>
R call(const char* name, Args&&... args) const
{
if constexpr (std::is_void_v<R>)
{
return emscripten::wrapper<T>::template call<param_t<R>>(name, convert_js<param_t<Args>>(std::forward<Args>(args))...);
}
else
{
return convert_cpp<R>(emscripten::wrapper<T>::template call<param_t<R>>(name, convert_js<param_t<Args>>(std::forward<Args>(args))...));
}
if constexpr (std::is_void_v<R>)
return emscripten::wrapper<T>::template call<param_t<R>>(name, convert_js<param_t<Args>>(std::forward<Args>(args))...);
else
return convert_cpp<R>(emscripten::wrapper<T>::template call<param_t<R>>(name, convert_js<param_t<Args>>(std::forward<Args>(args))...));
}

};
Expand Down
39 changes: 34 additions & 5 deletions source/scapix/link/js/convert.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,24 @@ namespace scapix {
namespace link {
namespace js {

//template <typename T>
//using param = std::conditional_t<std::experimental::is_detected_v<has_convert_cpp_t<emscripten::val, T>>, emscripten::val, T>;

template <typename T>
struct param
{
using type = emscripten::val;
};

template<>
struct param<void>
{
using type = void;
};

template <typename T>
using param_t = typename param<T>::type;

template <typename Js, typename Cpp, typename = void>
struct convert;

Expand Down Expand Up @@ -318,15 +336,26 @@ struct convert<emscripten::val, std::function<R(Args...)>>
return std::function<R(Args...)>([val](Args... args)
{
if constexpr (std::is_void_v<R>)
val(convert_js<emscripten::val>(args)...);
val(convert_js<emscripten::val>(std::forward<Args>(args))...);
else
return convert_cpp<R>(val(convert_js<emscripten::val>(args)...));
return convert_cpp<R>(val(convert_js<emscripten::val>(std::forward<Args>(args))...));
});
}

// static emscripten::val js(const std::function<R(Args...)>& func)
// {
// }
#if 0
// "BindingError", message: "_emval_take_value has unknown type NSt3__28functionIFvvEEE"

static emscripten::val js(const std::function<R(Args...)>& func)
{
return emscripten::val(std::function<param_t<R>(param_t<Args>...)>([func](param_t<Args>... args)
{
if constexpr (std::is_void_v<R>)
func(convert_cpp<Args>(std::forward<param_t<Args>>(args))...);
else
return convert_js<emscripten::val>(func(convert_cpp<Args>(std::forward<param_t<Args>>(args))...));
}));
}
#endif
};

template <typename Struct>
Expand Down

0 comments on commit 48c34a9

Please sign in to comment.