forked from enlightenment/efl
eldbus-cxx: Implementation of eldbus C++ API
Summary: Applications can: void method_callback(void* data, const Eldbus_Service_Interface* iface, const Eldbus_Message* message); struct { ... } data_struct; Eldbus_Method methods[] = { "method1", ELDBUS_ARGS("b", "bool"), ELDBUS_ARGS("b", "bool"), ELDBUS_METHOD_FLAG_HAS_DATA , (Eldbus_Method_Cb)&method_callback, &data_struct }; And method_callback will be called with data parameter pointing to data_struct global object. Also, Eldbus-cxx supports registering an interface passing a lambda or function object as method. For example: edb::service_interface iface = edb::service_interface_register (c, path, interface , es::method("SendStringAndBool" , [expected_string, expected_bool] (std::string const& n, bool b , bool* out) { std::cout << "Running SendStringAndBool" << std::endl; ck_assert(n == expected_string); ck_assert(b == expected_bool); *out = b; return n; } , es::ins<std::string, bool>("string", "bool") , es::outs<std::string, bool>("string", "bool") ) ); When a request for "SendStringAndBool" with the proper signature is called, executes the lambda and replies with the return value and its bool* out parameter value. Reviewers: cedric, woohyun, raster CC: savio, cedric Differential Revision: https://phab.enlightenment.org/D1052
This commit is contained in:
parent
ddac21534f
commit
30df128be5
|
@ -32,6 +32,7 @@ include Makefile_Evil.am
|
||||||
include Makefile_Escape.am
|
include Makefile_Escape.am
|
||||||
|
|
||||||
include Makefile_Eina.am
|
include Makefile_Eina.am
|
||||||
|
include Makefile_Eina_Cxx.am
|
||||||
include Makefile_Eo.am
|
include Makefile_Eo.am
|
||||||
include Makefile_Eet.am
|
include Makefile_Eet.am
|
||||||
include Makefile_Eolian.am
|
include Makefile_Eolian.am
|
||||||
|
@ -76,6 +77,7 @@ include Makefile_Evas_Cxx.am
|
||||||
endif
|
endif
|
||||||
|
|
||||||
include Makefile_Eina_Cxx.am
|
include Makefile_Eina_Cxx.am
|
||||||
|
include Makefile_Eldbus_Cxx.am
|
||||||
include Makefile_Eolian_Cxx.am
|
include Makefile_Eolian_Cxx.am
|
||||||
include Makefile_Eet_Cxx.am
|
include Makefile_Eet_Cxx.am
|
||||||
include Makefile_Eo_Cxx.am
|
include Makefile_Eo_Cxx.am
|
||||||
|
|
|
@ -8,9 +8,7 @@ dist_installed_eetcxxmainheaders_DATA = bindings/eet_cxx/Eet.hh
|
||||||
installed_eetcxxheadersdir = $(includedir)/eet-cxx-@VMAJ@/eet-cxx
|
installed_eetcxxheadersdir = $(includedir)/eet-cxx-@VMAJ@/eet-cxx
|
||||||
dist_installed_eetcxxheaders_DATA = \
|
dist_installed_eetcxxheaders_DATA = \
|
||||||
bindings/eet_cxx/eet_composite.hh \
|
bindings/eet_cxx/eet_composite.hh \
|
||||||
bindings/eet_cxx/eet_fold.hh \
|
|
||||||
bindings/eet_cxx/eet_register.hh \
|
bindings/eet_cxx/eet_register.hh \
|
||||||
bindings/eet_cxx/eet_tuple.hh \
|
|
||||||
bindings/eet_cxx/eet_type.hh
|
bindings/eet_cxx/eet_type.hh
|
||||||
|
|
||||||
### Unit tests
|
### Unit tests
|
||||||
|
|
|
@ -11,6 +11,7 @@ dist_installed_einacxxheaders_DATA = \
|
||||||
bindings/eina_cxx/eina_accessor.hh \
|
bindings/eina_cxx/eina_accessor.hh \
|
||||||
bindings/eina_cxx/eina_clone_allocators.hh \
|
bindings/eina_cxx/eina_clone_allocators.hh \
|
||||||
bindings/eina_cxx/eina_error.hh \
|
bindings/eina_cxx/eina_error.hh \
|
||||||
|
bindings/eina_cxx/eina_fold.hh \
|
||||||
bindings/eina_cxx/eina_inarray.hh \
|
bindings/eina_cxx/eina_inarray.hh \
|
||||||
bindings/eina_cxx/eina_inlist.hh \
|
bindings/eina_cxx/eina_inlist.hh \
|
||||||
bindings/eina_cxx/eina_integer_sequence.hh \
|
bindings/eina_cxx/eina_integer_sequence.hh \
|
||||||
|
@ -24,6 +25,8 @@ bindings/eina_cxx/eina_range_types.hh \
|
||||||
bindings/eina_cxx/eina_ref.hh \
|
bindings/eina_cxx/eina_ref.hh \
|
||||||
bindings/eina_cxx/eina_stringshare.hh \
|
bindings/eina_cxx/eina_stringshare.hh \
|
||||||
bindings/eina_cxx/eina_thread.hh \
|
bindings/eina_cxx/eina_thread.hh \
|
||||||
|
bindings/eina_cxx/eina_tuple.hh \
|
||||||
|
bindings/eina_cxx/eina_tuple_unwrap.hh \
|
||||||
bindings/eina_cxx/eina_type_traits.hh \
|
bindings/eina_cxx/eina_type_traits.hh \
|
||||||
bindings/eina_cxx/eina_value.hh
|
bindings/eina_cxx/eina_value.hh
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
|
||||||
|
### Library
|
||||||
|
|
||||||
|
installed_eldbuscxxmainheadersdir = $(includedir)/eldbus_cxx-@VMAJ@
|
||||||
|
dist_installed_eldbuscxxmainheaders_DATA = \
|
||||||
|
bindings/eldbus_cxx/eldbus_basic.hh \
|
||||||
|
bindings/eldbus_cxx/eldbus_error.hh \
|
||||||
|
bindings/eldbus_cxx/eldbus_freedesktop.hh \
|
||||||
|
bindings/eldbus_cxx/Eldbus.hh \
|
||||||
|
bindings/eldbus_cxx/eldbus_integer_sequence.hh \
|
||||||
|
bindings/eldbus_cxx/eldbus_message_arguments.hh \
|
||||||
|
bindings/eldbus_cxx/eldbus_message.hh \
|
||||||
|
bindings/eldbus_cxx/eldbus_proxy_call.hh \
|
||||||
|
bindings/eldbus_cxx/eldbus_raw_tuple.hh \
|
||||||
|
bindings/eldbus_cxx/eldbus_service.hh \
|
||||||
|
bindings/eldbus_cxx/eldbus_signature_traits.hh
|
||||||
|
|
||||||
|
### Unit tests
|
||||||
|
|
||||||
|
if EFL_ENABLE_TESTS
|
||||||
|
if HAVE_CXX11
|
||||||
|
|
||||||
|
check_PROGRAMS += tests/eldbus_cxx/eldbus_cxx_suite
|
||||||
|
TESTS += tests/eldbus_cxx/eldbus_cxx_suite
|
||||||
|
|
||||||
|
tests_eldbus_cxx_eldbus_cxx_suite_SOURCES = \
|
||||||
|
tests/eldbus_cxx/eldbus_cxx_suite.cc \
|
||||||
|
tests/eldbus_cxx/eldbus_cxx_test_eldbus_connect.cc \
|
||||||
|
tests/eldbus_cxx/eldbus_cxx_test_eldbus_client.cc
|
||||||
|
|
||||||
|
tests_eldbus_cxx_eldbus_cxx_suite_CPPFLAGS = \
|
||||||
|
-I$(top_builddir)/src/bindings/eina_cxx \
|
||||||
|
-I$(top_srcdir)/src/bindings/eina_cxx \
|
||||||
|
-I$(top_builddir)/src/bindings/ecore_cxx \
|
||||||
|
-I$(top_srcdir)/src/bindings/ecore_cxx \
|
||||||
|
-I$(top_builddir)/src/bindings/eldbus_cxx \
|
||||||
|
-I$(top_srcdir)/src/bindings/eldbus_cxx \
|
||||||
|
-I$(top_builddir)/src/lib/efl \
|
||||||
|
@CHECK_CFLAGS@ \
|
||||||
|
@ELDBUS_CFLAGS@ \
|
||||||
|
-DTESTS_BUILD_DIR=\"$(top_builddir)/src/tests/eldbus\"
|
||||||
|
|
||||||
|
tests_eldbus_cxx_eldbus_cxx_suite_LDADD = @CHECK_LIBS@ @USE_ELDBUS_LIBS@
|
||||||
|
tests_eldbus_cxx_eldbus_cxx_suite_DEPENDENCIES = @USE_ELDBUS_INTERNAL_LIBS@
|
||||||
|
|
||||||
|
endif
|
||||||
|
endif
|
|
@ -4,9 +4,10 @@
|
||||||
#include <Eet.h>
|
#include <Eet.h>
|
||||||
|
|
||||||
#include <eet_type.hh>
|
#include <eet_type.hh>
|
||||||
#include <eet_fold.hh>
|
|
||||||
#include <eet_register.hh>
|
#include <eet_register.hh>
|
||||||
|
|
||||||
|
#include <eina_fold.hh>
|
||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
@ -36,10 +37,10 @@ struct descriptor_type
|
||||||
struct push_back
|
struct push_back
|
||||||
{
|
{
|
||||||
template <typename A, typename B>
|
template <typename A, typename B>
|
||||||
struct apply : _mpl::push_back<A, typename _detail::member_type<typename B::member_type>::type> {};
|
struct apply : eina::_mpl::push_back<A, typename _detail::member_type<typename B::member_type>::type> {};
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef typename _mpl::fold< std::tuple<Args...>, push_back
|
typedef typename eina::_mpl::fold< std::tuple<Args...>, push_back
|
||||||
, descriptor<T> >::type type;
|
, descriptor<T> >::type type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
#ifndef EFL_EET_FOLD_HH_
|
#ifndef EFL_EINA_FOLD_HH_
|
||||||
#define EFL_EET_FOLD_HH_
|
#define EFL_EINA_FOLD_HH_
|
||||||
|
|
||||||
#include <eet_tuple.hh>
|
#include <eina_tuple.hh>
|
||||||
|
|
||||||
namespace efl { namespace eet {
|
namespace efl { namespace eina {
|
||||||
|
|
||||||
namespace _mpl {
|
namespace _mpl {
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ template <typename T, typename F, typename A0, bool B = std::is_same<T, std::tup
|
||||||
struct fold_impl
|
struct fold_impl
|
||||||
{
|
{
|
||||||
typedef typename F::template apply<A0, typename std::tuple_element<0, T>::type>::type result;
|
typedef typename F::template apply<A0, typename std::tuple_element<0, T>::type>::type result;
|
||||||
typedef typename fold_impl<typename pop_front<T>::type
|
typedef typename fold_impl<typename _mpl::pop_front<T>::type
|
||||||
, F, result
|
, F, result
|
||||||
>::type
|
>::type
|
||||||
type;
|
type;
|
|
@ -70,6 +70,36 @@ using index_sequence = integer_sequence<std::size_t, I...>;
|
||||||
template <std::size_t I>
|
template <std::size_t I>
|
||||||
using make_index_sequence = make_integer_sequence<std::size_t, I>;
|
using make_index_sequence = make_integer_sequence<std::size_t, I>;
|
||||||
|
|
||||||
|
template <typename T, typename U>
|
||||||
|
struct pop_integer_sequence_t;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct pop_integer_sequence_t<integer_sequence<T>, integer_sequence<T> >
|
||||||
|
{
|
||||||
|
typedef integer_sequence<T> type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, T S0, T... S>
|
||||||
|
struct pop_integer_sequence_t<integer_sequence<T>, integer_sequence<T, S0, S...> >
|
||||||
|
{
|
||||||
|
typedef integer_sequence<T, S...> type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, T S0, T... S>
|
||||||
|
struct pop_integer_sequence_t<integer_sequence<T, S0, S...>, integer_sequence<T> >
|
||||||
|
{
|
||||||
|
typedef integer_sequence<T> type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, T S, T... Ss1, T... Ss2>
|
||||||
|
struct pop_integer_sequence_t<integer_sequence<T, S, Ss1...>, integer_sequence<T, S, Ss2...> >
|
||||||
|
: pop_integer_sequence_t<integer_sequence<T, Ss1...>, integer_sequence<T, Ss2...> >
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename U>
|
||||||
|
using pop_integer_sequence = typename pop_integer_sequence_t<T, U>::type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
#ifndef EFL_EET_EET_TUPLE_HH_
|
#ifndef EFL_EINA_EINA_TUPLE_HH_
|
||||||
#define EFL_EET_EET_TUPLE_HH_
|
#define EFL_EINA_EINA_TUPLE_HH_
|
||||||
|
|
||||||
namespace efl { namespace eet {
|
namespace efl { namespace eina { namespace _mpl {
|
||||||
|
|
||||||
namespace _mpl {
|
|
||||||
|
|
||||||
template <typename A, typename... Args>
|
template <typename A, typename... Args>
|
||||||
struct push_back;
|
struct push_back;
|
||||||
|
@ -32,8 +30,6 @@ struct pop_front<C<T, Args...> >
|
||||||
typedef C<Args...> type;
|
typedef C<Args...> type;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} } }
|
||||||
|
|
||||||
} }
|
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -0,0 +1,38 @@
|
||||||
|
#ifndef EINA_CXX_EINA_TUPLE_UNWRAP_HH
|
||||||
|
#define EINA_CXX_EINA_TUPLE_UNWRAP_HH
|
||||||
|
|
||||||
|
#include <eina_integer_sequence.hh>
|
||||||
|
|
||||||
|
namespace efl { namespace eina {
|
||||||
|
|
||||||
|
template <typename Callable, typename T, std::size_t... S>
|
||||||
|
auto call_tuple_unwrap(Callable const& callable, T const& tuple
|
||||||
|
, eina::index_sequence<S...>)
|
||||||
|
-> decltype(callable(std::get<S>(tuple)...))
|
||||||
|
{
|
||||||
|
return callable(std::get<S>(tuple)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Callable, typename T, std::size_t... S
|
||||||
|
, typename... Args>
|
||||||
|
auto call_tuple_unwrap_prefix(Callable const& callable, T const& tuple
|
||||||
|
, eina::index_sequence<S...>
|
||||||
|
, Args&&... args)
|
||||||
|
-> decltype(callable(std::move(args)..., std::get<S>(tuple)...))
|
||||||
|
{
|
||||||
|
return callable(std::move(args)..., std::get<S>(tuple)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Callable, typename T, std::size_t... S
|
||||||
|
, typename... Args>
|
||||||
|
auto call_tuple_unwrap_suffix(Callable const& callable, T const& tuple
|
||||||
|
, eina::index_sequence<S...>
|
||||||
|
, Args&&... args)
|
||||||
|
-> decltype(callable(std::get<S>(tuple)..., std::move(args)...))
|
||||||
|
{
|
||||||
|
return callable(std::get<S>(tuple)..., std::move(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
} }
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,13 @@
|
||||||
|
#ifndef EFL_ELDBUS_HH_
|
||||||
|
#define EFL_ELDBUS_HH_
|
||||||
|
|
||||||
|
#include <Eina.hh>
|
||||||
|
#include <Eldbus.h>
|
||||||
|
|
||||||
|
#include <eldbus_basic.hh>
|
||||||
|
#include <eldbus_proxy_call.hh>
|
||||||
|
#include <eldbus_message.hh>
|
||||||
|
#include <eldbus_service.hh>
|
||||||
|
#include <eina_integer_sequence.hh>
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,150 @@
|
||||||
|
#ifndef ELDBUS_CXX_ELDBUS_BASIC_HH
|
||||||
|
#define ELDBUS_CXX_ELDBUS_BASIC_HH
|
||||||
|
|
||||||
|
#include <Eina.hh>
|
||||||
|
#include <Eldbus.h>
|
||||||
|
|
||||||
|
#include <eldbus_proxy_call.hh>
|
||||||
|
|
||||||
|
namespace efl { namespace eldbus {
|
||||||
|
|
||||||
|
struct unknown_t {};
|
||||||
|
struct session_t {};
|
||||||
|
struct system_t {};
|
||||||
|
struct start_t {};
|
||||||
|
struct address_t {};
|
||||||
|
|
||||||
|
unknown_t const unknown = unknown_t();
|
||||||
|
session_t const session = session_t();
|
||||||
|
system_t const system = system_t();
|
||||||
|
start_t const start = start_t();
|
||||||
|
address_t const address = address_t();
|
||||||
|
|
||||||
|
struct eldbus_init
|
||||||
|
{
|
||||||
|
eldbus_init()
|
||||||
|
{
|
||||||
|
::eldbus_init();
|
||||||
|
}
|
||||||
|
~eldbus_init()
|
||||||
|
{
|
||||||
|
::eldbus_shutdown();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct proxy
|
||||||
|
{
|
||||||
|
typedef Eldbus_Proxy* native_handle_type;
|
||||||
|
typedef Eldbus_Proxy const* const_native_handle_type;
|
||||||
|
|
||||||
|
proxy(native_handle_type native)
|
||||||
|
: _proxy(native) {}
|
||||||
|
|
||||||
|
template <typename R, typename Callback, typename... Args>
|
||||||
|
void call(const char* method, double timeout, Callback&& callback, Args... args) const
|
||||||
|
{
|
||||||
|
eldbus::_detail::proxy_call<R>(_proxy, method, timeout, std::move(callback), args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Callback, typename... Args>
|
||||||
|
void call(const char* method, double timeout, Callback&& callback, Args... args) const
|
||||||
|
{
|
||||||
|
eldbus::_detail::proxy_call<void>(_proxy, method, timeout, std::move(callback), args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
native_handle_type native_handle() { return _proxy; }
|
||||||
|
const_native_handle_type native_handle() const { return _proxy; }
|
||||||
|
private:
|
||||||
|
native_handle_type _proxy;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct object
|
||||||
|
{
|
||||||
|
typedef Eldbus_Object* native_handle_type;
|
||||||
|
typedef Eldbus_Object const* const_native_handle_type;
|
||||||
|
object(native_handle_type o)
|
||||||
|
: _object(o) {}
|
||||||
|
|
||||||
|
proxy get_proxy(const char* interface_) const
|
||||||
|
{
|
||||||
|
Eldbus_Proxy* p = eldbus_proxy_get
|
||||||
|
(const_cast<object*>(this)->native_handle(), interface_);
|
||||||
|
if(!p)
|
||||||
|
{
|
||||||
|
eina::error_code ec = eina::get_error_code();
|
||||||
|
assert(!!ec);
|
||||||
|
throw eina::system_error(ec, "eldbus");
|
||||||
|
}
|
||||||
|
return proxy(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
native_handle_type native_handle() { return _object; }
|
||||||
|
const_native_handle_type const_native_handle() { return _object; }
|
||||||
|
private:
|
||||||
|
native_handle_type _object;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct connection
|
||||||
|
{
|
||||||
|
typedef Eldbus_Connection* native_handle_type;
|
||||||
|
typedef Eldbus_Connection const* const_native_handle_type;
|
||||||
|
|
||||||
|
explicit connection(native_handle_type connection)
|
||||||
|
: _connection(connection) {}
|
||||||
|
~connection()
|
||||||
|
{
|
||||||
|
eldbus_connection_unref(_connection);
|
||||||
|
}
|
||||||
|
connection(unknown_t)
|
||||||
|
: _connection(eldbus_connection_get(ELDBUS_CONNECTION_TYPE_UNKNOWN))
|
||||||
|
{
|
||||||
|
_check_connection();
|
||||||
|
}
|
||||||
|
connection(session_t)
|
||||||
|
: _connection(eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SESSION))
|
||||||
|
{
|
||||||
|
_check_connection();
|
||||||
|
}
|
||||||
|
connection(system_t)
|
||||||
|
: _connection(eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SYSTEM))
|
||||||
|
{
|
||||||
|
_check_connection();
|
||||||
|
}
|
||||||
|
connection(address_t)
|
||||||
|
: _connection(eldbus_connection_get(ELDBUS_CONNECTION_TYPE_ADDRESS))
|
||||||
|
{
|
||||||
|
_check_connection();
|
||||||
|
}
|
||||||
|
|
||||||
|
object get_object(const char* bus, const char* path) const
|
||||||
|
{
|
||||||
|
Eldbus_Object* o = eldbus_object_get
|
||||||
|
(const_cast<connection*>(this)->native_handle(), bus, path);
|
||||||
|
if(!o)
|
||||||
|
{
|
||||||
|
eina::error_code ec = eina::get_error_code();
|
||||||
|
assert(!!ec);
|
||||||
|
throw eina::system_error(ec, "eldbus");
|
||||||
|
}
|
||||||
|
return object(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
native_handle_type native_handle() { return _connection; }
|
||||||
|
const_native_handle_type native_handle() const { return _connection; }
|
||||||
|
private:
|
||||||
|
void _check_connection()
|
||||||
|
{
|
||||||
|
if(!_connection)
|
||||||
|
{
|
||||||
|
eina::error_code ec = eina::get_error_code();
|
||||||
|
assert(!!ec);
|
||||||
|
throw eina::system_error(ec, "eldbus");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
native_handle_type _connection;
|
||||||
|
};
|
||||||
|
|
||||||
|
} }
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,22 @@
|
||||||
|
#ifndef ELDBUS_ERROR_HH
|
||||||
|
#define ELDBUS_ERROR_HH
|
||||||
|
|
||||||
|
#include <Eina.hh>
|
||||||
|
|
||||||
|
namespace efl { namespace eldbus {
|
||||||
|
|
||||||
|
inline Eina_Error call_error_code()
|
||||||
|
{
|
||||||
|
static Eina_Error error = eina_error_msg_static_register("Error while making eldbus rpc call");
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Eina_Error signature_mismatch_error_code()
|
||||||
|
{
|
||||||
|
static Eina_Error error = eina_error_msg_static_register("Mismatch function signature and signature specification");
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
} }
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,73 @@
|
||||||
|
#ifndef EFL_ELDBUS_CXX_ELDBUS_FREEDESKTOP_HH
|
||||||
|
#define EFL_ELDBUS_CXX_ELDBUS_FREEDESKTOP_HH
|
||||||
|
|
||||||
|
#include <eldbus_message.hh>
|
||||||
|
#include <eldbus_service.hh>
|
||||||
|
#include <eldbus_basic.hh>
|
||||||
|
#include <eldbus_raw_tuple.hh>
|
||||||
|
|
||||||
|
namespace efl { namespace eldbus { namespace _detail {
|
||||||
|
|
||||||
|
template <typename Callback, typename... Ins>
|
||||||
|
void _callback_wrapper(void* data, Eldbus_Message const* message, Eldbus_Pending* pending)
|
||||||
|
{
|
||||||
|
std::cout << "_callback_wrapper" << std::endl;
|
||||||
|
Callback* callback(static_cast<Callback*>(data));
|
||||||
|
|
||||||
|
const char* errname, *errmsg;
|
||||||
|
if (eldbus_message_error_get(message, &errname, &errmsg))
|
||||||
|
{
|
||||||
|
std::cout << "error " << errname << " " << errmsg << std::endl;
|
||||||
|
std::tuple<Ins...> tuple;
|
||||||
|
eldbus::const_message msg( ::eldbus_message_ref(const_cast<Eldbus_Message*>(message)));
|
||||||
|
eina::error_code ec (eldbus::call_error_code(), eina::eina_error_category());
|
||||||
|
eina::call_tuple_unwrap_prefix
|
||||||
|
(*callback, tuple, eina::make_index_sequence<sizeof...(Ins)>()
|
||||||
|
, ec, msg, pending);
|
||||||
|
}
|
||||||
|
|
||||||
|
typename raw_tuple<std::tuple<Ins...> >::type tuple;
|
||||||
|
if(sizeof...(Ins))
|
||||||
|
{
|
||||||
|
if(!_detail::_init_raw_tuple<0u, std::tuple<Ins...> >
|
||||||
|
(eldbus_message_iter_get(message)
|
||||||
|
, tuple, std::integral_constant<bool, (sizeof...(Ins) == 0)>()))
|
||||||
|
{
|
||||||
|
std::cout << "error init raw tuple" << std::endl;
|
||||||
|
std::tuple<Ins...> tuple;
|
||||||
|
eldbus::const_message msg( ::eldbus_message_ref(const_cast<Eldbus_Message*>(message)));
|
||||||
|
eina::error_code ec(eldbus::signature_mismatch_error_code(), eina::eina_error_category());
|
||||||
|
eina::call_tuple_unwrap_prefix
|
||||||
|
(*callback, tuple, eina::make_index_sequence<sizeof...(Ins)>()
|
||||||
|
, ec, msg, pending);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cout << "OK go" << std::endl;
|
||||||
|
eina::error_code ec;
|
||||||
|
eldbus::const_message msg( ::eldbus_message_ref(const_cast<Eldbus_Message*>(message)));
|
||||||
|
eina::call_tuple_unwrap_prefix
|
||||||
|
(*callback, tuple, eina::make_index_sequence<sizeof...(Ins)>()
|
||||||
|
, ec, msg, pending);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename F>
|
||||||
|
void _free_cb(void* data, const void*)
|
||||||
|
{
|
||||||
|
delete static_cast<F*>(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Ins, typename F>
|
||||||
|
pending name_request(connection& c, const char* bus, unsigned int flags, F&& function)
|
||||||
|
{
|
||||||
|
F* f = new F(std::move(function));
|
||||||
|
pending r = ::eldbus_name_request(c.native_handle(), bus, flags
|
||||||
|
, &_detail::_callback_wrapper<F, Ins...>, f);
|
||||||
|
eldbus_pending_free_cb_add(r.native_handle(), &_detail::_free_cb<F>, f);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
} }
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,41 @@
|
||||||
|
#ifndef ELDBUS_CXX_ELDBUS_INTEGER_SEQUENCE_HH
|
||||||
|
#define ELDBUS_CXX_ELDBUS_INTEGER_SEQUENCE_HH
|
||||||
|
|
||||||
|
namespace efl { namespace eldbus { namespace _detail {
|
||||||
|
|
||||||
|
template <typename T, T... Ints>
|
||||||
|
struct integer_sequence
|
||||||
|
{
|
||||||
|
typedef T value_type;
|
||||||
|
static constexpr std::size_t size() { return sizeof...(Ints); }
|
||||||
|
typedef integer_sequence<T, Ints...> type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class S1, class S2> struct concat;
|
||||||
|
|
||||||
|
template<typename T, T... I1, T... I2>
|
||||||
|
struct concat<integer_sequence<T, I1...>, integer_sequence<T, I2...> >
|
||||||
|
: integer_sequence<T, I1..., (sizeof...(I1)+I2)...> {};
|
||||||
|
|
||||||
|
template<class S1, class S2>
|
||||||
|
using Concat = typename concat<S1, S2>::type;
|
||||||
|
|
||||||
|
template<typename T, T N> struct gen_seq;
|
||||||
|
template<typename T, T N> using make_integer_sequence = typename gen_seq<T, N>::type;
|
||||||
|
|
||||||
|
template<typename T, T N>
|
||||||
|
struct gen_seq : Concat<make_integer_sequence<T, N/2>
|
||||||
|
, make_integer_sequence<T, N - N/2>>{};
|
||||||
|
|
||||||
|
template<> struct gen_seq<std::size_t, 0> : integer_sequence<std::size_t>{};
|
||||||
|
template<> struct gen_seq<std::size_t, 1> : integer_sequence<std::size_t, 0>{};
|
||||||
|
|
||||||
|
template <std::size_t... I>
|
||||||
|
using index_sequence = integer_sequence<std::size_t, I...>;
|
||||||
|
|
||||||
|
template <std::size_t I>
|
||||||
|
using make_index_sequence = make_integer_sequence<std::size_t, I>;
|
||||||
|
|
||||||
|
} } }
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,283 @@
|
||||||
|
#ifndef ELDBUS_CXX_ELDBUS_MESSAGE_HH
|
||||||
|
#define ELDBUS_CXX_ELDBUS_MESSAGE_HH
|
||||||
|
|
||||||
|
#include <Eldbus.h>
|
||||||
|
#include <eldbus_signature_traits.hh>
|
||||||
|
|
||||||
|
namespace efl { namespace eldbus {
|
||||||
|
|
||||||
|
struct message_value
|
||||||
|
{
|
||||||
|
message_value() : _iterator(0) {}
|
||||||
|
message_value( ::Eldbus_Message_Iter* iterator) : _iterator(iterator) {}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T get() const
|
||||||
|
{
|
||||||
|
assert(!!_iterator);
|
||||||
|
std::cout << "trying to read " << _detail::signature_traits<T>::sig
|
||||||
|
<< " has " << eldbus_message_iter_signature_get(_iterator) << std::endl;
|
||||||
|
T object;
|
||||||
|
char* c = eldbus_message_iter_signature_get(_iterator);
|
||||||
|
if(c[0] != _detail::signature_traits<T>::sig)
|
||||||
|
throw std::runtime_error("");
|
||||||
|
eldbus_message_iter_arguments_get(_iterator, c, &object);
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
friend inline bool operator==(message_value const& lhs, message_value const& rhs)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
lhs._iterator == rhs._iterator
|
||||||
|
|| (!lhs._iterator && rhs._iterator && std::strlen(eldbus_message_iter_signature_get(rhs._iterator)) == 0)
|
||||||
|
|| (!rhs._iterator && lhs._iterator && std::strlen(eldbus_message_iter_signature_get(lhs._iterator)) == 0)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
friend struct message_iterator;
|
||||||
|
::Eldbus_Message_Iter* _iterator;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool operator!=(message_value const& lhs, message_value const& rhs)
|
||||||
|
{
|
||||||
|
return !(lhs == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct message_iterator
|
||||||
|
{
|
||||||
|
typedef message_value value_type;
|
||||||
|
typedef value_type& reference;
|
||||||
|
typedef value_type const& const_reference;
|
||||||
|
typedef value_type* pointer;
|
||||||
|
typedef value_type const* const_pointer;
|
||||||
|
typedef std::ptrdiff_t difference_type;
|
||||||
|
typedef std::size_t size_type;
|
||||||
|
typedef std::input_iterator_tag iterator_category;
|
||||||
|
|
||||||
|
message_iterator()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
message_iterator(Eldbus_Message_Iter* iterator)
|
||||||
|
: value(iterator)
|
||||||
|
{}
|
||||||
|
|
||||||
|
reference operator*() const
|
||||||
|
{
|
||||||
|
return const_cast<reference>(value);
|
||||||
|
}
|
||||||
|
pointer operator->() const
|
||||||
|
{
|
||||||
|
return const_cast<pointer>(&value);
|
||||||
|
}
|
||||||
|
message_iterator& operator++()
|
||||||
|
{
|
||||||
|
if(!eldbus_message_iter_next(value._iterator))
|
||||||
|
{
|
||||||
|
value._iterator = 0;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
message_iterator operator++() const
|
||||||
|
{
|
||||||
|
message_iterator tmp(*this);
|
||||||
|
++*this;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
friend inline bool operator==(message_iterator const& lhs, message_iterator const& rhs)
|
||||||
|
{
|
||||||
|
return lhs.value == rhs.value;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
message_value value;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool operator!=(message_iterator const& lhs, message_iterator const& rhs)
|
||||||
|
{
|
||||||
|
return !(lhs == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct reply_t {};
|
||||||
|
struct error_t {};
|
||||||
|
struct method_call_t {};
|
||||||
|
|
||||||
|
reply_t const reply = {};
|
||||||
|
error_t const error = {};
|
||||||
|
method_call_t const method_call = {};
|
||||||
|
|
||||||
|
struct const_message
|
||||||
|
{
|
||||||
|
explicit const_message(Eldbus_Message const* message) : _message(message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
const_message(const_message const& other, reply_t)
|
||||||
|
: _message( ::eldbus_message_method_return_new(other.native_handle()))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
const_message(const_message const& other, const char* error_name, const char* error_msg, error_t)
|
||||||
|
: _message( ::eldbus_message_error_new(other.native_handle(), error_name, error_msg))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
const_message(const char* destination, const char* path, const char* iface
|
||||||
|
, const char* method, method_call_t)
|
||||||
|
: _message( ::eldbus_message_method_call_new(destination, path, iface, method))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
const_message(const_message const& other)
|
||||||
|
: _message( ::eldbus_message_ref(const_cast<Eldbus_Message*>(other.native_handle())))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
~const_message()
|
||||||
|
{
|
||||||
|
eldbus_message_unref(const_cast<Eldbus_Message*>(native_handle()));
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* path_get() const
|
||||||
|
{
|
||||||
|
return ::eldbus_message_path_get(_message);
|
||||||
|
}
|
||||||
|
const char* interface_get() const
|
||||||
|
{
|
||||||
|
return ::eldbus_message_interface_get(_message);
|
||||||
|
}
|
||||||
|
const char* member_get() const
|
||||||
|
{
|
||||||
|
return ::eldbus_message_member_get(_message);
|
||||||
|
}
|
||||||
|
const char* destination_get() const
|
||||||
|
{
|
||||||
|
return ::eldbus_message_destination_get(_message);
|
||||||
|
}
|
||||||
|
const char* sender_get() const
|
||||||
|
{
|
||||||
|
return ::eldbus_message_sender_get(_message);
|
||||||
|
}
|
||||||
|
const char* signature_get() const
|
||||||
|
{
|
||||||
|
return ::eldbus_message_signature_get(_message);
|
||||||
|
}
|
||||||
|
bool operator!() const
|
||||||
|
{
|
||||||
|
bool b (*this);
|
||||||
|
return !b;
|
||||||
|
}
|
||||||
|
explicit operator bool() const
|
||||||
|
{
|
||||||
|
const char* name, * text;
|
||||||
|
return !eldbus_message_error_get(_message, &name, &text);
|
||||||
|
}
|
||||||
|
std::pair<const char*, const char*> error_get() const
|
||||||
|
{
|
||||||
|
const char* name, * text;
|
||||||
|
eldbus_message_error_get(_message, &name, &text);
|
||||||
|
return {name, text};
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef message_iterator const_iterator;
|
||||||
|
typedef const_iterator iterator;
|
||||||
|
typedef Eldbus_Message const* native_handle_type;
|
||||||
|
typedef Eldbus_Message const* const_native_handle_type;
|
||||||
|
const_native_handle_type native_handle() const { return _message; }
|
||||||
|
const_native_handle_type const_native_handle() const { return _message; }
|
||||||
|
|
||||||
|
const_iterator begin() const
|
||||||
|
{
|
||||||
|
return const_iterator( ::eldbus_message_iter_get(_message));
|
||||||
|
}
|
||||||
|
const_iterator end() const
|
||||||
|
{
|
||||||
|
return const_iterator();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
Eldbus_Message const* _message;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct message : const_message
|
||||||
|
{
|
||||||
|
typedef const_message base_type;
|
||||||
|
|
||||||
|
explicit message(Eldbus_Message* message) : const_message(message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
message(const_message const& other, reply_t r)
|
||||||
|
: const_message(other, r)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
message(const_message const& other, const char* error_name, const char* error_msg, error_t e)
|
||||||
|
: const_message(other, error_name, error_msg, e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
message(const char* destination, const char* path, const char* iface
|
||||||
|
, const char* method, method_call_t m)
|
||||||
|
: const_message(destination, path, iface, method, m)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
message(message const& other)
|
||||||
|
: const_message(static_cast<base_type const&>(other))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
typedef Eldbus_Message* native_handle_type;
|
||||||
|
native_handle_type native_handle() { return const_cast<native_handle_type>(const_message::native_handle()); }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct const_pending
|
||||||
|
{
|
||||||
|
const_pending() : _pending(0) {}
|
||||||
|
const_pending(Eldbus_Pending const* pending) : _pending(pending) {}
|
||||||
|
|
||||||
|
void* data_get(const char* key) const
|
||||||
|
{
|
||||||
|
return ::eldbus_pending_data_get(_pending, key);
|
||||||
|
}
|
||||||
|
const char* destination_get() const
|
||||||
|
{
|
||||||
|
return ::eldbus_pending_destination_get(_pending);
|
||||||
|
}
|
||||||
|
const char* path_get() const
|
||||||
|
{
|
||||||
|
return ::eldbus_pending_path_get(_pending);
|
||||||
|
}
|
||||||
|
const char* interface_get() const
|
||||||
|
{
|
||||||
|
return ::eldbus_pending_interface_get(_pending);
|
||||||
|
}
|
||||||
|
const char* method_get() const
|
||||||
|
{
|
||||||
|
return ::eldbus_pending_method_get(_pending);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef Eldbus_Pending const* native_handle_type;
|
||||||
|
typedef Eldbus_Pending const* const_native_handle_type;
|
||||||
|
native_handle_type native_handle() const { return _pending; }
|
||||||
|
const_native_handle_type const_native_handle() const { return _pending; }
|
||||||
|
private:
|
||||||
|
const_native_handle_type _pending;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pending : const_pending
|
||||||
|
{
|
||||||
|
pending() : const_pending(0) {}
|
||||||
|
pending(Eldbus_Pending* pending) : const_pending(pending) {}
|
||||||
|
|
||||||
|
void data_set(const char* key, const char* data)
|
||||||
|
{
|
||||||
|
::eldbus_pending_data_set(native_handle(), key, data);
|
||||||
|
}
|
||||||
|
void* data_del(const char* key)
|
||||||
|
{
|
||||||
|
return ::eldbus_pending_data_del(native_handle(), key);
|
||||||
|
}
|
||||||
|
void cancel()
|
||||||
|
{
|
||||||
|
::eldbus_pending_cancel(native_handle());
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef Eldbus_Pending* native_handle_type;
|
||||||
|
native_handle_type native_handle()
|
||||||
|
{
|
||||||
|
return const_cast<native_handle_type>(const_pending::native_handle());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} }
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,56 @@
|
||||||
|
#ifndef ELDBUS_CXX_ELDBUS_MESSAGE_ARGUMENTS_HH
|
||||||
|
#define ELDBUS_CXX_ELDBUS_MESSAGE_ARGUMENTS_HH
|
||||||
|
|
||||||
|
#include <Eldbus.h>
|
||||||
|
|
||||||
|
#include <tuple>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace efl { namespace eldbus { namespace _detail {
|
||||||
|
|
||||||
|
template <std::size_t I, typename Seq, typename Tuple>
|
||||||
|
bool _init_raw_tuple(Eldbus_Message_Iter*, Tuple const&, std::true_type)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <std::size_t I, typename Seq, typename Tuple>
|
||||||
|
bool _init_raw_tuple(Eldbus_Message_Iter* iterator, Tuple const& tuple, std::false_type)
|
||||||
|
{
|
||||||
|
typedef signature_traits<typename std::tuple_element<I, Seq>::type> traits;
|
||||||
|
typedef typename traits::value_type element_type;
|
||||||
|
|
||||||
|
char* c = eldbus_message_iter_signature_get(iterator);
|
||||||
|
if(c[0] != signature_traits<element_type>::sig)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
eldbus_message_iter_get_and_next(iterator, *c, &std::get<I>(tuple));
|
||||||
|
|
||||||
|
return _init_raw_tuple<I+1, Seq>
|
||||||
|
(iterator, tuple, std::integral_constant<bool, (I+1 == std::tuple_size<Tuple>::value)>());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <std::size_t I, typename Tuple>
|
||||||
|
bool _append_tuple(Eldbus_Message*, Tuple const&, std::true_type)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <std::size_t I, typename Tuple>
|
||||||
|
bool _append_tuple(Eldbus_Message* message, Tuple const& tuple, std::false_type)
|
||||||
|
{
|
||||||
|
typedef signature_traits<typename std::tuple_element<I, Tuple>::type> traits;
|
||||||
|
|
||||||
|
char signature[2] = {traits::sig, 0};
|
||||||
|
if(!eldbus_message_arguments_append(message, signature, traits::to_raw(std::get<I>(tuple))))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return _append_tuple<I+1>
|
||||||
|
(message, tuple, std::integral_constant<bool, (I+1 == std::tuple_size<Tuple>::value)>());
|
||||||
|
}
|
||||||
|
|
||||||
|
} } }
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,117 @@
|
||||||
|
#ifndef ELDBUS_PROXY_CALL_HH
|
||||||
|
#define ELDBUS_PROXY_CALL_HH
|
||||||
|
|
||||||
|
#include <Eina.hh>
|
||||||
|
#include <eldbus_error.hh>
|
||||||
|
#include <eldbus_signature_traits.hh>
|
||||||
|
#include <eldbus_message_arguments.hh>
|
||||||
|
#include <eldbus_message.hh>
|
||||||
|
#include <eldbus_raw_tuple.hh>
|
||||||
|
#include <eina_integer_sequence.hh>
|
||||||
|
#include <eina_tuple_unwrap.hh>
|
||||||
|
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace efl { namespace eldbus { namespace _detail {
|
||||||
|
|
||||||
|
template <typename T> struct tag {};
|
||||||
|
|
||||||
|
template <typename Seq, typename Callback, std::size_t... I>
|
||||||
|
void _on_call_impl(void* data, Eldbus_Message const* message, Eldbus_Pending* pending)
|
||||||
|
{
|
||||||
|
std::unique_ptr<Callback> callback(static_cast<Callback*>(data));
|
||||||
|
|
||||||
|
const char* errname, *errmsg;
|
||||||
|
if (eldbus_message_error_get(message, &errname, &errmsg))
|
||||||
|
{
|
||||||
|
Seq tuple;
|
||||||
|
::eldbus_message_ref(const_cast<Eldbus_Message*>(message));
|
||||||
|
eldbus::const_message msg(message);
|
||||||
|
eina::error_code ec (eldbus::call_error_code(), eina::eina_error_category());
|
||||||
|
eina::call_tuple_unwrap_prefix
|
||||||
|
(*callback, tuple, eina::make_index_sequence<std::tuple_size<Seq>::value>()
|
||||||
|
, ec, msg, pending);
|
||||||
|
}
|
||||||
|
|
||||||
|
typename raw_tuple<Seq>::type tuple;
|
||||||
|
if(std::tuple_size<Seq>::value)
|
||||||
|
{
|
||||||
|
if(!_detail::_init_raw_tuple<0u, Seq>
|
||||||
|
(eldbus_message_iter_get(message)
|
||||||
|
, tuple, std::integral_constant<bool, (std::tuple_size<Seq>::value == 0)>()))
|
||||||
|
{
|
||||||
|
Seq tuple;
|
||||||
|
::eldbus_message_ref(const_cast<Eldbus_Message*>(message));
|
||||||
|
eldbus::const_message msg(message);
|
||||||
|
eina::error_code ec(eldbus::signature_mismatch_error_code(), eina::eina_error_category());
|
||||||
|
eina::call_tuple_unwrap_prefix
|
||||||
|
(*callback, tuple, eina::make_index_sequence<std::tuple_size<Seq>::value>()
|
||||||
|
, ec, msg, pending);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
eina::error_code ec;
|
||||||
|
::eldbus_message_ref(const_cast<Eldbus_Message*>(message));
|
||||||
|
eldbus::const_message msg(message);
|
||||||
|
eina::call_tuple_unwrap_prefix
|
||||||
|
(*callback, tuple, eina::make_index_sequence<std::tuple_size<Seq>::value>()
|
||||||
|
, ec, msg, pending);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Seq, typename Callback>
|
||||||
|
void _on_call(void* data, Eldbus_Message const* message, Eldbus_Pending* pending)
|
||||||
|
{
|
||||||
|
_detail::_on_call_impl<Seq, Callback>(data, message, pending);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename R, typename Callback, typename... Args>
|
||||||
|
void proxy_call_impl2(Eldbus_Proxy* proxy, const char* method, double timeout
|
||||||
|
, Callback&& callback, Args const&... args)
|
||||||
|
{
|
||||||
|
typedef std::tuple<Args...> tuple_args;
|
||||||
|
char signature[signature_size<tuple_args>::value +1];
|
||||||
|
_detail::init_signature_array<Args...>
|
||||||
|
(signature, eina::make_index_sequence<signature_size<tuple_args>::value +1>());
|
||||||
|
|
||||||
|
Callback* c = new Callback(std::move(callback));
|
||||||
|
|
||||||
|
eldbus_proxy_call(proxy, method, &_on_call<R, Callback>, c, timeout, signature
|
||||||
|
, _detail::to_raw(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename R, typename Callback, typename... Args>
|
||||||
|
void proxy_call_impl(tag<R>, Eldbus_Proxy* proxy, const char* method, double timeout
|
||||||
|
, Callback&& callback, Args const&... args)
|
||||||
|
{
|
||||||
|
typedef std::tuple<R> reply_tuple;
|
||||||
|
_detail::proxy_call_impl2<reply_tuple>(proxy, method, timeout, std::move(callback), args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... R, typename Callback, typename... Args>
|
||||||
|
void proxy_call_impl(tag<std::tuple<R...> >, Eldbus_Proxy* proxy, const char* method, double timeout
|
||||||
|
, Callback&& callback, Args const&... args)
|
||||||
|
{
|
||||||
|
typedef std::tuple<R...> reply_tuple;
|
||||||
|
_detail::proxy_call_impl2<reply_tuple>(proxy, method, timeout, std::move(callback), args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Callback, typename... Args>
|
||||||
|
void proxy_call_impl(tag<void>, Eldbus_Proxy* proxy, const char* method, double timeout
|
||||||
|
, Callback&& callback, Args const&... args)
|
||||||
|
{
|
||||||
|
typedef std::tuple<> reply_tuple;
|
||||||
|
_detail::proxy_call_impl2<reply_tuple>(proxy, method, timeout, std::move(callback), args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename R, typename Callback, typename... Args>
|
||||||
|
void proxy_call(Eldbus_Proxy* proxy, const char* method, double timeout
|
||||||
|
, Callback&& callback, Args const&... args)
|
||||||
|
{
|
||||||
|
return proxy_call_impl(tag<R>(), proxy, method, timeout, std::move(callback), args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
} } }
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
#ifndef EFL_ELDBUS_CXX_ELDBUS_RAW_TUPLE_HH
|
||||||
|
#define EFL_ELDBUS_CXX_ELDBUS_RAW_TUPLE_HH
|
||||||
|
|
||||||
|
#include <eldbus_signature_traits.hh>
|
||||||
|
|
||||||
|
#include <eina_fold.hh>
|
||||||
|
#include <eina_tuple.hh>
|
||||||
|
|
||||||
|
namespace efl { namespace eldbus { namespace _detail {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct raw_tuple;
|
||||||
|
|
||||||
|
template <typename... T>
|
||||||
|
struct raw_tuple<std::tuple<T...> >
|
||||||
|
{
|
||||||
|
struct push_back
|
||||||
|
{
|
||||||
|
template <typename L, typename R>
|
||||||
|
struct apply
|
||||||
|
: eina::_mpl::push_back<L, typename signature_traits<R>::raw_type> {};
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef typename eina::_mpl::fold< std::tuple<T...>, push_back
|
||||||
|
, std::tuple<> >::type type;
|
||||||
|
};
|
||||||
|
|
||||||
|
} } }
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,379 @@
|
||||||
|
#ifndef ELDBUS_CXX_ELDBUS_SERVICE_HH
|
||||||
|
#define ELDBUS_CXX_ELDBUS_SERVICE_HH
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
namespace efl { namespace eldbus {
|
||||||
|
|
||||||
|
struct service_interface
|
||||||
|
{
|
||||||
|
service_interface(Eldbus_Service_Interface const* iface)
|
||||||
|
: _iface(iface)
|
||||||
|
{}
|
||||||
|
|
||||||
|
typedef Eldbus_Service_Interface* native_handle_type;
|
||||||
|
typedef Eldbus_Service_Interface const* const_native_handle_type;
|
||||||
|
const_native_handle_type native_handle() { return _iface; }
|
||||||
|
const_native_handle_type native_handle() const { return _iface; }
|
||||||
|
private:
|
||||||
|
const_native_handle_type _iface;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace service {
|
||||||
|
|
||||||
|
template <typename F, typename Ins, typename Outs>
|
||||||
|
struct method_specification
|
||||||
|
{
|
||||||
|
const char* name;
|
||||||
|
F f;
|
||||||
|
|
||||||
|
typedef F function_type;
|
||||||
|
typedef Ins ins_type;
|
||||||
|
typedef Outs outs_type;
|
||||||
|
|
||||||
|
ins_type ins;
|
||||||
|
outs_type outs;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace _detail {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct const_char_type
|
||||||
|
{
|
||||||
|
typedef const char* type;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
struct ins
|
||||||
|
{
|
||||||
|
ins(typename _detail::const_char_type<Args>::type... names) : _names({names...}) {}
|
||||||
|
|
||||||
|
static constexpr std::size_t size() { return sizeof...(Args); }
|
||||||
|
|
||||||
|
typedef std::tuple<Args...> types;
|
||||||
|
std::array<const char*, sizeof...(Args)> _names;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
struct outs
|
||||||
|
{
|
||||||
|
outs(typename _detail::const_char_type<Args>::type... names) : _names({names...}) {}
|
||||||
|
|
||||||
|
static constexpr std::size_t size() { return sizeof...(Args); }
|
||||||
|
|
||||||
|
typedef std::tuple<Args...> types;
|
||||||
|
std::array<const char*, sizeof...(Args)> _names;
|
||||||
|
};
|
||||||
|
|
||||||
|
void foo(int);
|
||||||
|
|
||||||
|
template <typename F, typename Ins, typename Outs>
|
||||||
|
method_specification<F, Ins, Outs>
|
||||||
|
method(const char* name, F f, Ins ins, Outs outs)
|
||||||
|
{
|
||||||
|
return method_specification<F, Ins, Outs>
|
||||||
|
{name, f, ins, outs}
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename F, typename... Outs>
|
||||||
|
method_specification<F, service::ins<>, service::outs<Outs...> >
|
||||||
|
method(const char* name, F f, service::outs<Outs...> outs)
|
||||||
|
{
|
||||||
|
return method_specification<F, service::ins<>, service::outs<Outs...> >
|
||||||
|
{name, f, service::ins<>(), outs}
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename F, typename... Ins>
|
||||||
|
method_specification<F, service::ins<Ins...>, service::outs<> >
|
||||||
|
method(const char* name, F f, service::ins<Ins...> ins)
|
||||||
|
{
|
||||||
|
return method_specification<F, service::ins<Ins...>, service::outs<> >
|
||||||
|
{name, f, ins, service::outs<>()}
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template <std::size_t I, std::size_t N, template <typename...> class params
|
||||||
|
, typename ... Args>
|
||||||
|
int _fill_method_impl(std::array<Eldbus_Arg_Info, N>& array
|
||||||
|
, params<Args...> const&
|
||||||
|
, std::true_type)
|
||||||
|
{
|
||||||
|
array[I] = Eldbus_Arg_Info {0, 0};
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <std::size_t I, std::size_t N, template <typename...> class params
|
||||||
|
, typename ... Args>
|
||||||
|
int _fill_method_impl(std::array<Eldbus_Arg_Info, N>& array
|
||||||
|
, params<Args...> const& directional_methods
|
||||||
|
, std::false_type)
|
||||||
|
{
|
||||||
|
typedef std::tuple<Args...> params_type;
|
||||||
|
static const char sig[2]
|
||||||
|
= {_detail::signature_traits
|
||||||
|
<
|
||||||
|
typename std::tuple_element<I, params_type>::type
|
||||||
|
>::sig
|
||||||
|
, '\0'
|
||||||
|
};
|
||||||
|
array[I] = {sig
|
||||||
|
, directional_methods._names[I]
|
||||||
|
};
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <std::size_t I, std::size_t N, template <typename...> class params
|
||||||
|
, typename ... Args>
|
||||||
|
int _fill_method(std::array<Eldbus_Arg_Info, N>& array
|
||||||
|
, params<Args...> const& directional_methods)
|
||||||
|
{
|
||||||
|
_fill_method_impl<I>(array, directional_methods
|
||||||
|
, std::integral_constant<bool, N-1 == I>());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... T>
|
||||||
|
void _foo(T...) {}
|
||||||
|
|
||||||
|
template <std::size_t N, template <typename...> class params, typename ... Args
|
||||||
|
, std::size_t... Seq>
|
||||||
|
void _fill_methods_impl(std::array<Eldbus_Arg_Info, N>& array
|
||||||
|
, params<Args...> const& directional_methods
|
||||||
|
, eina::index_sequence<Seq...>
|
||||||
|
)
|
||||||
|
{
|
||||||
|
eldbus::_foo(eldbus::_fill_method<Seq>(array, directional_methods) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <std::size_t N, template <typename...> class params, typename ... Args>
|
||||||
|
void _fill_methods(std::array<Eldbus_Arg_Info, N>& array
|
||||||
|
, params<Args...> const& directional_methods)
|
||||||
|
{
|
||||||
|
eldbus::_fill_methods_impl(array, directional_methods
|
||||||
|
, eina::make_index_sequence<N>());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Tuple, std::size_t I>
|
||||||
|
void _create_methods_specification(Tuple const&
|
||||||
|
, std::array<Eldbus_Method, std::tuple_size<Tuple>::value+1>& methods
|
||||||
|
, std::integral_constant<std::size_t, I>
|
||||||
|
, std::true_type)
|
||||||
|
{
|
||||||
|
methods[I] = Eldbus_Method {0, 0, 0, 0, 0, 0};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <std::size_t, typename T>
|
||||||
|
T get_in(Eldbus_Message const* msg)
|
||||||
|
{
|
||||||
|
typename _detail::signature_traits<T>::raw_type object;
|
||||||
|
|
||||||
|
const char sig[2] = {_detail::signature_traits<T>::sig, 0};
|
||||||
|
if (!eldbus_message_arguments_get(msg, sig, &object))
|
||||||
|
{
|
||||||
|
printf("eldbus_message_arguments_get() error\n");
|
||||||
|
throw std::runtime_error("");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Callable, typename... Ins, typename... Outs
|
||||||
|
, std::size_t... IndexIns, std::size_t... IndexOuts
|
||||||
|
, std::size_t... IndexOuts2>
|
||||||
|
Eldbus_Message* _method_callback_call
|
||||||
|
(Callable const& callable, service::ins<Ins...> const&, service::outs<Outs...> const&
|
||||||
|
, eina::index_sequence<IndexIns...>, eina::index_sequence<IndexOuts...>
|
||||||
|
, eina::index_sequence<IndexOuts2...>
|
||||||
|
, Eldbus_Service_Interface const* iface, Eldbus_Message const* message
|
||||||
|
, typename std::enable_if
|
||||||
|
<!std::is_void
|
||||||
|
<decltype(callable
|
||||||
|
(*static_cast<eldbus::message*>(nullptr)
|
||||||
|
, *static_cast<eldbus::service_interface*>(nullptr)
|
||||||
|
, std::get<IndexIns>(std::tuple<Ins...>())...
|
||||||
|
, &std::get<IndexOuts2>
|
||||||
|
(*static_cast<std::tuple<Outs...>*>(nullptr))...
|
||||||
|
)
|
||||||
|
)>::value, int>::type)
|
||||||
|
{
|
||||||
|
typedef std::tuple<Ins...> tuple_ins;
|
||||||
|
typename _detail::raw_tuple<tuple_ins>::type tuple_ins_raw;
|
||||||
|
_detail::_init_raw_tuple<0u, tuple_ins>
|
||||||
|
(eldbus_message_iter_get(message), tuple_ins_raw
|
||||||
|
, std::integral_constant<bool, (std::tuple_size<tuple_ins>::value == 0u)>());
|
||||||
|
|
||||||
|
std::tuple<Outs...> tuple_outs;
|
||||||
|
|
||||||
|
eldbus::const_message msg( ::eldbus_message_ref(const_cast<Eldbus_Message*>(message)));
|
||||||
|
eldbus::service_interface siface(iface);
|
||||||
|
|
||||||
|
// If you have an error here, then you probably got your ins<...>
|
||||||
|
// and/or outs<...> different from the arguments of your callable
|
||||||
|
//typedef _detail::signature_traits<result_type> traits;
|
||||||
|
std::get<0u>(tuple_outs) =
|
||||||
|
callable(msg, siface, std::get<IndexIns>(tuple_ins_raw)..., &std::get<IndexOuts2>(tuple_outs)...);
|
||||||
|
|
||||||
|
Eldbus_Message *reply = eldbus_message_method_return_new(message);
|
||||||
|
_detail::_append_tuple<0u>(reply, tuple_outs, std::false_type());
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Callable, typename... Ins, typename... Outs
|
||||||
|
, std::size_t... IndexIns, std::size_t... IndexOuts
|
||||||
|
, std::size_t... IndexOuts2>
|
||||||
|
Eldbus_Message* _method_callback_call
|
||||||
|
(Callable const& callable, service::ins<Ins...> const&, service::outs<Outs...> const&
|
||||||
|
, eina::index_sequence<IndexIns...>, eina::index_sequence<IndexOuts...>
|
||||||
|
, eina::index_sequence<IndexOuts2...>
|
||||||
|
, Eldbus_Service_Interface const* iface, Eldbus_Message const* message
|
||||||
|
, long)
|
||||||
|
{
|
||||||
|
typedef std::tuple<Ins...> tuple_ins;
|
||||||
|
typename _detail::raw_tuple<tuple_ins>::type tuple_ins_raw;
|
||||||
|
_detail::_init_raw_tuple<0u, tuple_ins>
|
||||||
|
(eldbus_message_iter_get(message), tuple_ins_raw
|
||||||
|
, std::integral_constant<bool, (std::tuple_size<tuple_ins>::value == 0u)>());
|
||||||
|
|
||||||
|
typedef std::tuple<Outs...> tuple_outs_type;
|
||||||
|
tuple_outs_type tuple_outs;
|
||||||
|
|
||||||
|
eldbus::const_message msg( ::eldbus_message_ref(const_cast<Eldbus_Message*>(message)));
|
||||||
|
eldbus::service_interface siface(iface);
|
||||||
|
|
||||||
|
// If you have an error here, then you probably got your ins<...>
|
||||||
|
// and/or outs<...> different from the arguments of your callable
|
||||||
|
callable(msg, siface, std::get<IndexIns>(tuple_ins_raw)..., &std::get<IndexOuts>(tuple_outs)...);
|
||||||
|
|
||||||
|
Eldbus_Message *reply = eldbus_message_method_return_new(message);
|
||||||
|
_detail::_append_tuple<0u>
|
||||||
|
(reply, tuple_outs
|
||||||
|
, std::integral_constant<bool, std::tuple_size<tuple_outs_type>::value == 0u>());
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Callable, typename Ins, typename Outs>
|
||||||
|
Eldbus_Message* _method_callback(void* data, Eldbus_Service_Interface const* iface, Eldbus_Message const* msg)
|
||||||
|
{
|
||||||
|
std::tuple<Callable, Ins, Outs>*
|
||||||
|
tuple = static_cast<std::tuple<Callable, Ins, Outs>*>(data);
|
||||||
|
|
||||||
|
return _method_callback_call(std::get<0u>(*tuple), std::get<1u>(*tuple), std::get<2u>(*tuple)
|
||||||
|
, eina::make_index_sequence
|
||||||
|
<std::tuple_size<typename Ins::types>::value>()
|
||||||
|
, eina::make_index_sequence
|
||||||
|
<std::tuple_size<typename Outs::types>::value>()
|
||||||
|
, eina::pop_integer_sequence
|
||||||
|
<eina::make_index_sequence<0u>
|
||||||
|
, eina::make_index_sequence
|
||||||
|
<std::tuple_size<typename Outs::types>::value>
|
||||||
|
>()
|
||||||
|
, iface, msg, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Method>
|
||||||
|
void _create_methods_specification_impl(Method const& method, Eldbus_Method& eldbus_method, std::false_type)
|
||||||
|
{
|
||||||
|
std::array<Eldbus_Arg_Info, Method::ins_type::size()+1>*
|
||||||
|
in_params = new std::array<Eldbus_Arg_Info, Method::ins_type::size()+1>;
|
||||||
|
|
||||||
|
eldbus::_fill_methods(*in_params, method.ins);
|
||||||
|
|
||||||
|
std::array<Eldbus_Arg_Info, Method::outs_type::size()+1>*
|
||||||
|
out_params = new std::array<Eldbus_Arg_Info, Method::outs_type::size()+1>;
|
||||||
|
|
||||||
|
eldbus::_fill_methods(*out_params, method.outs);
|
||||||
|
|
||||||
|
eldbus_method = {method.name, &(*in_params)[0], &(*out_params)[0]
|
||||||
|
, reinterpret_cast<Eldbus_Method_Cb>
|
||||||
|
(static_cast<Eldbus_Method_Data_Cb>
|
||||||
|
(&_method_callback<typename Method::function_type
|
||||||
|
, typename Method::ins_type, typename Method::outs_type>))
|
||||||
|
, ELDBUS_METHOD_FLAG_HAS_DATA
|
||||||
|
, new std::tuple<typename Method::function_type
|
||||||
|
, typename Method::ins_type, typename Method::outs_type
|
||||||
|
>(std::move(method.f), method.ins, method.outs)};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Method>
|
||||||
|
void _create_methods_specification_impl(Method const& method, Eldbus_Method& eldbus_method, std::true_type)
|
||||||
|
{
|
||||||
|
std::array<Eldbus_Arg_Info, Method::ins_type::size()+1>*
|
||||||
|
in_params = new std::array<Eldbus_Arg_Info, Method::ins_type::size()+1>;
|
||||||
|
|
||||||
|
eldbus::_fill_methods(*in_params, method.ins);
|
||||||
|
|
||||||
|
std::array<Eldbus_Arg_Info, Method::outs_type::size()+1>*
|
||||||
|
out_params = new std::array<Eldbus_Arg_Info, Method::outs_type::size()+1>;
|
||||||
|
|
||||||
|
eldbus::_fill_methods(*out_params, method.outs);
|
||||||
|
|
||||||
|
eldbus_method = {method.name, &(*in_params)[0], &(*out_params)[0], method.f, 0, 0};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Tuple, std::size_t I>
|
||||||
|
void _create_methods_specification(Tuple const& tuple
|
||||||
|
, std::array<Eldbus_Method, std::tuple_size<Tuple>::value+1>& methods
|
||||||
|
, std::integral_constant<std::size_t, I>
|
||||||
|
, std::false_type)
|
||||||
|
{
|
||||||
|
typedef Eldbus_Message*(*function_type)(Eldbus_Service_Interface const*, Eldbus_Message const*);
|
||||||
|
|
||||||
|
typedef typename std::tuple_element<I, Tuple>::type method_type;
|
||||||
|
|
||||||
|
_create_methods_specification_impl(std::get<I>(tuple), methods[I]
|
||||||
|
, std::is_convertible<typename method_type::function_type
|
||||||
|
, function_type>());
|
||||||
|
|
||||||
|
return _create_methods_specification(tuple, methods
|
||||||
|
, std::integral_constant<std::size_t, I+1>()
|
||||||
|
, std::integral_constant<bool, I+1 == std::tuple_size<Tuple>::value>());
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Tuple>
|
||||||
|
std::array<Eldbus_Method, std::tuple_size<Tuple>::value+1> _create_methods_specification
|
||||||
|
(Tuple const& tuple
|
||||||
|
)
|
||||||
|
{
|
||||||
|
typedef std::tuple_size<Tuple> tuple_size;
|
||||||
|
std::array<Eldbus_Method, tuple_size::value+1> array;
|
||||||
|
|
||||||
|
_create_methods_specification(tuple, array
|
||||||
|
, std::integral_constant<std::size_t, 0u>()
|
||||||
|
, std::integral_constant<bool, 0 == std::tuple_size<Tuple>::value>());
|
||||||
|
return array;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
service_interface service_interface_register(connection& c, const char* path
|
||||||
|
, const char* interface
|
||||||
|
, Args... args
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::array<Eldbus_Method, sizeof...(Args) + 1>* methods
|
||||||
|
= new std::array<Eldbus_Method, sizeof...(Args) + 1>
|
||||||
|
(
|
||||||
|
_create_methods_specification(std::make_tuple(args...))
|
||||||
|
);
|
||||||
|
Eldbus_Service_Interface_Desc description =
|
||||||
|
{
|
||||||
|
interface, &(*methods)[0], 0, 0, 0, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
Eldbus_Service_Interface* iface
|
||||||
|
= ::eldbus_service_interface_register(c.native_handle(), path, &description);
|
||||||
|
return service_interface(iface);
|
||||||
|
}
|
||||||
|
|
||||||
|
} }
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,194 @@
|
||||||
|
#ifndef ELDBUS_SIGNATURE_TRAITS_HH_
|
||||||
|
#define ELDBUS_SIGNATURE_TRAITS_HH_
|
||||||
|
|
||||||
|
#include <eina_fold.hh>
|
||||||
|
#include <eina_integer_sequence.hh>
|
||||||
|
|
||||||
|
namespace efl { namespace eldbus { namespace _detail {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct signature_traits;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct signature_traits<bool>
|
||||||
|
{
|
||||||
|
typedef Eina_Bool raw_type;
|
||||||
|
typedef bool value_type;
|
||||||
|
typedef std::integral_constant<int, 1u> sig_size;
|
||||||
|
static int const sig = 'b';
|
||||||
|
|
||||||
|
static raw_type to_raw(value_type v) { return v ? EINA_TRUE : EINA_FALSE; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct signature_traits<char>
|
||||||
|
{
|
||||||
|
typedef char raw_type;
|
||||||
|
typedef raw_type value_type;
|
||||||
|
typedef std::integral_constant<int, 1u> sig_size;
|
||||||
|
static int const sig = 'y';
|
||||||
|
|
||||||
|
static raw_type to_raw(value_type v) { return v; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct signature_traits<int16_t>
|
||||||
|
{
|
||||||
|
typedef int16_t raw_type;
|
||||||
|
typedef raw_type value_type;
|
||||||
|
typedef std::integral_constant<int, 1u> sig_size;
|
||||||
|
static char const sig = 'n';
|
||||||
|
|
||||||
|
static raw_type to_raw(value_type v) { return v; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct signature_traits<uint16_t>
|
||||||
|
{
|
||||||
|
typedef uint16_t raw_type;
|
||||||
|
typedef raw_type value_type;
|
||||||
|
typedef std::integral_constant<int, 1u> sig_size;
|
||||||
|
static char const sig = 'q';
|
||||||
|
|
||||||
|
static raw_type to_raw(value_type i) { return i; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct signature_traits<int32_t>
|
||||||
|
{
|
||||||
|
typedef int32_t raw_type;
|
||||||
|
typedef raw_type value_type;
|
||||||
|
typedef std::integral_constant<int, 1u> sig_size;
|
||||||
|
static char const sig = 'i';
|
||||||
|
|
||||||
|
static raw_type to_raw(value_type i) { return i; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct signature_traits<uint32_t>
|
||||||
|
{
|
||||||
|
typedef uint32_t raw_type;
|
||||||
|
typedef raw_type value_type;
|
||||||
|
typedef std::integral_constant<int, 1u> sig_size;
|
||||||
|
static char const sig = 'u';
|
||||||
|
|
||||||
|
static raw_type to_raw(value_type i) { return i; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct signature_traits<int64_t>
|
||||||
|
{
|
||||||
|
typedef int64_t raw_type;
|
||||||
|
typedef raw_type value_type;
|
||||||
|
typedef std::integral_constant<int, 1u> sig_size;
|
||||||
|
static char const sig = 'x';
|
||||||
|
|
||||||
|
static raw_type to_raw(value_type i) { return i; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct signature_traits<uint64_t>
|
||||||
|
{
|
||||||
|
typedef uint64_t raw_type;
|
||||||
|
typedef raw_type value_type;
|
||||||
|
typedef std::integral_constant<int, 1u> sig_size;
|
||||||
|
static char const sig = 't';
|
||||||
|
|
||||||
|
static raw_type to_raw(value_type i) { return i; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct signature_traits<double>
|
||||||
|
{
|
||||||
|
typedef double raw_type;
|
||||||
|
typedef raw_type value_type;
|
||||||
|
typedef std::integral_constant<int, 1u> sig_size;
|
||||||
|
static char const sig = 'd';
|
||||||
|
|
||||||
|
static raw_type to_raw(value_type i) { return i; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct signature_traits<std::string>
|
||||||
|
{
|
||||||
|
typedef const char* raw_type;
|
||||||
|
typedef std::string value_type;
|
||||||
|
typedef std::integral_constant<int, 1u> sig_size;
|
||||||
|
static char const sig = 's';
|
||||||
|
|
||||||
|
static raw_type to_raw(std::string const& s) { return s.c_str(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct signature_traits<T const> : signature_traits<T>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
typename signature_traits<T>::raw_type to_raw(T const& object)
|
||||||
|
{
|
||||||
|
return signature_traits<T>::to_raw(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr std::size_t add(std::size_t N)
|
||||||
|
{
|
||||||
|
return N;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr std::size_t add(std::size_t L, std::size_t R)
|
||||||
|
{
|
||||||
|
return L + R;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... T>
|
||||||
|
constexpr std::size_t add(std::size_t L, std::size_t R, T ... O)
|
||||||
|
{
|
||||||
|
return L + R + add(O...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename U>
|
||||||
|
struct signature_size_impl;
|
||||||
|
|
||||||
|
template <typename T, std::size_t... S>
|
||||||
|
struct signature_size_impl<T, eina::index_sequence<S...> >
|
||||||
|
: std::integral_constant
|
||||||
|
<std::size_t
|
||||||
|
, _detail::add
|
||||||
|
(signature_traits<typename std::tuple_element<S, T>::type>::sig_size::value...)>
|
||||||
|
{
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct signature_size : signature_size_impl<T, eina::make_index_sequence<std::tuple_size<T>::value> >
|
||||||
|
{
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename ... T>
|
||||||
|
void call_all(T...) {}
|
||||||
|
|
||||||
|
template <std::size_t I, typename Tuple, std::size_t N
|
||||||
|
, typename = typename std::enable_if<I != N-1>::type>
|
||||||
|
int init_signature(char (&signature)[N])
|
||||||
|
{
|
||||||
|
signature[I] = signature_traits<typename std::tuple_element<I, Tuple>::type>::sig;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <std::size_t I, typename Tuple>
|
||||||
|
int init_signature(char (&signature)[I+1])
|
||||||
|
{
|
||||||
|
signature[I] = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Args, std::size_t... S, std::size_t N>
|
||||||
|
void init_signature_array(char (&signature)[N], eina::index_sequence<S...>)
|
||||||
|
{
|
||||||
|
call_all(_detail::init_signature<S, std::tuple<Args...> >(signature)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
} } }
|
||||||
|
|
||||||
|
#endif
|
|
@ -395,7 +395,7 @@ cb_introspect(const Eldbus_Service_Interface *_iface, const Eldbus_Message *mess
|
||||||
}
|
}
|
||||||
|
|
||||||
static const Eldbus_Method introspect = {
|
static const Eldbus_Method introspect = {
|
||||||
"Introspect", NULL, ELDBUS_ARGS({ "s", "xml" }), cb_introspect, 0
|
"Introspect", NULL, ELDBUS_ARGS({ "s", "xml" }), cb_introspect, 0, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -435,15 +435,15 @@ _default_interfaces_free(void)
|
||||||
static const Eldbus_Method _property_methods[] = {
|
static const Eldbus_Method _property_methods[] = {
|
||||||
{
|
{
|
||||||
"Get", ELDBUS_ARGS({"s", "interface"}, {"s", "property"}),
|
"Get", ELDBUS_ARGS({"s", "interface"}, {"s", "property"}),
|
||||||
ELDBUS_ARGS({"v", "value"}), _cb_property_get, 0
|
ELDBUS_ARGS({"v", "value"}), _cb_property_get, 0, NULL
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Set", ELDBUS_ARGS({"s", "interface"}, {"s", "property"}, {"v", "value"}),
|
"Set", ELDBUS_ARGS({"s", "interface"}, {"s", "property"}, {"v", "value"}),
|
||||||
NULL, _cb_property_set, 0
|
NULL, _cb_property_set, 0, NULL
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"GetAll", ELDBUS_ARGS({"s", "interface"}), ELDBUS_ARGS({"a{sv}", "props"}),
|
"GetAll", ELDBUS_ARGS({"s", "interface"}), ELDBUS_ARGS({"a{sv}", "props"}),
|
||||||
_cb_property_getall, 0
|
_cb_property_getall, 0, NULL
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -570,7 +570,7 @@ _cb_managed_objects(const Eldbus_Service_Interface *iface, const Eldbus_Message
|
||||||
|
|
||||||
static Eldbus_Method get_managed_objects = {
|
static Eldbus_Method get_managed_objects = {
|
||||||
"GetManagedObjects", NULL, ELDBUS_ARGS({"a{oa{sa{sv}}}", "objects"}),
|
"GetManagedObjects", NULL, ELDBUS_ARGS({"a{oa{sa{sv}}}", "objects"}),
|
||||||
_cb_managed_objects, 0
|
_cb_managed_objects, 0, NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
static const Eldbus_Signal _object_manager_signals[] = {
|
static const Eldbus_Signal _object_manager_signals[] = {
|
||||||
|
@ -1282,6 +1282,20 @@ _object_unregister(DBusConnection *conn EINA_UNUSED, void *user_data)
|
||||||
_object_free(obj);
|
_object_free(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Eldbus_Message*
|
||||||
|
_eldbus_method_call(Eldbus_Method const* method, Eldbus_Service_Interface* iface, Eldbus_Message* msg)
|
||||||
|
{
|
||||||
|
if(method->flags & ELDBUS_METHOD_FLAG_HAS_DATA)
|
||||||
|
{
|
||||||
|
Eldbus_Method_Data_Cb cb = (Eldbus_Method_Data_Cb)method->cb;
|
||||||
|
return cb(method->data, iface, msg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return method->cb(iface, msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static DBusHandlerResult
|
static DBusHandlerResult
|
||||||
_object_handler(DBusConnection *dbus_conn EINA_UNUSED, DBusMessage *msg, void *user_data)
|
_object_handler(DBusConnection *dbus_conn EINA_UNUSED, DBusMessage *msg, void *user_data)
|
||||||
{
|
{
|
||||||
|
@ -1331,19 +1345,19 @@ _object_handler(DBusConnection *dbus_conn EINA_UNUSED, DBusMessage *msg, void *u
|
||||||
|
|
||||||
if (!_have_signature(method->in, eldbus_msg))
|
if (!_have_signature(method->in, eldbus_msg))
|
||||||
reply = eldbus_message_error_new(eldbus_msg, DBUS_ERROR_INVALID_SIGNATURE,
|
reply = eldbus_message_error_new(eldbus_msg, DBUS_ERROR_INVALID_SIGNATURE,
|
||||||
"See introspectable to know the expected signature");
|
"See introspectable to know the expected signature");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (iface->obj)
|
if (iface->obj)
|
||||||
reply = method->cb(iface, eldbus_msg);
|
reply = _eldbus_method_call(method, iface, eldbus_msg);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* if iface does have obj it is some of FreeDesktop interfaces:
|
/* if iface does have obj it is some of FreeDesktop interfaces:
|
||||||
Introspectable, Properties or ObjectManager */
|
Introspectable, Properties or ObjectManager */
|
||||||
iface->obj = obj;
|
iface->obj = obj;
|
||||||
reply = method->cb(iface, eldbus_msg);
|
reply = _eldbus_method_call(method, iface, eldbus_msg);
|
||||||
iface->obj = NULL;
|
iface->obj = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
eldbus_message_unref(eldbus_msg);
|
eldbus_message_unref(eldbus_msg);
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
*/
|
*/
|
||||||
#define ELDBUS_METHOD_FLAG_DEPRECATED 1
|
#define ELDBUS_METHOD_FLAG_DEPRECATED 1
|
||||||
#define ELDBUS_METHOD_FLAG_NOREPLY (1 << 1)
|
#define ELDBUS_METHOD_FLAG_NOREPLY (1 << 1)
|
||||||
|
#define ELDBUS_METHOD_FLAG_HAS_DATA (1 << 2) // @since 1.1
|
||||||
|
|
||||||
#define ELDBUS_SIGNAL_FLAG_DEPRECATED 1
|
#define ELDBUS_SIGNAL_FLAG_DEPRECATED 1
|
||||||
|
|
||||||
|
@ -32,6 +33,8 @@ typedef struct _Eldbus_Arg_Info
|
||||||
typedef struct _Eldbus_Service_Interface Eldbus_Service_Interface;
|
typedef struct _Eldbus_Service_Interface Eldbus_Service_Interface;
|
||||||
typedef Eldbus_Message * (*Eldbus_Method_Cb)(const Eldbus_Service_Interface *iface, const Eldbus_Message *message);
|
typedef Eldbus_Message * (*Eldbus_Method_Cb)(const Eldbus_Service_Interface *iface, const Eldbus_Message *message);
|
||||||
|
|
||||||
|
typedef Eldbus_Message * (*Eldbus_Method_Data_Cb)(void* data, const Eldbus_Service_Interface *iface, const Eldbus_Message *message); // @since 1.11
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback function to append property value to message.
|
* Callback function to append property value to message.
|
||||||
*
|
*
|
||||||
|
@ -69,6 +72,7 @@ typedef struct _Eldbus_Method
|
||||||
const Eldbus_Arg_Info *out;
|
const Eldbus_Arg_Info *out;
|
||||||
Eldbus_Method_Cb cb;
|
Eldbus_Method_Cb cb;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
|
void* data; // @since 1.11
|
||||||
} Eldbus_Method;
|
} Eldbus_Method;
|
||||||
|
|
||||||
typedef struct _Eldbus_Signal
|
typedef struct _Eldbus_Signal
|
||||||
|
|
|
@ -0,0 +1,106 @@
|
||||||
|
|
||||||
|
#include <Eina.h>
|
||||||
|
#include "Eldbus.hh"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <check.h>
|
||||||
|
|
||||||
|
void eldbus_test_connection(TCase* tc);
|
||||||
|
void eldbus_test_client(TCase* tc);
|
||||||
|
|
||||||
|
typedef struct _Eldbus_Test_Case Eldbus_Test_Case;
|
||||||
|
struct _Eldbus_Test_Case
|
||||||
|
{
|
||||||
|
const char *test_case;
|
||||||
|
void (*build)(TCase *tc);
|
||||||
|
};
|
||||||
|
|
||||||
|
static const Eldbus_Test_Case etc[] = {
|
||||||
|
{ "connection", eldbus_test_connection },
|
||||||
|
{ "client", eldbus_test_client },
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
_list_tests(void)
|
||||||
|
{
|
||||||
|
const Eldbus_Test_Case *itr = etc;
|
||||||
|
fputs("Available Test Cases:\n", stderr);
|
||||||
|
for (; itr->test_case; itr++)
|
||||||
|
fprintf(stderr, "\t%s\n", itr->test_case);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_use_test(int argc, const char **argv, const char *test_case)
|
||||||
|
{
|
||||||
|
if (argc < 1)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
for (; argc > 0; argc--, argv++)
|
||||||
|
if (strcmp(test_case, *argv) == 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Suite *
|
||||||
|
eldbus_build_suite(int argc, const char **argv)
|
||||||
|
{
|
||||||
|
TCase *tc;
|
||||||
|
Suite *s;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
s = suite_create("Eldbus");
|
||||||
|
|
||||||
|
for (i = 0; etc[i].test_case; ++i)
|
||||||
|
{
|
||||||
|
if (!_use_test(argc, argv, etc[i].test_case))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
tc = tcase_create(etc[i].test_case);
|
||||||
|
tcase_set_timeout(tc, 0);
|
||||||
|
|
||||||
|
etc[i].build(tc);
|
||||||
|
suite_add_tcase(s, tc);
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
Suite *s;
|
||||||
|
SRunner *sr;
|
||||||
|
int i, failed_count;
|
||||||
|
|
||||||
|
for (i = 1; i < argc; i++)
|
||||||
|
if ((strcmp(argv[i], "-h") == 0) ||
|
||||||
|
(strcmp(argv[i], "--help") == 0))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Usage:\n\t%s [test_case1 .. [test_caseN]]\n",
|
||||||
|
argv[0]);
|
||||||
|
_list_tests();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if ((strcmp(argv[i], "-l") == 0) ||
|
||||||
|
(strcmp(argv[i], "--list") == 0))
|
||||||
|
{
|
||||||
|
_list_tests();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
putenv(const_cast<char*>("EFL_RUN_IN_TREE=1"));
|
||||||
|
|
||||||
|
s = eldbus_build_suite(argc - 1, (const char **)argv + 1);
|
||||||
|
sr = srunner_create(s);
|
||||||
|
|
||||||
|
srunner_set_xml(sr, TESTS_BUILD_DIR "/check-results.xml");
|
||||||
|
|
||||||
|
srunner_run_all(sr, CK_ENV);
|
||||||
|
failed_count = srunner_ntests_failed(sr);
|
||||||
|
srunner_free(sr);
|
||||||
|
|
||||||
|
return (failed_count == 0) ? 0 : 255;
|
||||||
|
}
|
|
@ -0,0 +1,458 @@
|
||||||
|
|
||||||
|
#include "Eldbus.hh"
|
||||||
|
#include "Ecore.hh"
|
||||||
|
|
||||||
|
#include <eldbus_freedesktop.hh>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <check.h>
|
||||||
|
|
||||||
|
const char bus[] = "org.Enlightenment";
|
||||||
|
const char path[] = "/org/enlightenment";
|
||||||
|
const char interface[] = "org.enlightenment.Test";
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_name_request(std::error_code const& ec, efl::eldbus::const_message
|
||||||
|
, efl::eldbus::pending, unsigned int reply)
|
||||||
|
{
|
||||||
|
if(!ec)
|
||||||
|
{
|
||||||
|
if(reply != ELDBUS_NAME_REQUEST_REPLY_PRIMARY_OWNER)
|
||||||
|
{
|
||||||
|
printf("error name already in use\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
START_TEST(eldbus_cxx_client)
|
||||||
|
{
|
||||||
|
namespace edb = efl::eldbus;
|
||||||
|
|
||||||
|
efl::ecore::ecore_init ecore_init;
|
||||||
|
edb::eldbus_init init;
|
||||||
|
|
||||||
|
edb::connection c(edb::session);
|
||||||
|
|
||||||
|
namespace es = edb::service;
|
||||||
|
|
||||||
|
bool expected_bool = true;
|
||||||
|
char expected_byte = 0xAA;
|
||||||
|
uint32_t expected_uint32 = 0xFFFFFFFF;
|
||||||
|
int32_t expected_int32 = -1;
|
||||||
|
int16_t expected_int16 = -1;
|
||||||
|
double expected_double = 3.1415926;
|
||||||
|
std::string expected_string = "expected string";
|
||||||
|
|
||||||
|
edb::service_interface iface = edb::service_interface_register
|
||||||
|
(c, path, interface
|
||||||
|
, es::method("SendBool"
|
||||||
|
, [expected_bool] (edb::const_message, edb::service_interface, bool b)
|
||||||
|
{
|
||||||
|
ck_assert(b == expected_bool);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
, es::ins<bool>("bool")
|
||||||
|
, es::outs<bool>("bool")
|
||||||
|
)
|
||||||
|
, es::method("SendByte"
|
||||||
|
, [expected_byte] (edb::const_message, edb::service_interface, char c)
|
||||||
|
{
|
||||||
|
ck_assert(c == expected_byte);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
, es::ins<char>("byte")
|
||||||
|
, es::outs<char>("byte")
|
||||||
|
)
|
||||||
|
, es::method("SendUint32"
|
||||||
|
, [expected_uint32] (edb::const_message, edb::service_interface, uint32_t n)
|
||||||
|
{
|
||||||
|
ck_assert(n == expected_uint32);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
, es::ins<uint32_t>("uint32")
|
||||||
|
, es::outs<uint32_t>("uint32")
|
||||||
|
)
|
||||||
|
, es::method("SendInt32"
|
||||||
|
, [expected_int32] (edb::const_message, edb::service_interface, int32_t n)
|
||||||
|
{
|
||||||
|
ck_assert(n == expected_int32);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
, es::ins<int32_t>("int32")
|
||||||
|
, es::outs<int32_t>("int32")
|
||||||
|
)
|
||||||
|
, es::method("SendInt16"
|
||||||
|
, [expected_int16] (edb::const_message, edb::service_interface, int16_t n)
|
||||||
|
{
|
||||||
|
ck_assert(n == expected_int16);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
, es::ins<int16_t>("int16")
|
||||||
|
, es::outs<int16_t>("int16")
|
||||||
|
)
|
||||||
|
, es::method("SendDouble"
|
||||||
|
, [expected_double] (edb::const_message, edb::service_interface, double n)
|
||||||
|
{
|
||||||
|
ck_assert(n == expected_double);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
, es::ins<double>("double")
|
||||||
|
, es::outs<double>("double")
|
||||||
|
)
|
||||||
|
, es::method("SendString"
|
||||||
|
, [expected_string] (edb::const_message, edb::service_interface, std::string const& n)
|
||||||
|
{
|
||||||
|
std::cout << "SendString " << n.size() << " " << n << std::endl;
|
||||||
|
ck_assert(n == expected_string);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
, es::ins<std::string>("string")
|
||||||
|
, es::outs<std::string>("string")
|
||||||
|
)
|
||||||
|
, es::method("GetVoid"
|
||||||
|
, [expected_bool] (edb::const_message, edb::service_interface, bool b)
|
||||||
|
{
|
||||||
|
ck_assert(b == expected_bool);
|
||||||
|
}
|
||||||
|
, es::ins<bool>("string")
|
||||||
|
)
|
||||||
|
, es::method("SendStringWithBool"
|
||||||
|
, [expected_string, expected_bool] (edb::const_message, edb::service_interface
|
||||||
|
, std::string const& n, bool b)
|
||||||
|
{
|
||||||
|
ck_assert(n == expected_string);
|
||||||
|
ck_assert(b == expected_bool);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
, es::ins<std::string, bool>("string", "bool")
|
||||||
|
, es::outs<std::string>("string")
|
||||||
|
)
|
||||||
|
, es::method("SendStringAndBool"
|
||||||
|
, [expected_string, expected_bool] (edb::const_message, edb::service_interface
|
||||||
|
, std::string const& n, bool b
|
||||||
|
, bool* out)
|
||||||
|
{
|
||||||
|
std::cout << "Running SendStringAndBool" << std::endl;
|
||||||
|
ck_assert(n == expected_string);
|
||||||
|
ck_assert(b == expected_bool);
|
||||||
|
*out = b;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
, es::ins<std::string, bool>("string", "bool")
|
||||||
|
, es::outs<std::string, bool>("string", "bool")
|
||||||
|
)
|
||||||
|
, es::method("SendStringAndBoolWithoutReturn"
|
||||||
|
, [expected_string, expected_bool] (edb::const_message, edb::service_interface
|
||||||
|
, std::string const& s, bool b
|
||||||
|
, std::string* out_s, bool* out_b)
|
||||||
|
{
|
||||||
|
std::cout << "Running SendStringAndBool" << std::endl;
|
||||||
|
ck_assert(s == expected_string);
|
||||||
|
ck_assert(b == expected_bool);
|
||||||
|
*out_s = s;
|
||||||
|
*out_b = b;
|
||||||
|
}
|
||||||
|
, es::ins<std::string, bool>("string", "bool")
|
||||||
|
, es::outs<std::string, bool>("string", "bool")
|
||||||
|
)
|
||||||
|
);
|
||||||
|
using namespace std::placeholders;
|
||||||
|
edb::name_request<std::uint32_t>(c, bus, ELDBUS_NAME_REQUEST_FLAG_DO_NOT_QUEUE
|
||||||
|
, & ::on_name_request);
|
||||||
|
|
||||||
|
std::cout << "registered" << std::endl;
|
||||||
|
|
||||||
|
edb::object o = c.get_object(bus, path);
|
||||||
|
edb::proxy p = o.get_proxy(interface);
|
||||||
|
|
||||||
|
using namespace std::placeholders;
|
||||||
|
p.call<bool>
|
||||||
|
("SendBool"
|
||||||
|
, -1
|
||||||
|
, std::bind
|
||||||
|
([expected_bool] (std::error_code const& ec, edb::const_message const& /*msg*/, bool b)
|
||||||
|
{
|
||||||
|
if(!ec)
|
||||||
|
{
|
||||||
|
std::cout << "bool received " << b << std::endl;
|
||||||
|
ck_assert(b == expected_bool);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "error " << ec.message() << std::endl;
|
||||||
|
const char *errname = "", *errmsg = "";
|
||||||
|
// eldbus_message_error_get(msg, &errname, &errmsg);
|
||||||
|
std::cout << "error " << errname << " " << errmsg << std::endl;
|
||||||
|
std::abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
, _1, _2, _4)
|
||||||
|
, expected_bool
|
||||||
|
);
|
||||||
|
|
||||||
|
p.call<char>
|
||||||
|
("SendByte"
|
||||||
|
, -1
|
||||||
|
, std::bind
|
||||||
|
([expected_byte] (std::error_code const& ec, edb::const_message const& msg, char c)
|
||||||
|
{
|
||||||
|
if(!ec)
|
||||||
|
{
|
||||||
|
std::cout << "char received " << c << std::endl;
|
||||||
|
ck_assert(c == expected_byte);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "error " << ec.message() << std::endl;
|
||||||
|
const char *errname, *errmsg;
|
||||||
|
std::tie(errname, errmsg) = msg.error_get();
|
||||||
|
std::cout << "error " << errname << " " << errmsg << std::endl;
|
||||||
|
std::abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
, _1, _2, _4)
|
||||||
|
, expected_byte
|
||||||
|
);
|
||||||
|
|
||||||
|
p.call<uint32_t>
|
||||||
|
("SendUint32"
|
||||||
|
, -1
|
||||||
|
, std::bind
|
||||||
|
([expected_uint32] (std::error_code const& ec, edb::const_message const& msg, uint32_t i)
|
||||||
|
{
|
||||||
|
if(!ec)
|
||||||
|
{
|
||||||
|
std::cout << "uint32_t received " << i << std::endl;
|
||||||
|
ck_assert(i == expected_uint32);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "error " << ec.message() << std::endl;
|
||||||
|
const char *errname, *errmsg;
|
||||||
|
std::tie(errname, errmsg) = msg.error_get();
|
||||||
|
std::cout << "error " << errname << " " << errmsg << std::endl;
|
||||||
|
std::abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
, _1, _2, _4)
|
||||||
|
, expected_uint32
|
||||||
|
);
|
||||||
|
|
||||||
|
p.call<int32_t>
|
||||||
|
("SendInt32"
|
||||||
|
, -1
|
||||||
|
, std::bind
|
||||||
|
([expected_int32] (std::error_code const& ec, edb::const_message const& msg, int32_t i)
|
||||||
|
{
|
||||||
|
if(!ec)
|
||||||
|
{
|
||||||
|
std::cout << "int32_t received " << i << std::endl;
|
||||||
|
ck_assert(i == expected_int32);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "error " << ec.message() << std::endl;
|
||||||
|
const char *errname, *errmsg;
|
||||||
|
std::tie(errname, errmsg) = msg.error_get();
|
||||||
|
std::cout << "error " << errname << " " << errmsg << std::endl;
|
||||||
|
std::abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
, _1, _2, _4)
|
||||||
|
, expected_int32
|
||||||
|
);
|
||||||
|
|
||||||
|
p.call<int16_t>
|
||||||
|
("SendInt16"
|
||||||
|
, -1
|
||||||
|
, std::bind
|
||||||
|
([expected_int16] (std::error_code const& ec, edb::const_message const& msg, int16_t i)
|
||||||
|
{
|
||||||
|
if(!ec)
|
||||||
|
{
|
||||||
|
std::cout << "int16_t received " << i << std::endl;
|
||||||
|
ck_assert(i == expected_int16);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "error " << ec.message() << std::endl;
|
||||||
|
const char *errname, *errmsg;
|
||||||
|
std::tie(errname, errmsg) = msg.error_get();
|
||||||
|
std::cout << "error " << errname << " " << errmsg << std::endl;
|
||||||
|
std::abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
, _1, _2, _4)
|
||||||
|
, expected_int16
|
||||||
|
);
|
||||||
|
|
||||||
|
p.call<double>
|
||||||
|
("SendDouble"
|
||||||
|
, -1
|
||||||
|
, std::bind
|
||||||
|
([expected_double] (std::error_code const& ec, edb::const_message const& msg, double i)
|
||||||
|
{
|
||||||
|
if(!ec)
|
||||||
|
{
|
||||||
|
std::cout << "double received " << i << std::endl;
|
||||||
|
ck_assert(i == expected_double);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "error " << ec.message() << std::endl;
|
||||||
|
const char *errname, *errmsg;
|
||||||
|
std::tie(errname, errmsg) = msg.error_get();
|
||||||
|
std::cout << "error " << errname << " " << errmsg << std::endl;
|
||||||
|
std::abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
, _1, _2, _4)
|
||||||
|
, expected_double
|
||||||
|
);
|
||||||
|
|
||||||
|
p.call<std::string>
|
||||||
|
("SendString"
|
||||||
|
, -1
|
||||||
|
, std::bind
|
||||||
|
([expected_string] (std::error_code const& ec, edb::const_message const& msg, std::string i)
|
||||||
|
{
|
||||||
|
if(!ec)
|
||||||
|
{
|
||||||
|
std::cout << "string received " << i << std::endl;
|
||||||
|
ck_assert(i == expected_string);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "error " << ec.message() << std::endl;
|
||||||
|
const char *errname, *errmsg;
|
||||||
|
std::tie(errname, errmsg) = msg.error_get();
|
||||||
|
std::cout << "error " << errname << " " << errmsg << std::endl;
|
||||||
|
std::abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
, _1, _2, _4)
|
||||||
|
, expected_string
|
||||||
|
);
|
||||||
|
|
||||||
|
p.call<void>
|
||||||
|
("GetVoid"
|
||||||
|
, -1
|
||||||
|
, std::bind
|
||||||
|
([] (std::error_code const& ec, edb::const_message const& msg)
|
||||||
|
{
|
||||||
|
if(!ec)
|
||||||
|
{
|
||||||
|
std::cout << "GetVoid returned succesfully" << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "error " << ec.message() << std::endl;
|
||||||
|
const char *errname, *errmsg;
|
||||||
|
std::tie(errname, errmsg) = msg.error_get();
|
||||||
|
std::cout << "error " << errname << " " << errmsg << std::endl;
|
||||||
|
std::abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
, _1, _2)
|
||||||
|
, expected_bool
|
||||||
|
);
|
||||||
|
|
||||||
|
p.call<std::string>
|
||||||
|
("SendStringWithBool"
|
||||||
|
, -1
|
||||||
|
, std::bind
|
||||||
|
([expected_string] (std::error_code const& ec, edb::const_message const& msg, std::string i)
|
||||||
|
{
|
||||||
|
if(!ec)
|
||||||
|
{
|
||||||
|
std::cout << "string received " << i << std::endl;
|
||||||
|
ck_assert(i == expected_string);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "error " << ec.message() << std::endl;
|
||||||
|
const char *errname, *errmsg;
|
||||||
|
std::tie(errname, errmsg) = msg.error_get();
|
||||||
|
std::cout << "error " << errname << " " << errmsg << std::endl;
|
||||||
|
std::abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
, _1, _2, _4)
|
||||||
|
, expected_string
|
||||||
|
, expected_bool
|
||||||
|
);
|
||||||
|
|
||||||
|
p.call<std::tuple<std::string, bool> >
|
||||||
|
("SendStringAndBool"
|
||||||
|
, -1
|
||||||
|
, std::bind
|
||||||
|
([expected_string, expected_bool]
|
||||||
|
(std::error_code const& ec, edb::const_message const& msg, std::string i, bool b)
|
||||||
|
{
|
||||||
|
if(!ec)
|
||||||
|
{
|
||||||
|
std::cout << "string received " << i << std::endl;
|
||||||
|
ck_assert(i == expected_string);
|
||||||
|
ck_assert(b == expected_bool);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "error " << ec.message() << std::endl;
|
||||||
|
const char *errname, *errmsg;
|
||||||
|
std::tie(errname, errmsg) = msg.error_get();
|
||||||
|
std::cout << "error " << errname << " " << errmsg << std::endl;
|
||||||
|
std::abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
, _1, _2, _4, _5)
|
||||||
|
, expected_string
|
||||||
|
, expected_bool
|
||||||
|
);
|
||||||
|
|
||||||
|
p.call<std::tuple<std::string, bool> >
|
||||||
|
("SendStringAndBoolWithoutReturn"
|
||||||
|
, -1
|
||||||
|
, std::bind
|
||||||
|
([expected_string, expected_bool]
|
||||||
|
(std::error_code const& ec, edb::const_message const& msg, std::string i, bool b)
|
||||||
|
{
|
||||||
|
if(!ec)
|
||||||
|
{
|
||||||
|
std::cout << "string received " << i << std::endl;
|
||||||
|
ck_assert(i == expected_string);
|
||||||
|
ck_assert(b == expected_bool);
|
||||||
|
|
||||||
|
::ecore_main_loop_quit();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "error " << ec.message() << std::endl;
|
||||||
|
const char *errname, *errmsg;
|
||||||
|
std::tie(errname, errmsg) = msg.error_get();
|
||||||
|
std::cout << "error " << errname << " " << errmsg << std::endl;
|
||||||
|
std::abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
, _1, _2, _4, _5)
|
||||||
|
, expected_string
|
||||||
|
, expected_bool
|
||||||
|
);
|
||||||
|
|
||||||
|
// eldbus_name_owner_changed_callback_add(c.native_handle(), bus, on_name_owner_changed,
|
||||||
|
// c.native_handle(), EINA_TRUE);
|
||||||
|
|
||||||
|
ecore_main_loop_begin();
|
||||||
|
|
||||||
|
std::cout << "out of loop" << std::endl;
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
void
|
||||||
|
eldbus_test_client(TCase* tc)
|
||||||
|
{
|
||||||
|
tcase_add_test(tc, eldbus_cxx_client);
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
|
||||||
|
#include "Eldbus.hh"
|
||||||
|
#include "Ecore.hh"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <check.h>
|
||||||
|
|
||||||
|
START_TEST(eldbus_cxx_session_connection)
|
||||||
|
{
|
||||||
|
efl::eldbus::eldbus_init init;
|
||||||
|
|
||||||
|
efl::eldbus::connection c(efl::eldbus::session);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(eldbus_cxx_system_connection)
|
||||||
|
{
|
||||||
|
efl::eldbus::eldbus_init init;
|
||||||
|
|
||||||
|
efl::eldbus::connection c(efl::eldbus::system);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
void
|
||||||
|
eldbus_test_connection(TCase* tc)
|
||||||
|
{
|
||||||
|
tcase_add_test(tc, eldbus_cxx_session_connection);
|
||||||
|
tcase_add_test(tc, eldbus_cxx_system_connection);
|
||||||
|
}
|
Loading…
Reference in New Issue