summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFelipe Magno de Almeida <felipe@expertisesolutions.com.br>2014-07-03 16:28:22 +0900
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>2014-07-03 16:28:23 +0900
commit30df128be5dd3d2cea4c976ed5d5c9b85a15aa77 (patch)
tree8fe7a9c6c61677f46e82199075856a45717b4e98 /src
parentddac21534f9eaa8bc01f8c72c1bff5926de27bd6 (diff)
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
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am2
-rw-r--r--src/Makefile_Eet_Cxx.am2
-rw-r--r--src/Makefile_Eina_Cxx.am3
-rw-r--r--src/Makefile_Eldbus_Cxx.am47
-rw-r--r--src/bindings/eet_cxx/Eet.hh7
-rw-r--r--src/bindings/eina_cxx/eina_fold.hh (renamed from src/bindings/eet_cxx/eet_fold.hh)10
-rw-r--r--src/bindings/eina_cxx/eina_integer_sequence.hh30
-rw-r--r--src/bindings/eina_cxx/eina_tuple.hh (renamed from src/bindings/eet_cxx/eet_tuple.hh)12
-rw-r--r--src/bindings/eina_cxx/eina_tuple_unwrap.hh38
-rw-r--r--src/bindings/eldbus_cxx/Eldbus.hh13
-rw-r--r--src/bindings/eldbus_cxx/eldbus_basic.hh150
-rw-r--r--src/bindings/eldbus_cxx/eldbus_error.hh22
-rw-r--r--src/bindings/eldbus_cxx/eldbus_freedesktop.hh73
-rw-r--r--src/bindings/eldbus_cxx/eldbus_integer_sequence.hh41
-rw-r--r--src/bindings/eldbus_cxx/eldbus_message.hh283
-rw-r--r--src/bindings/eldbus_cxx/eldbus_message_arguments.hh56
-rw-r--r--src/bindings/eldbus_cxx/eldbus_proxy_call.hh117
-rw-r--r--src/bindings/eldbus_cxx/eldbus_raw_tuple.hh30
-rw-r--r--src/bindings/eldbus_cxx/eldbus_service.hh379
-rw-r--r--src/bindings/eldbus_cxx/eldbus_signature_traits.hh194
-rw-r--r--src/lib/eldbus/eldbus_service.c46
-rw-r--r--src/lib/eldbus/eldbus_service.h4
-rw-r--r--src/tests/eldbus_cxx/eldbus_cxx_suite.cc106
-rw-r--r--src/tests/eldbus_cxx/eldbus_cxx_test_eldbus_client.cc458
-rw-r--r--src/tests/eldbus_cxx/eldbus_cxx_test_eldbus_connect.cc32
25 files changed, 2121 insertions, 34 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 62ea229..9ba8132 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -32,6 +32,7 @@ include Makefile_Evil.am
32include Makefile_Escape.am 32include Makefile_Escape.am
33 33
34include Makefile_Eina.am 34include Makefile_Eina.am
35include Makefile_Eina_Cxx.am
35include Makefile_Eo.am 36include Makefile_Eo.am
36include Makefile_Eet.am 37include Makefile_Eet.am
37include Makefile_Eolian.am 38include Makefile_Eolian.am
@@ -76,6 +77,7 @@ include Makefile_Evas_Cxx.am
76endif 77endif
77 78
78include Makefile_Eina_Cxx.am 79include Makefile_Eina_Cxx.am
80include Makefile_Eldbus_Cxx.am
79include Makefile_Eolian_Cxx.am 81include Makefile_Eolian_Cxx.am
80include Makefile_Eet_Cxx.am 82include Makefile_Eet_Cxx.am
81include Makefile_Eo_Cxx.am 83include Makefile_Eo_Cxx.am
diff --git a/src/Makefile_Eet_Cxx.am b/src/Makefile_Eet_Cxx.am
index d2d5592..2e1487d 100644
--- a/src/Makefile_Eet_Cxx.am
+++ b/src/Makefile_Eet_Cxx.am
@@ -8,9 +8,7 @@ dist_installed_eetcxxmainheaders_DATA = bindings/eet_cxx/Eet.hh
8installed_eetcxxheadersdir = $(includedir)/eet-cxx-@VMAJ@/eet-cxx 8installed_eetcxxheadersdir = $(includedir)/eet-cxx-@VMAJ@/eet-cxx
9dist_installed_eetcxxheaders_DATA = \ 9dist_installed_eetcxxheaders_DATA = \
10bindings/eet_cxx/eet_composite.hh \ 10bindings/eet_cxx/eet_composite.hh \
11bindings/eet_cxx/eet_fold.hh \
12bindings/eet_cxx/eet_register.hh \ 11bindings/eet_cxx/eet_register.hh \
13bindings/eet_cxx/eet_tuple.hh \
14bindings/eet_cxx/eet_type.hh 12bindings/eet_cxx/eet_type.hh
15 13
16### Unit tests 14### Unit tests
diff --git a/src/Makefile_Eina_Cxx.am b/src/Makefile_Eina_Cxx.am
index 2fd916c..cfac247 100644
--- a/src/Makefile_Eina_Cxx.am
+++ b/src/Makefile_Eina_Cxx.am
@@ -11,6 +11,7 @@ dist_installed_einacxxheaders_DATA = \
11bindings/eina_cxx/eina_accessor.hh \ 11bindings/eina_cxx/eina_accessor.hh \
12bindings/eina_cxx/eina_clone_allocators.hh \ 12bindings/eina_cxx/eina_clone_allocators.hh \
13bindings/eina_cxx/eina_error.hh \ 13bindings/eina_cxx/eina_error.hh \
14bindings/eina_cxx/eina_fold.hh \
14bindings/eina_cxx/eina_inarray.hh \ 15bindings/eina_cxx/eina_inarray.hh \
15bindings/eina_cxx/eina_inlist.hh \ 16bindings/eina_cxx/eina_inlist.hh \
16bindings/eina_cxx/eina_integer_sequence.hh \ 17bindings/eina_cxx/eina_integer_sequence.hh \
@@ -24,6 +25,8 @@ bindings/eina_cxx/eina_range_types.hh \
24bindings/eina_cxx/eina_ref.hh \ 25bindings/eina_cxx/eina_ref.hh \
25bindings/eina_cxx/eina_stringshare.hh \ 26bindings/eina_cxx/eina_stringshare.hh \
26bindings/eina_cxx/eina_thread.hh \ 27bindings/eina_cxx/eina_thread.hh \
28bindings/eina_cxx/eina_tuple.hh \
29bindings/eina_cxx/eina_tuple_unwrap.hh \
27bindings/eina_cxx/eina_type_traits.hh \ 30bindings/eina_cxx/eina_type_traits.hh \
28bindings/eina_cxx/eina_value.hh 31bindings/eina_cxx/eina_value.hh
29 32
diff --git a/src/Makefile_Eldbus_Cxx.am b/src/Makefile_Eldbus_Cxx.am
new file mode 100644
index 0000000..17b0941
--- /dev/null
+++ b/src/Makefile_Eldbus_Cxx.am
@@ -0,0 +1,47 @@
1
2### Library
3
4installed_eldbuscxxmainheadersdir = $(includedir)/eldbus_cxx-@VMAJ@
5dist_installed_eldbuscxxmainheaders_DATA = \
6bindings/eldbus_cxx/eldbus_basic.hh \
7bindings/eldbus_cxx/eldbus_error.hh \
8bindings/eldbus_cxx/eldbus_freedesktop.hh \
9bindings/eldbus_cxx/Eldbus.hh \
10bindings/eldbus_cxx/eldbus_integer_sequence.hh \
11bindings/eldbus_cxx/eldbus_message_arguments.hh \
12bindings/eldbus_cxx/eldbus_message.hh \
13bindings/eldbus_cxx/eldbus_proxy_call.hh \
14bindings/eldbus_cxx/eldbus_raw_tuple.hh \
15bindings/eldbus_cxx/eldbus_service.hh \
16bindings/eldbus_cxx/eldbus_signature_traits.hh
17
18### Unit tests
19
20if EFL_ENABLE_TESTS
21if HAVE_CXX11
22
23check_PROGRAMS += tests/eldbus_cxx/eldbus_cxx_suite
24TESTS += tests/eldbus_cxx/eldbus_cxx_suite
25
26tests_eldbus_cxx_eldbus_cxx_suite_SOURCES = \
27tests/eldbus_cxx/eldbus_cxx_suite.cc \
28tests/eldbus_cxx/eldbus_cxx_test_eldbus_connect.cc \
29tests/eldbus_cxx/eldbus_cxx_test_eldbus_client.cc
30
31tests_eldbus_cxx_eldbus_cxx_suite_CPPFLAGS = \
32-I$(top_builddir)/src/bindings/eina_cxx \
33-I$(top_srcdir)/src/bindings/eina_cxx \
34-I$(top_builddir)/src/bindings/ecore_cxx \
35-I$(top_srcdir)/src/bindings/ecore_cxx \
36-I$(top_builddir)/src/bindings/eldbus_cxx \
37-I$(top_srcdir)/src/bindings/eldbus_cxx \
38-I$(top_builddir)/src/lib/efl \
39@CHECK_CFLAGS@ \
40 @ELDBUS_CFLAGS@ \
41-DTESTS_BUILD_DIR=\"$(top_builddir)/src/tests/eldbus\"
42
43tests_eldbus_cxx_eldbus_cxx_suite_LDADD = @CHECK_LIBS@ @USE_ELDBUS_LIBS@
44tests_eldbus_cxx_eldbus_cxx_suite_DEPENDENCIES = @USE_ELDBUS_INTERNAL_LIBS@
45
46endif
47endif
diff --git a/src/bindings/eet_cxx/Eet.hh b/src/bindings/eet_cxx/Eet.hh
index a350696..0c329f5 100644
--- a/src/bindings/eet_cxx/Eet.hh
+++ b/src/bindings/eet_cxx/Eet.hh
@@ -4,9 +4,10 @@
4#include <Eet.h> 4#include <Eet.h>
5 5
6#include <eet_type.hh> 6#include <eet_type.hh>
7#include <eet_fold.hh>
8#include <eet_register.hh> 7#include <eet_register.hh>
9 8
9#include <eina_fold.hh>
10
10#include <type_traits> 11#include <type_traits>
11#include <cassert> 12#include <cassert>
12#include <stdexcept> 13#include <stdexcept>
@@ -36,10 +37,10 @@ struct descriptor_type
36 struct push_back 37 struct push_back
37 { 38 {
38 template <typename A, typename B> 39 template <typename A, typename B>
39 struct apply : _mpl::push_back<A, typename _detail::member_type<typename B::member_type>::type> {}; 40 struct apply : eina::_mpl::push_back<A, typename _detail::member_type<typename B::member_type>::type> {};
40 }; 41 };
41 42
42 typedef typename _mpl::fold< std::tuple<Args...>, push_back 43 typedef typename eina::_mpl::fold< std::tuple<Args...>, push_back
43 , descriptor<T> >::type type; 44 , descriptor<T> >::type type;
44}; 45};
45 46
diff --git a/src/bindings/eet_cxx/eet_fold.hh b/src/bindings/eina_cxx/eina_fold.hh
index 7ff19ae..167e0df 100644
--- a/src/bindings/eet_cxx/eet_fold.hh
+++ b/src/bindings/eina_cxx/eina_fold.hh
@@ -1,9 +1,9 @@
1#ifndef EFL_EET_FOLD_HH_ 1#ifndef EFL_EINA_FOLD_HH_
2#define EFL_EET_FOLD_HH_ 2#define EFL_EINA_FOLD_HH_
3 3
4#include <eet_tuple.hh> 4#include <eina_tuple.hh>
5 5
6namespace efl { namespace eet { 6namespace efl { namespace eina {
7 7
8namespace _mpl { 8namespace _mpl {
9 9
@@ -11,7 +11,7 @@ template <typename T, typename F, typename A0, bool B = std::is_same<T, std::tup
11struct fold_impl 11struct fold_impl
12{ 12{
13 typedef typename F::template apply<A0, typename std::tuple_element<0, T>::type>::type result; 13 typedef typename F::template apply<A0, typename std::tuple_element<0, T>::type>::type result;
14 typedef typename fold_impl<typename pop_front<T>::type 14 typedef typename fold_impl<typename _mpl::pop_front<T>::type
15 , F, result 15 , F, result
16 >::type 16 >::type
17 type; 17 type;
diff --git a/src/bindings/eina_cxx/eina_integer_sequence.hh b/src/bindings/eina_cxx/eina_integer_sequence.hh
index b1f98a0..854bb8f 100644
--- a/src/bindings/eina_cxx/eina_integer_sequence.hh
+++ b/src/bindings/eina_cxx/eina_integer_sequence.hh
@@ -70,6 +70,36 @@ using index_sequence = integer_sequence<std::size_t, I...>;
70template <std::size_t I> 70template <std::size_t I>
71using make_index_sequence = make_integer_sequence<std::size_t, I>; 71using make_index_sequence = make_integer_sequence<std::size_t, I>;
72 72
73template <typename T, typename U>
74struct pop_integer_sequence_t;
75
76template <typename T>
77struct pop_integer_sequence_t<integer_sequence<T>, integer_sequence<T> >
78{
79 typedef integer_sequence<T> type;
80};
81
82template <typename T, T S0, T... S>
83struct pop_integer_sequence_t<integer_sequence<T>, integer_sequence<T, S0, S...> >
84{
85 typedef integer_sequence<T, S...> type;
86};
87
88template <typename T, T S0, T... S>
89struct pop_integer_sequence_t<integer_sequence<T, S0, S...>, integer_sequence<T> >
90{
91 typedef integer_sequence<T> type;
92};
93
94template <typename T, T S, T... Ss1, T... Ss2>
95struct pop_integer_sequence_t<integer_sequence<T, S, Ss1...>, integer_sequence<T, S, Ss2...> >
96 : pop_integer_sequence_t<integer_sequence<T, Ss1...>, integer_sequence<T, Ss2...> >
97{
98};
99
100template <typename T, typename U>
101using pop_integer_sequence = typename pop_integer_sequence_t<T, U>::type;
102
73/** 103/**
74 * @} 104 * @}
75 */ 105 */
diff --git a/src/bindings/eet_cxx/eet_tuple.hh b/src/bindings/eina_cxx/eina_tuple.hh
index 2fbb395..f0f22d9 100644
--- a/src/bindings/eet_cxx/eet_tuple.hh
+++ b/src/bindings/eina_cxx/eina_tuple.hh
@@ -1,9 +1,7 @@
1#ifndef EFL_EET_EET_TUPLE_HH_ 1#ifndef EFL_EINA_EINA_TUPLE_HH_
2#define EFL_EET_EET_TUPLE_HH_ 2#define EFL_EINA_EINA_TUPLE_HH_
3 3
4namespace efl { namespace eet { 4namespace efl { namespace eina { namespace _mpl {
5
6namespace _mpl {
7 5
8template <typename A, typename... Args> 6template <typename A, typename... Args>
9struct push_back; 7struct push_back;
@@ -32,8 +30,6 @@ struct pop_front<C<T, Args...> >
32 typedef C<Args...> type; 30 typedef C<Args...> type;
33}; 31};
34 32
35} 33} } }
36
37} }
38 34
39#endif 35#endif
diff --git a/src/bindings/eina_cxx/eina_tuple_unwrap.hh b/src/bindings/eina_cxx/eina_tuple_unwrap.hh
new file mode 100644
index 0000000..379f492
--- /dev/null
+++ b/src/bindings/eina_cxx/eina_tuple_unwrap.hh
@@ -0,0 +1,38 @@
1#ifndef EINA_CXX_EINA_TUPLE_UNWRAP_HH
2#define EINA_CXX_EINA_TUPLE_UNWRAP_HH
3
4#include <eina_integer_sequence.hh>
5
6namespace efl { namespace eina {
7
8template <typename Callable, typename T, std::size_t... S>
9auto call_tuple_unwrap(Callable const& callable, T const& tuple
10 , eina::index_sequence<S...>)
11 -> decltype(callable(std::get<S>(tuple)...))
12{
13 return callable(std::get<S>(tuple)...);
14}
15
16template <typename Callable, typename T, std::size_t... S
17 , typename... Args>
18auto call_tuple_unwrap_prefix(Callable const& callable, T const& tuple
19 , eina::index_sequence<S...>
20 , Args&&... args)
21 -> decltype(callable(std::move(args)..., std::get<S>(tuple)...))
22{
23 return callable(std::move(args)..., std::get<S>(tuple)...);
24}
25
26template <typename Callable, typename T, std::size_t... S
27 , typename... Args>
28auto call_tuple_unwrap_suffix(Callable const& callable, T const& tuple
29 , eina::index_sequence<S...>
30 , Args&&... args)
31 -> decltype(callable(std::get<S>(tuple)..., std::move(args)...))
32{
33 return callable(std::get<S>(tuple)..., std::move(args)...);
34}
35
36} }
37
38#endif
diff --git a/src/bindings/eldbus_cxx/Eldbus.hh b/src/bindings/eldbus_cxx/Eldbus.hh
new file mode 100644
index 0000000..67cbaf6
--- /dev/null
+++ b/src/bindings/eldbus_cxx/Eldbus.hh
@@ -0,0 +1,13 @@
1#ifndef EFL_ELDBUS_HH_
2#define EFL_ELDBUS_HH_
3
4#include <Eina.hh>
5#include <Eldbus.h>
6
7#include <eldbus_basic.hh>
8#include <eldbus_proxy_call.hh>
9#include <eldbus_message.hh>
10#include <eldbus_service.hh>
11#include <eina_integer_sequence.hh>
12
13#endif
diff --git a/src/bindings/eldbus_cxx/eldbus_basic.hh b/src/bindings/eldbus_cxx/eldbus_basic.hh
new file mode 100644
index 0000000..12903da
--- /dev/null
+++ b/src/bindings/eldbus_cxx/eldbus_basic.hh
@@ -0,0 +1,150 @@
1#ifndef ELDBUS_CXX_ELDBUS_BASIC_HH
2#define ELDBUS_CXX_ELDBUS_BASIC_HH
3
4#include <Eina.hh>
5#include <Eldbus.h>
6
7#include <eldbus_proxy_call.hh>
8
9namespace efl { namespace eldbus {
10
11struct unknown_t {};
12struct session_t {};
13struct system_t {};
14struct start_t {};
15struct address_t {};
16
17unknown_t const unknown = unknown_t();
18session_t const session = session_t();
19system_t const system = system_t();
20start_t const start = start_t();
21address_t const address = address_t();
22
23struct eldbus_init
24{
25 eldbus_init()
26 {
27 ::eldbus_init();
28 }
29 ~eldbus_init()
30 {
31 ::eldbus_shutdown();
32 }
33};
34
35struct proxy
36{
37 typedef Eldbus_Proxy* native_handle_type;
38 typedef Eldbus_Proxy const* const_native_handle_type;
39
40 proxy(native_handle_type native)
41 : _proxy(native) {}
42
43 template <typename R, typename Callback, typename... Args>
44 void call(const char* method, double timeout, Callback&& callback, Args... args) const
45 {
46 eldbus::_detail::proxy_call<R>(_proxy, method, timeout, std::move(callback), args...);
47 }
48
49 template <typename Callback, typename... Args>
50 void call(const char* method, double timeout, Callback&& callback, Args... args) const
51 {
52 eldbus::_detail::proxy_call<void>(_proxy, method, timeout, std::move(callback), args...);
53 }
54
55 native_handle_type native_handle() { return _proxy; }
56 const_native_handle_type native_handle() const { return _proxy; }
57private:
58 native_handle_type _proxy;
59};
60
61struct object
62{
63 typedef Eldbus_Object* native_handle_type;
64 typedef Eldbus_Object const* const_native_handle_type;
65 object(native_handle_type o)
66 : _object(o) {}
67
68 proxy get_proxy(const char* interface_) const
69 {
70 Eldbus_Proxy* p = eldbus_proxy_get
71 (const_cast<object*>(this)->native_handle(), interface_);
72 if(!p)
73 {
74 eina::error_code ec = eina::get_error_code();
75 assert(!!ec);
76 throw eina::system_error(ec, "eldbus");
77 }
78 return proxy(p);
79 }
80
81 native_handle_type native_handle() { return _object; }
82 const_native_handle_type const_native_handle() { return _object; }
83private:
84 native_handle_type _object;
85};
86
87struct connection
88{
89 typedef Eldbus_Connection* native_handle_type;
90 typedef Eldbus_Connection const* const_native_handle_type;
91
92 explicit connection(native_handle_type connection)
93 : _connection(connection) {}
94 ~connection()
95 {
96 eldbus_connection_unref(_connection);
97 }
98 connection(unknown_t)
99 : _connection(eldbus_connection_get(ELDBUS_CONNECTION_TYPE_UNKNOWN))
100 {
101 _check_connection();
102 }
103 connection(session_t)
104 : _connection(eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SESSION))
105 {
106 _check_connection();
107 }
108 connection(system_t)
109 : _connection(eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SYSTEM))
110 {
111 _check_connection();
112 }
113 connection(address_t)
114 : _connection(eldbus_connection_get(ELDBUS_CONNECTION_TYPE_ADDRESS))
115 {
116 _check_connection();
117 }
118
119 object get_object(const char* bus, const char* path) const
120 {
121 Eldbus_Object* o = eldbus_object_get
122 (const_cast<connection*>(this)->native_handle(), bus, path);
123 if(!o)
124 {
125 eina::error_code ec = eina::get_error_code();
126 assert(!!ec);
127 throw eina::system_error(ec, "eldbus");
128 }
129 return object(o);
130 }
131
132 native_handle_type native_handle() { return _connection; }
133 const_native_handle_type native_handle() const { return _connection; }
134private:
135 void _check_connection()
136 {
137 if(!_connection)
138 {
139 eina::error_code ec = eina::get_error_code();
140 assert(!!ec);
141 throw eina::system_error(ec, "eldbus");
142 }
143 }
144
145 native_handle_type _connection;
146};
147
148} }
149
150#endif
diff --git a/src/bindings/eldbus_cxx/eldbus_error.hh b/src/bindings/eldbus_cxx/eldbus_error.hh
new file mode 100644
index 0000000..dad1d1b
--- /dev/null
+++ b/src/bindings/eldbus_cxx/eldbus_error.hh
@@ -0,0 +1,22 @@
1#ifndef ELDBUS_ERROR_HH
2#define ELDBUS_ERROR_HH
3
4#include <Eina.hh>
5
6namespace efl { namespace eldbus {
7
8inline Eina_Error call_error_code()
9{
10 static Eina_Error error = eina_error_msg_static_register("Error while making eldbus rpc call");
11 return error;
12}
13
14inline Eina_Error signature_mismatch_error_code()
15{
16 static Eina_Error error = eina_error_msg_static_register("Mismatch function signature and signature specification");
17 return error;
18}
19
20} }
21
22#endif
diff --git a/src/bindings/eldbus_cxx/eldbus_freedesktop.hh b/src/bindings/eldbus_cxx/eldbus_freedesktop.hh
new file mode 100644
index 0000000..9e1c208
--- /dev/null
+++ b/src/bindings/eldbus_cxx/eldbus_freedesktop.hh
@@ -0,0 +1,73 @@
1#ifndef EFL_ELDBUS_CXX_ELDBUS_FREEDESKTOP_HH
2#define EFL_ELDBUS_CXX_ELDBUS_FREEDESKTOP_HH
3
4#include <eldbus_message.hh>
5#include <eldbus_service.hh>
6#include <eldbus_basic.hh>
7#include <eldbus_raw_tuple.hh>
8
9namespace efl { namespace eldbus { namespace _detail {
10
11template <typename Callback, typename... Ins>
12void _callback_wrapper(void* data, Eldbus_Message const* message, Eldbus_Pending* pending)
13{
14 std::cout << "_callback_wrapper" << std::endl;
15 Callback* callback(static_cast<Callback*>(data));
16
17 const char* errname, *errmsg;
18 if (eldbus_message_error_get(message, &errname, &errmsg))
19 {
20 std::cout << "error " << errname << " " << errmsg << std::endl;
21 std::tuple<Ins...> tuple;
22 eldbus::const_message msg( ::eldbus_message_ref(const_cast<Eldbus_Message*>(message)));
23 eina::error_code ec (eldbus::call_error_code(), eina::eina_error_category());
24 eina::call_tuple_unwrap_prefix
25 (*callback, tuple, eina::make_index_sequence<sizeof...(Ins)>()
26 , ec, msg, pending);
27 }
28
29 typename raw_tuple<std::tuple<Ins...> >::type tuple;
30 if(sizeof...(Ins))
31 {
32 if(!_detail::_init_raw_tuple<0u, std::tuple<Ins...> >
33 (eldbus_message_iter_get(message)
34 , tuple, std::integral_constant<bool, (sizeof...(Ins) == 0)>()))
35 {
36 std::cout << "error init raw tuple" << std::endl;
37 std::tuple<Ins...> tuple;
38 eldbus::const_message msg( ::eldbus_message_ref(const_cast<Eldbus_Message*>(message)));
39 eina::error_code ec(eldbus::signature_mismatch_error_code(), eina::eina_error_category());
40 eina::call_tuple_unwrap_prefix
41 (*callback, tuple, eina::make_index_sequence<sizeof...(Ins)>()
42 , ec, msg, pending);
43 }
44 }
45 std::cout << "OK go" << std::endl;
46 eina::error_code ec;
47 eldbus::const_message msg( ::eldbus_message_ref(const_cast<Eldbus_Message*>(message)));
48 eina::call_tuple_unwrap_prefix
49 (*callback, tuple, eina::make_index_sequence<sizeof...(Ins)>()
50 , ec, msg, pending);
51}
52
53template <typename F>
54void _free_cb(void* data, const void*)
55{
56 delete static_cast<F*>(data);
57}
58
59}
60
61template <typename... Ins, typename F>
62pending name_request(connection& c, const char* bus, unsigned int flags, F&& function)
63{
64 F* f = new F(std::move(function));
65 pending r = ::eldbus_name_request(c.native_handle(), bus, flags
66 , &_detail::_callback_wrapper<F, Ins...>, f);
67 eldbus_pending_free_cb_add(r.native_handle(), &_detail::_free_cb<F>, f);
68 return r;
69}
70
71} }
72
73#endif
diff --git a/src/bindings/eldbus_cxx/eldbus_integer_sequence.hh b/src/bindings/eldbus_cxx/eldbus_integer_sequence.hh
new file mode 100644
index 0000000..282936a
--- /dev/null
+++ b/src/bindings/eldbus_cxx/eldbus_integer_sequence.hh
@@ -0,0 +1,41 @@
1#ifndef ELDBUS_CXX_ELDBUS_INTEGER_SEQUENCE_HH
2#define ELDBUS_CXX_ELDBUS_INTEGER_SEQUENCE_HH
3
4namespace efl { namespace eldbus { namespace _detail {
5
6template <typename T, T... Ints>
7struct integer_sequence
8{
9 typedef T value_type;
10 static constexpr std::size_t size() { return sizeof...(Ints); }
11 typedef integer_sequence<T, Ints...> type;
12};
13
14template<class S1, class S2> struct concat;
15
16template<typename T, T... I1, T... I2>
17struct concat<integer_sequence<T, I1...>, integer_sequence<T, I2...> >
18 : integer_sequence<T, I1..., (sizeof...(I1)+I2)...> {};
19
20template<class S1, class S2>
21using Concat = typename concat<S1, S2>::type;
22
23template<typename T, T N> struct gen_seq;
24template<typename T, T N> using make_integer_sequence = typename gen_seq<T, N>::type;
25
26template<typename T, T N>
27struct gen_seq : Concat<make_integer_sequence<T, N/2>
28 , make_integer_sequence<T, N - N/2>>{};
29
30template<> struct gen_seq<std::size_t, 0> : integer_sequence<std::size_t>{};
31template<> struct gen_seq<std::size_t, 1> : integer_sequence<std::size_t, 0>{};
32
33template <std::size_t... I>
34using index_sequence = integer_sequence<std::size_t, I...>;
35
36template <std::size_t I>
37using make_index_sequence = make_integer_sequence<std::size_t, I>;
38
39} } }
40
41#endif
diff --git a/src/bindings/eldbus_cxx/eldbus_message.hh b/src/bindings/eldbus_cxx/eldbus_message.hh
new file mode 100644
index 0000000..9a6eeab
--- /dev/null
+++ b/src/bindings/eldbus_cxx/eldbus_message.hh
@@ -0,0 +1,283 @@
1#ifndef ELDBUS_CXX_ELDBUS_MESSAGE_HH
2#define ELDBUS_CXX_ELDBUS_MESSAGE_HH
3
4#include <Eldbus.h>
5#include <eldbus_signature_traits.hh>
6
7namespace efl { namespace eldbus {
8
9struct message_value
10{
11 message_value() : _iterator(0) {}
12 message_value( ::Eldbus_Message_Iter* iterator) : _iterator(iterator) {}
13
14 template <typename T>
15 T get() const
16 {
17 assert(!!_iterator);
18 std::cout << "trying to read " << _detail::signature_traits<T>::sig
19 << " has " << eldbus_message_iter_signature_get(_iterator) << std::endl;
20 T object;
21 char* c = eldbus_message_iter_signature_get(_iterator);
22 if(c[0] != _detail::signature_traits<T>::sig)
23 throw std::runtime_error("");
24 eldbus_message_iter_arguments_get(_iterator, c, &object);
25 return object;
26 }
27 friend inline bool operator==(message_value const& lhs, message_value const& rhs)
28 {
29 return
30 lhs._iterator == rhs._iterator
31 || (!lhs._iterator && rhs._iterator && std::strlen(eldbus_message_iter_signature_get(rhs._iterator)) == 0)
32 || (!rhs._iterator && lhs._iterator && std::strlen(eldbus_message_iter_signature_get(lhs._iterator)) == 0)
33 ;
34 }
35private:
36 friend struct message_iterator;
37 ::Eldbus_Message_Iter* _iterator;
38};
39
40inline bool operator!=(message_value const& lhs, message_value const& rhs)
41{
42 return !(lhs == rhs);
43}
44
45struct message_iterator
46{
47 typedef message_value value_type;
48 typedef value_type& reference;
49 typedef value_type const& const_reference;
50 typedef value_type* pointer;
51 typedef value_type const* const_pointer;
52 typedef std::ptrdiff_t difference_type;
53 typedef std::size_t size_type;
54 typedef std::input_iterator_tag iterator_category;
55
56 message_iterator()
57 {
58 }
59
60 message_iterator(Eldbus_Message_Iter* iterator)
61 : value(iterator)
62 {}
63
64 reference operator*() const
65 {
66 return const_cast<reference>(value);
67 }
68 pointer operator->() const
69 {
70 return const_cast<pointer>(&value);
71 }
72 message_iterator& operator++()
73 {
74 if(!eldbus_message_iter_next(value._iterator))
75 {
76 value._iterator = 0;
77 }
78 return *this;
79 }
80 message_iterator operator++() const
81 {
82 message_iterator tmp(*this);
83 ++*this;
84 return tmp;
85 }
86 friend inline bool operator==(message_iterator const& lhs, message_iterator const& rhs)
87 {
88 return lhs.value == rhs.value;
89 }
90private:
91 message_value value;
92};
93
94inline bool operator!=(message_iterator const& lhs, message_iterator const& rhs)
95{
96 return !(lhs == rhs);
97}
98
99struct reply_t {};
100struct error_t {};
101struct method_call_t {};
102
103reply_t const reply = {};
104error_t const error = {};
105method_call_t const method_call = {};
106
107struct const_message
108{
109 explicit const_message(Eldbus_Message const* message) : _message(message)
110 {
111 }
112 const_message(const_message const& other, reply_t)
113 : _message( ::eldbus_message_method_return_new(other.native_handle()))
114 {
115 }
116 const_message(const_message const& other, const char* error_name, const char* error_msg, error_t)
117 : _message( ::eldbus_message_error_new(other.native_handle(), error_name, error_msg))
118 {
119 }
120 const_message(const char* destination, const char* path, const char* iface
121 , const char* method, method_call_t)
122 : _message( ::eldbus_message_method_call_new(destination, path, iface, method))
123 {
124 }
125 const_message(const_message const& other)
126 : _message( ::eldbus_message_ref(const_cast<Eldbus_Message*>(other.native_handle())))
127 {
128 }
129 ~const_message()
130 {
131 eldbus_message_unref(const_cast<Eldbus_Message*>(native_handle()));
132 }
133
134 const char* path_get() const
135 {
136 return ::eldbus_message_path_get(_message);
137 }
138 const char* interface_get() const
139 {
140 return ::eldbus_message_interface_get(_message);
141 }
142 const char* member_get() const
143 {
144 return ::eldbus_message_member_get(_message);
145 }
146 const char* destination_get() const
147 {
148 return ::eldbus_message_destination_get(_message);
149 }
150 const char* sender_get() const
151 {
152 return ::eldbus_message_sender_get(_message);
153 }
154 const char* signature_get() const
155 {
156 return ::eldbus_message_signature_get(_message);
157 }
158 bool operator!() const
159 {
160 bool b (*this);
161 return !b;
162 }
163 explicit operator bool() const
164 {
165 const char* name, * text;
166 return !eldbus_message_error_get(_message, &name, &text);
167 }
168 std::pair<const char*, const char*> error_get() const
169 {
170 const char* name, * text;
171 eldbus_message_error_get(_message, &name, &text);
172 return {name, text};
173 }
174
175 typedef message_iterator const_iterator;
176 typedef const_iterator iterator;
177 typedef Eldbus_Message const* native_handle_type;
178 typedef Eldbus_Message const* const_native_handle_type;
179 const_native_handle_type native_handle() const { return _message; }
180 const_native_handle_type const_native_handle() const { return _message; }
181
182 const_iterator begin() const
183 {
184 return const_iterator( ::eldbus_message_iter_get(_message));
185 }
186 const_iterator end() const
187 {
188 return const_iterator();
189 }
190private:
191 Eldbus_Message const* _message;
192};
193
194struct message : const_message
195{
196 typedef const_message base_type;
197
198 explicit message(Eldbus_Message* message) : const_message(message)
199 {
200 }
201 message(const_message const& other, reply_t r)
202 : const_message(other, r)
203 {
204 }
205 message(const_message const& other, const char* error_name, const char* error_msg, error_t e)
206 : const_message(other, error_name, error_msg, e)
207 {
208 }
209 message(const char* destination, const char* path, const char* iface
210 , const char* method, method_call_t m)
211 : const_message(destination, path, iface, method, m)
212 {
213 }
214 message(message const& other)
215 : const_message(static_cast<base_type const&>(other))
216 {
217 }
218 typedef Eldbus_Message* native_handle_type;
219 native_handle_type native_handle() { return const_cast<native_handle_type>(const_message::native_handle()); }
220};
221
222struct const_pending
223{
224 const_pending() : _pending(0) {}
225 const_pending(Eldbus_Pending const* pending) : _pending(pending) {}
226
227 void* data_get(const char* key) const
228 {
229 return ::eldbus_pending_data_get(_pending, key);
230 }
231 const char* destination_get() const
232 {
233 return ::eldbus_pending_destination_get(_pending);
234 }
235 const char* path_get() const
236 {
237 return ::eldbus_pending_path_get(_pending);
238 }
239 const char* interface_get() const
240 {
241 return ::eldbus_pending_interface_get(_pending);
242 }
243 const char* method_get() const
244 {
245 return ::eldbus_pending_method_get(_pending);
246 }
247
248 typedef Eldbus_Pending const* native_handle_type;
249 typedef Eldbus_Pending const* const_native_handle_type;
250 native_handle_type native_handle() const { return _pending; }
251 const_native_handle_type const_native_handle() const { return _pending; }
252private:
253 const_native_handle_type _pending;
254};
255
256struct pending : const_pending
257{
258 pending() : const_pending(0) {}
259 pending(Eldbus_Pending* pending) : const_pending(pending) {}
260
261 void data_set(const char* key, const char* data)
262 {
263 ::eldbus_pending_data_set(native_handle(), key, data);
264 }
265 void* data_del(const char* key)
266 {
267 return ::eldbus_pending_data_del(native_handle(), key);
268 }
269 void cancel()
270 {
271 ::eldbus_pending_cancel(native_handle());
272 }
273
274 typedef Eldbus_Pending* native_handle_type;
275 native_handle_type native_handle()
276 {
277 return const_cast<native_handle_type>(const_pending::native_handle());
278 }
279};
280
281} }
282
283#endif
diff --git a/src/bindings/eldbus_cxx/eldbus_message_arguments.hh b/src/bindings/eldbus_cxx/eldbus_message_arguments.hh
new file mode 100644
index 0000000..6c57b02
--- /dev/null
+++ b/src/bindings/eldbus_cxx/eldbus_message_arguments.hh
@@ -0,0 +1,56 @@
1#ifndef ELDBUS_CXX_ELDBUS_MESSAGE_ARGUMENTS_HH
2#define ELDBUS_CXX_ELDBUS_MESSAGE_ARGUMENTS_HH
3
4#include <Eldbus.h>
5
6#include <tuple>
7#include <iostream>
8
9namespace efl { namespace eldbus { namespace _detail {
10
11template <std::size_t I, typename Seq, typename Tuple>
12bool _init_raw_tuple(Eldbus_Message_Iter*, Tuple const&, std::true_type)
13{
14 return true;
15}
16
17template <std::size_t I, typename Seq, typename Tuple>
18bool _init_raw_tuple(Eldbus_Message_Iter* iterator, Tuple const& tuple, std::false_type)
19{
20 typedef signature_traits<typename std::tuple_element<I, Seq>::type> traits;
21 typedef typename traits::value_type element_type;
22
23 char* c = eldbus_message_iter_signature_get(iterator);
24 if(c[0] != signature_traits<element_type>::sig)
25 {
26 return false;
27 }
28
29 eldbus_message_iter_get_and_next(iterator, *c, &std::get<I>(tuple));
30
31 return _init_raw_tuple<I+1, Seq>
32 (iterator, tuple, std::integral_constant<bool, (I+1 == std::tuple_size<Tuple>::value)>());
33}
34
35template <std::size_t I, typename Tuple>
36bool _append_tuple(Eldbus_Message*, Tuple const&, std::true_type)
37{
38 return true;
39}
40
41template <std::size_t I, typename Tuple>
42bool _append_tuple(Eldbus_Message* message, Tuple const& tuple, std::false_type)
43{
44 typedef signature_traits<typename std::tuple_element<I, Tuple>::type> traits;
45
46 char signature[2] = {traits::sig, 0};
47 if(!eldbus_message_arguments_append(message, signature, traits::to_raw(std::get<I>(tuple))))
48 return false;
49
50 return _append_tuple<I+1>
51 (message, tuple, std::integral_constant<bool, (I+1 == std::tuple_size<Tuple>::value)>());
52}
53
54} } }
55
56#endif
diff --git a/src/bindings/eldbus_cxx/eldbus_proxy_call.hh b/src/bindings/eldbus_cxx/eldbus_proxy_call.hh
new file mode 100644
index 0000000..2780e75
--- /dev/null
+++ b/src/bindings/eldbus_cxx/eldbus_proxy_call.hh
@@ -0,0 +1,117 @@
1#ifndef ELDBUS_PROXY_CALL_HH
2#define ELDBUS_PROXY_CALL_HH
3
4#include <Eina.hh>
5#include <eldbus_error.hh>
6#include <eldbus_signature_traits.hh>
7#include <eldbus_message_arguments.hh>
8#include <eldbus_message.hh>
9#include <eldbus_raw_tuple.hh>
10#include <eina_integer_sequence.hh>
11#include <eina_tuple_unwrap.hh>
12
13#include <tuple>
14
15#include <iostream>
16
17namespace efl { namespace eldbus { namespace _detail {
18
19template <typename T> struct tag {};
20
21template <typename Seq, typename Callback, std::size_t... I>
22void _on_call_impl(void* data, Eldbus_Message const* message, Eldbus_Pending* pending)
23{
24 std::unique_ptr<Callback> callback(static_cast<Callback*>(data));
25
26 const char* errname, *errmsg;
27 if (eldbus_message_error_get(message, &errname, &errmsg))
28 {
29 Seq tuple;
30 ::eldbus_message_ref(const_cast<Eldbus_Message*>(message));
31 eldbus::const_message msg(message);
32 eina::error_code ec (eldbus::call_error_code(), eina::eina_error_category());
33 eina::call_tuple_unwrap_prefix
34 (*callback, tuple, eina::make_index_sequence<std::tuple_size<Seq>::value>()
35 , ec, msg, pending);
36 }
37
38 typename raw_tuple<Seq>::type tuple;
39 if(std::tuple_size<Seq>::value)
40 {
41 if(!_detail::_init_raw_tuple<0u, Seq>
42 (eldbus_message_iter_get(message)
43 , tuple, std::integral_constant<bool, (std::tuple_size<Seq>::value == 0)>()))
44 {
45 Seq tuple;
46 ::eldbus_message_ref(const_cast<Eldbus_Message*>(message));
47 eldbus::const_message msg(message);
48 eina::error_code ec(eldbus::signature_mismatch_error_code(), eina::eina_error_category());
49 eina::call_tuple_unwrap_prefix
50 (*callback, tuple, eina::make_index_sequence<std::tuple_size<Seq>::value>()
51 , ec, msg, pending);
52 }
53 }
54 eina::error_code ec;
55 ::eldbus_message_ref(const_cast<Eldbus_Message*>(message));
56 eldbus::const_message msg(message);
57 eina::call_tuple_unwrap_prefix
58 (*callback, tuple, eina::make_index_sequence<std::tuple_size<Seq>::value>()
59 , ec, msg, pending);
60}
61
62template <typename Seq, typename Callback>
63void _on_call(void* data, Eldbus_Message const* message, Eldbus_Pending* pending)
64{
65 _detail::_on_call_impl<Seq, Callback>(data, message, pending);
66}
67
68template <typename R, typename Callback, typename... Args>
69void proxy_call_impl2(Eldbus_Proxy* proxy, const char* method, double timeout
70 , Callback&& callback, Args const&... args)
71{
72 typedef std::tuple<Args...> tuple_args;
73 char signature[signature_size<tuple_args>::value +1];
74 _detail::init_signature_array<Args...>
75 (signature, eina::make_index_sequence<signature_size<tuple_args>::value +1>());
76
77 Callback* c = new Callback(std::move(callback));
78
79 eldbus_proxy_call(proxy, method, &_on_call<R, Callback>, c, timeout, signature
80 , _detail::to_raw(args)...);
81}
82
83template <typename R, typename Callback, typename... Args>
84void proxy_call_impl(tag<R>, Eldbus_Proxy* proxy, const char* method, double timeout
85 , Callback&& callback, Args const&... args)
86{
87 typedef std::tuple<R> reply_tuple;
88 _detail::proxy_call_impl2<reply_tuple>(proxy, method, timeout, std::move(callback), args...);
89}
90
91template <typename... R, typename Callback, typename... Args>
92void proxy_call_impl(tag<std::tuple<R...> >, Eldbus_Proxy* proxy, const char* method, double timeout
93 , Callback&& callback, Args const&... args)
94{
95 typedef std::tuple<R...> reply_tuple;
96 _detail::proxy_call_impl2<reply_tuple>(proxy, method, timeout, std::move(callback), args...);
97}
98
99template <typename Callback, typename... Args>
100void proxy_call_impl(tag<void>, Eldbus_Proxy* proxy, const char* method, double timeout
101 , Callback&& callback, Args const&... args)
102{
103 typedef std::tuple<> reply_tuple;
104 _detail::proxy_call_impl2<reply_tuple>(proxy, method, timeout, std::move(callback), args...);
105}
106
107template <typename R, typename Callback, typename... Args>
108void proxy_call(Eldbus_Proxy* proxy, const char* method, double timeout
109 , Callback&& callback, Args const&... args)
110{
111 return proxy_call_impl(tag<R>(), proxy, method, timeout, std::move(callback), args...);
112}
113
114} } }
115
116#endif
117
diff --git a/src/bindings/eldbus_cxx/eldbus_raw_tuple.hh b/src/bindings/eldbus_cxx/eldbus_raw_tuple.hh
new file mode 100644
index 0000000..ee17cfb
--- /dev/null
+++ b/src/bindings/eldbus_cxx/eldbus_raw_tuple.hh
@@ -0,0 +1,30 @@
1#ifndef EFL_ELDBUS_CXX_ELDBUS_RAW_TUPLE_HH
2#define EFL_ELDBUS_CXX_ELDBUS_RAW_TUPLE_HH
3
4#include <eldbus_signature_traits.hh>
5
6#include <eina_fold.hh>
7#include <eina_tuple.hh>
8
9namespace efl { namespace eldbus { namespace _detail {
10
11template <typename T>
12struct raw_tuple;
13
14template <typename... T>
15struct raw_tuple<std::tuple<T...> >
16{
17 struct push_back
18 {
19 template <typename L, typename R>
20 struct apply
21 : eina::_mpl::push_back<L, typename signature_traits<R>::raw_type> {};
22 };
23
24 typedef typename eina::_mpl::fold< std::tuple<T...>, push_back
25 , std::tuple<> >::type type;
26};
27
28} } }
29
30#endif
diff --git a/src/bindings/eldbus_cxx/eldbus_service.hh b/src/bindings/eldbus_cxx/eldbus_service.hh
new file mode 100644
index 0000000..aca6d3f
--- /dev/null
+++ b/src/bindings/eldbus_cxx/eldbus_service.hh
@@ -0,0 +1,379 @@
1#ifndef ELDBUS_CXX_ELDBUS_SERVICE_HH
2#define ELDBUS_CXX_ELDBUS_SERVICE_HH
3
4#include <array>
5
6namespace efl { namespace eldbus {
7
8struct service_interface
9{
10 service_interface(Eldbus_Service_Interface const* iface)
11 : _iface(iface)
12 {}
13
14 typedef Eldbus_Service_Interface* native_handle_type;
15 typedef Eldbus_Service_Interface const* const_native_handle_type;
16 const_native_handle_type native_handle() { return _iface; }
17 const_native_handle_type native_handle() const { return _iface; }
18private:
19 const_native_handle_type _iface;
20};
21
22namespace service {
23
24template <typename F, typename Ins, typename Outs>
25struct method_specification
26{
27 const char* name;
28 F f;
29
30 typedef F function_type;
31 typedef Ins ins_type;
32 typedef Outs outs_type;
33
34 ins_type ins;
35 outs_type outs;
36};
37
38namespace _detail {
39
40template <typename T>
41struct const_char_type
42{
43 typedef const char* type;
44};
45
46}
47
48template <typename... Args>
49struct ins
50{
51 ins(typename _detail::const_char_type<Args>::type... names) : _names({names...}) {}
52
53 static constexpr std::size_t size() { return sizeof...(Args); }
54
55 typedef std::tuple<Args...> types;
56 std::array<const char*, sizeof...(Args)> _names;
57};
58
59template <typename... Args>
60struct outs
61{
62 outs(typename _detail::const_char_type<Args>::type... names) : _names({names...}) {}
63
64 static constexpr std::size_t size() { return sizeof...(Args); }
65
66 typedef std::tuple<Args...> types;
67 std::array<const char*, sizeof...(Args)> _names;
68};
69
70void foo(int);
71
72template <typename F, typename Ins, typename Outs>
73method_specification<F, Ins, Outs>
74method(const char* name, F f, Ins ins, Outs outs)
75{
76 return method_specification<F, Ins, Outs>
77 {name, f, ins, outs}
78 ;
79}
80
81template <typename F, typename... Outs>
82method_specification<F, service::ins<>, service::outs<Outs...> >
83method(const char* name, F f, service::outs<Outs...> outs)
84{
85 return method_specification<F, service::ins<>, service::outs<Outs...> >
86 {name, f, service::ins<>(), outs}
87 ;
88}
89
90template <typename F, typename... Ins>
91method_specification<F, service::ins<Ins...>, service::outs<> >
92method(const char* name, F f, service::ins<Ins...> ins)
93{
94 return method_specification<F, service::ins<Ins...>, service::outs<> >
95 {name, f, ins, service::outs<>()}
96 ;
97}
98
99}
100
101template <std::size_t I, std::size_t N, template <typename...> class params
102 , typename ... Args>
103int _fill_method_impl(std::array<Eldbus_Arg_Info, N>& array
104 , params<Args...> const&
105 , std::true_type)
106{
107 array[I] = Eldbus_Arg_Info {0, 0};
108 return 0;
109}
110
111
112template <std::size_t I, std::size_t N, template <typename...> class params
113 , typename ... Args>
114int _fill_method_impl(std::array<Eldbus_Arg_Info, N>& array
115 , params<Args...> const& directional_methods
116 , std::false_type)
117{
118 typedef std::tuple<Args...> params_type;
119 static const char sig[2]
120 = {_detail::signature_traits
121 <
122 typename std::tuple_element<I, params_type>::type
123 >::sig
124 , '\0'
125 };
126 array[I] = {sig
127 , directional_methods._names[I]
128 };
129 return 0;
130}
131
132
133template <std::size_t I, std::size_t N, template <typename...> class params
134 , typename ... Args>
135int _fill_method(std::array<Eldbus_Arg_Info, N>& array
136 , params<Args...> const& directional_methods)
137{
138 _fill_method_impl<I>(array, directional_methods
139 , std::integral_constant<bool, N-1 == I>());
140 return 0;
141}
142
143template <typename... T>
144void _foo(T...) {}
145
146template <std::size_t N, template <typename...> class params, typename ... Args
147 , std::size_t... Seq>
148void _fill_methods_impl(std::array<Eldbus_Arg_Info, N>& array
149 , params<Args...> const& directional_methods
150 , eina::index_sequence<Seq...>
151 )
152{
153 eldbus::_foo(eldbus::_fill_method<Seq>(array, directional_methods) ...);
154}
155
156template <std::size_t N, template <typename...> class params, typename ... Args>
157void _fill_methods(std::array<Eldbus_Arg_Info, N>& array
158 , params<Args...> const& directional_methods)
159{
160 eldbus::_fill_methods_impl(array, directional_methods
161 , eina::make_index_sequence<N>());
162}
163
164template <typename Tuple, std::size_t I>
165void _create_methods_specification(Tuple const&
166 , std::array<Eldbus_Method, std::tuple_size<Tuple>::value+1>& methods
167 , std::integral_constant<std::size_t, I>
168 , std::true_type)
169{
170 methods[I] = Eldbus_Method {0, 0, 0, 0, 0, 0};
171};
172
173template <std::size_t, typename T>
174T get_in(Eldbus_Message const* msg)
175{
176 typename _detail::signature_traits<T>::raw_type object;
177
178 const char sig[2] = {_detail::signature_traits<T>::sig, 0};
179 if (!eldbus_message_arguments_get(msg, sig, &object))
180 {
181 printf("eldbus_message_arguments_get() error\n");
182 throw std::runtime_error("");
183 }
184 else
185 {
186 return object;
187 }
188}
189
190template <typename Callable, typename... Ins, typename... Outs
191 , std::size_t... IndexIns, std::size_t... IndexOuts
192 , std::size_t... IndexOuts2>
193Eldbus_Message* _method_callback_call
194(Callable const& callable, service::ins<Ins...> const&, service::outs<Outs...> const&
195 , eina::index_sequence<IndexIns...>, eina::index_sequence<IndexOuts...>
196 , eina::index_sequence<IndexOuts2...>
197 , Eldbus_Service_Interface const* iface, Eldbus_Message const* message
198 , typename std::enable_if
199 <!std::is_void
200 <decltype(callable
201 (*static_cast<eldbus::message*>(nullptr)
202 , *static_cast<eldbus::service_interface*>(nullptr)
203 , std::get<IndexIns>(std::tuple<Ins...>())...
204 , &std::get<IndexOuts2>
205 (*static_cast<std::tuple<Outs...>*>(nullptr))...
206 )
207 )>::value, int>::type)
208{
209 typedef std::tuple<Ins...> tuple_ins;
210 typename _detail::raw_tuple<tuple_ins>::type tuple_ins_raw;
211 _detail::_init_raw_tuple<0u, tuple_ins>
212 (eldbus_message_iter_get(message), tuple_ins_raw
213 , std::integral_constant<bool, (std::tuple_size<tuple_ins>::value == 0u)>());
214
215 std::tuple<Outs...> tuple_outs;
216
217 eldbus::const_message msg( ::eldbus_message_ref(const_cast<Eldbus_Message*>(message)));
218 eldbus::service_interface siface(iface);
219
220 // If you have an error here, then you probably got your ins<...>
221 // and/or outs<...> different from the arguments of your callable
222 //typedef _detail::signature_traits<result_type> traits;
223 std::get<0u>(tuple_outs) =
224 callable(msg, siface, std::get<IndexIns>(tuple_ins_raw)..., &std::get<IndexOuts2>(tuple_outs)...);
225
226 Eldbus_Message *reply = eldbus_message_method_return_new(message);
227 _detail::_append_tuple<0u>(reply, tuple_outs, std::false_type());
228 return reply;
229}
230
231template <typename Callable, typename... Ins, typename... Outs
232 , std::size_t... IndexIns, std::size_t... IndexOuts
233 , std::size_t... IndexOuts2>
234Eldbus_Message* _method_callback_call
235(Callable const& callable, service::ins<Ins...> const&, service::outs<Outs...> const&
236 , eina::index_sequence<IndexIns...>, eina::index_sequence<IndexOuts...>
237 , eina::index_sequence<IndexOuts2...>
238 , Eldbus_Service_Interface const* iface, Eldbus_Message const* message
239 , long)
240{
241 typedef std::tuple<Ins...> tuple_ins;
242 typename _detail::raw_tuple<tuple_ins>::type tuple_ins_raw;
243 _detail::_init_raw_tuple<0u, tuple_ins>
244 (eldbus_message_iter_get(message), tuple_ins_raw
245 , std::integral_constant<bool, (std::tuple_size<tuple_ins>::value == 0u)>());
246
247 typedef std::tuple<Outs...> tuple_outs_type;
248 tuple_outs_type tuple_outs;
249
250 eldbus::const_message msg( ::eldbus_message_ref(const_cast<Eldbus_Message*>(message)));
251 eldbus::service_interface siface(iface);
252
253 // If you have an error here, then you probably got your ins<...>
254 // and/or outs<...> different from the arguments of your callable
255 callable(msg, siface, std::get<IndexIns>(tuple_ins_raw)..., &std::get<IndexOuts>(tuple_outs)...);
256
257 Eldbus_Message *reply = eldbus_message_method_return_new(message);
258 _detail::_append_tuple<0u>
259 (reply, tuple_outs
260 , std::integral_constant<bool, std::tuple_size<tuple_outs_type>::value == 0u>());
261 return reply;
262}
263
264template <typename Callable, typename Ins, typename Outs>
265Eldbus_Message* _method_callback(void* data, Eldbus_Service_Interface const* iface, Eldbus_Message const* msg)
266{
267 std::tuple<Callable, Ins, Outs>*
268 tuple = static_cast<std::tuple<Callable, Ins, Outs>*>(data);
269
270 return _method_callback_call(std::get<0u>(*tuple), std::get<1u>(*tuple), std::get<2u>(*tuple)
271 , eina::make_index_sequence
272 <std::tuple_size<typename Ins::types>::value>()
273 , eina::make_index_sequence
274 <std::tuple_size<typename Outs::types>::value>()
275 , eina::pop_integer_sequence
276 <eina::make_index_sequence<0u>
277 , eina::make_index_sequence
278 <std::tuple_size<typename Outs::types>::value>
279 >()
280 , iface, msg, 0);
281}
282
283template <typename Method>
284void _create_methods_specification_impl(Method const& method, Eldbus_Method& eldbus_method, std::false_type)
285{
286 std::array<Eldbus_Arg_Info, Method::ins_type::size()+1>*
287 in_params = new std::array<Eldbus_Arg_Info, Method::ins_type::size()+1>;
288
289 eldbus::_fill_methods(*in_params, method.ins);
290
291 std::array<Eldbus_Arg_Info, Method::outs_type::size()+1>*
292 out_params = new std::array<Eldbus_Arg_Info, Method::outs_type::size()+1>;
293
294 eldbus::_fill_methods(*out_params, method.outs);
295
296 eldbus_method = {method.name, &(*in_params)[0], &(*out_params)[0]
297 , reinterpret_cast<Eldbus_Method_Cb>
298 (static_cast<Eldbus_Method_Data_Cb>
299 (&_method_callback<typename Method::function_type
300 , typename Method::ins_type, typename Method::outs_type>))
301 , ELDBUS_METHOD_FLAG_HAS_DATA
302 , new std::tuple<typename Method::function_type
303 , typename Method::ins_type, typename Method::outs_type
304 >(std::move(method.f), method.ins, method.outs)};
305}
306
307template <typename Method>
308void _create_methods_specification_impl(Method const& method, Eldbus_Method& eldbus_method, std::true_type)
309{
310 std::array<Eldbus_Arg_Info, Method::ins_type::size()+1>*
311 in_params = new std::array<Eldbus_Arg_Info, Method::ins_type::size()+1>;
312
313 eldbus::_fill_methods(*in_params, method.ins);
314
315 std::array<Eldbus_Arg_Info, Method::outs_type::size()+1>*
316 out_params = new std::array<Eldbus_Arg_Info, Method::outs_type::size()+1>;
317
318 eldbus::_fill_methods(*out_params, method.outs);
319
320 eldbus_method = {method.name, &(*in_params)[0], &(*out_params)[0], method.f, 0, 0};
321}
322
323template <typename Tuple, std::size_t I>
324void _create_methods_specification(Tuple const& tuple
325 , std::array<Eldbus_Method, std::tuple_size<Tuple>::value+1>& methods
326 , std::integral_constant<std::size_t, I>
327 , std::false_type)
328{
329 typedef Eldbus_Message*(*function_type)(Eldbus_Service_Interface const*, Eldbus_Message const*);
330
331 typedef typename std::tuple_element<I, Tuple>::type method_type;
332
333 _create_methods_specification_impl(std::get<I>(tuple), methods[I]
334 , std::is_convertible<typename method_type::function_type
335 , function_type>());
336
337 return _create_methods_specification(tuple, methods
338 , std::integral_constant<std::size_t, I+1>()
339 , std::integral_constant<bool, I+1 == std::tuple_size<Tuple>::value>());
340};
341
342template <typename Tuple>
343std::array<Eldbus_Method, std::tuple_size<Tuple>::value+1> _create_methods_specification
344 (Tuple const& tuple
345 )
346{
347 typedef std::tuple_size<Tuple> tuple_size;
348 std::array<Eldbus_Method, tuple_size::value+1> array;
349
350 _create_methods_specification(tuple, array
351 , std::integral_constant<std::size_t, 0u>()
352 , std::integral_constant<bool, 0 == std::tuple_size<Tuple>::value>());
353 return array;
354};
355
356template <typename... Args>
357service_interface service_interface_register(connection& c, const char* path
358 , const char* interface
359 , Args... args
360 )
361{
362 std::array<Eldbus_Method, sizeof...(Args) + 1>* methods
363 = new std::array<Eldbus_Method, sizeof...(Args) + 1>
364 (
365 _create_methods_specification(std::make_tuple(args...))
366 );
367 Eldbus_Service_Interface_Desc description =
368 {
369 interface, &(*methods)[0], 0, 0, 0, 0
370 };
371
372 Eldbus_Service_Interface* iface
373 = ::eldbus_service_interface_register(c.native_handle(), path, &description);
374 return service_interface(iface);
375}
376
377} }
378
379#endif
diff --git a/src/bindings/eldbus_cxx/eldbus_signature_traits.hh b/src/bindings/eldbus_cxx/eldbus_signature_traits.hh
new file mode 100644
index 0000000..8f2f324
--- /dev/null
+++ b/src/bindings/eldbus_cxx/eldbus_signature_traits.hh
@@ -0,0 +1,194 @@
1#ifndef ELDBUS_SIGNATURE_TRAITS_HH_
2#define ELDBUS_SIGNATURE_TRAITS_HH_
3
4#include <eina_fold.hh>
5#include <eina_integer_sequence.hh>
6
7namespace efl { namespace eldbus { namespace _detail {
8
9template <typename T>
10struct signature_traits;
11
12template <>
13struct signature_traits<bool>
14{
15 typedef Eina_Bool raw_type;
16 typedef bool value_type;
17 typedef std::integral_constant<int, 1u> sig_size;
18 static int const sig = 'b';
19
20 static raw_type to_raw(value_type v) { return v ? EINA_TRUE : EINA_FALSE; }
21};
22
23template <>
24struct signature_traits<char>
25{
26 typedef char raw_type;
27 typedef raw_type value_type;
28 typedef std::integral_constant<int, 1u> sig_size;
29 static int const sig = 'y';
30
31 static raw_type to_raw(value_type v) { return v; }
32};
33
34template <>
35struct signature_traits<int16_t>
36{
37 typedef int16_t raw_type;
38 typedef raw_type value_type;
39 typedef std::integral_constant<int, 1u> sig_size;
40 static char const sig = 'n';
41
42 static raw_type to_raw(value_type v) { return v; }
43};
44
45template <>
46struct signature_traits<uint16_t>
47{
48 typedef uint16_t raw_type;
49 typedef raw_type value_type;
50 typedef std::integral_constant<int, 1u> sig_size;
51 static char const sig = 'q';
52
53 static raw_type to_raw(value_type i) { return i; }
54};
55
56template <>
57struct signature_traits<int32_t>
58{
59 typedef int32_t raw_type;
60 typedef raw_type value_type;
61 typedef std::integral_constant<int, 1u> sig_size;
62 static char const sig = 'i';
63
64 static raw_type to_raw(value_type i) { return i; }
65};
66
67template <>
68struct signature_traits<uint32_t>
69{
70 typedef uint32_t raw_type;
71 typedef raw_type value_type;
72 typedef std::integral_constant<int, 1u> sig_size;
73 static char const sig = 'u';
74
75 static raw_type to_raw(value_type i) { return i; }
76};
77
78template <>
79struct signature_traits<int64_t>
80{
81 typedef int64_t raw_type;
82 typedef raw_type value_type;
83 typedef std::integral_constant<int, 1u> sig_size;
84 static char const sig = 'x';
85
86 static raw_type to_raw(value_type i) { return i; }
87};
88
89template <>
90struct signature_traits<uint64_t>
91{
92 typedef uint64_t raw_type;
93 typedef raw_type value_type;
94 typedef std::integral_constant<int, 1u> sig_size;
95 static char const sig = 't';
96
97 static raw_type to_raw(value_type i) { return i; }
98};
99
100template <>
101struct signature_traits<double>
102{
103 typedef double raw_type;
104 typedef raw_type value_type;
105 typedef std::integral_constant<int, 1u> sig_size;
106 static char const sig = 'd';
107
108 static raw_type to_raw(value_type i) { return i; }
109};
110
111template <>
112struct signature_traits<std::string>
113{
114 typedef const char* raw_type;
115 typedef std::string value_type;
116 typedef std::integral_constant<int, 1u> sig_size;
117 static char const sig = 's';
118
119 static raw_type to_raw(std::string const& s) { return s.c_str(); }
120};
121
122template <typename T>
123struct signature_traits<T const> : signature_traits<T>
124{
125};
126
127template <typename T>
128typename signature_traits<T>::raw_type to_raw(T const& object)
129{
130 return signature_traits<T>::to_raw(object);
131}
132
133constexpr std::size_t add(std::size_t N)
134{
135 return N;
136}
137
138constexpr std::size_t add(std::size_t L, std::size_t R)
139{
140 return L + R;
141}
142
143template <typename... T>
144constexpr std::size_t add(std::size_t L, std::size_t R, T ... O)
145{
146 return L + R + add(O...);
147}
148
149template <typename T, typename U>
150struct signature_size_impl;
151
152template <typename T, std::size_t... S>
153struct signature_size_impl<T, eina::index_sequence<S...> >
154 : std::integral_constant
155 <std::size_t
156 , _detail::add
157 (signature_traits<typename std::tuple_element<S, T>::type>::sig_size::value...)>
158{
159
160};
161
162template <typename T>
163struct signature_size : signature_size_impl<T, eina::make_index_sequence<std::tuple_size<T>::value> >
164{
165
166};
167
168template <typename ... T>
169void call_all(T...) {}
170
171template <std::size_t I, typename Tuple, std::size_t N
172 , typename = typename std::enable_if<I != N-1>::type>
173int init_signature(char (&signature)[N])
174{
175 signature[I] = signature_traits<typename std::tuple_element<I, Tuple>::type>::sig;
176 return 0;
177}
178
179template <std::size_t I, typename Tuple>
180int init_signature(char (&signature)[I+1])
181{
182 signature[I] = 0;
183 return 0;
184}
185
186template <typename... Args, std::size_t... S, std::size_t N>
187void init_signature_array(char (&signature)[N], eina::index_sequence<S...>)
188{
189 call_all(_detail::init_signature<S, std::tuple<Args...> >(signature)...);
190}
191
192} } }
193
194#endif
diff --git a/src/lib/eldbus/eldbus_service.c b/src/lib/eldbus/eldbus_service.c
index 4b7295c..0b06fa3 100644
--- a/src/lib/eldbus/eldbus_service.c
+++ b/src/lib/eldbus/eldbus_service.c
@@ -395,7 +395,7 @@ cb_introspect(const Eldbus_Service_Interface *_iface, const Eldbus_Message *mess
395} 395}
396 396
397static const Eldbus_Method introspect = { 397static const Eldbus_Method introspect = {
398 "Introspect", NULL, ELDBUS_ARGS({ "s", "xml" }), cb_introspect, 0 398 "Introspect", NULL, ELDBUS_ARGS({ "s", "xml" }), cb_introspect, 0, 0
399}; 399};
400 400
401static void 401static void
@@ -435,15 +435,15 @@ _default_interfaces_free(void)
435static const Eldbus_Method _property_methods[] = { 435static const Eldbus_Method _property_methods[] = {
436 { 436 {
437 "Get", ELDBUS_ARGS({"s", "interface"}, {"s", "property"}), 437 "Get", ELDBUS_ARGS({"s", "interface"}, {"s", "property"}),
438 ELDBUS_ARGS({"v", "value"}), _cb_property_get, 0 438 ELDBUS_ARGS({"v", "value"}), _cb_property_get, 0, NULL
439 }, 439 },
440 { 440 {
441 "Set", ELDBUS_ARGS({"s", "interface"}, {"s", "property"}, {"v", "value"}), 441 "Set", ELDBUS_ARGS({"s", "interface"}, {"s", "property"}, {"v", "value"}),
442 NULL, _cb_property_set, 0 442 NULL, _cb_property_set, 0, NULL
443 }, 443 },
444 { 444 {
445 "GetAll", ELDBUS_ARGS({"s", "interface"}), ELDBUS_ARGS({"a{sv}", "props"}), 445 "GetAll", ELDBUS_ARGS({"s", "interface"}), ELDBUS_ARGS({"a{sv}", "props"}),
446 _cb_property_getall, 0 446 _cb_property_getall, 0, NULL
447 } 447 }
448}; 448};
449 449
@@ -570,7 +570,7 @@ _cb_managed_objects(const Eldbus_Service_Interface *iface, const Eldbus_Message
570 570
571static Eldbus_Method get_managed_objects = { 571static Eldbus_Method get_managed_objects = {
572 "GetManagedObjects", NULL, ELDBUS_ARGS({"a{oa{sa{sv}}}", "objects"}), 572 "GetManagedObjects", NULL, ELDBUS_ARGS({"a{oa{sa{sv}}}", "objects"}),
573 _cb_managed_objects, 0 573 _cb_managed_objects, 0, NULL
574}; 574};
575 575
576static const Eldbus_Signal _object_manager_signals[] = { 576static const Eldbus_Signal _object_manager_signals[] = {
@@ -1282,6 +1282,20 @@ _object_unregister(DBusConnection *conn EINA_UNUSED, void *user_data)
1282 _object_free(obj); 1282 _object_free(obj);
1283} 1283}
1284 1284
1285static Eldbus_Message*
1286_eldbus_method_call(Eldbus_Method const* method, Eldbus_Service_Interface* iface, Eldbus_Message* msg)
1287{
1288 if(method->flags & ELDBUS_METHOD_FLAG_HAS_DATA)
1289 {
1290 Eldbus_Method_Data_Cb cb = (Eldbus_Method_Data_Cb)method->cb;
1291 return cb(method->data, iface, msg);
1292 }
1293 else
1294 {
1295 return method->cb(iface, msg);
1296 }
1297}
1298
1285static DBusHandlerResult 1299static DBusHandlerResult
1286_object_handler(DBusConnection *dbus_conn EINA_UNUSED, DBusMessage *msg, void *user_data) 1300_object_handler(DBusConnection *dbus_conn EINA_UNUSED, DBusMessage *msg, void *user_data)
1287{ 1301{
@@ -1331,19 +1345,19 @@ _object_handler(DBusConnection *dbus_conn EINA_UNUSED, DBusMessage *msg, void *u
1331 1345
1332 if (!_have_signature(method->in, eldbus_msg)) 1346 if (!_have_signature(method->in, eldbus_msg))
1333 reply = eldbus_message_error_new(eldbus_msg, DBUS_ERROR_INVALID_SIGNATURE, 1347 reply = eldbus_message_error_new(eldbus_msg, DBUS_ERROR_INVALID_SIGNATURE,
1334 "See introspectable to know the expected signature"); 1348 "See introspectable to know the expected signature");
1335 else 1349 else
1336 { 1350 {
1337 if (iface->obj) 1351 if (iface->obj)
1338 reply = method->cb(iface, eldbus_msg); 1352 reply = _eldbus_method_call(method, iface, eldbus_msg);
1339 else 1353 else
1340 { 1354 {
1341 /* if iface does have obj it is some of FreeDesktop interfaces: 1355 /* if iface does have obj it is some of FreeDesktop interfaces:
1342 Introspectable, Properties or ObjectManager */ 1356 Introspectable, Properties or ObjectManager */
1343 iface->obj = obj; 1357 iface->obj = obj;
1344 reply = method->cb(iface, eldbus_msg); 1358 reply = _eldbus_method_call(method, iface, eldbus_msg);
1345 iface->obj = NULL; 1359 iface->obj = NULL;
1346 } 1360 }
1347 } 1361 }
1348 1362
1349 eldbus_message_unref(eldbus_msg); 1363 eldbus_message_unref(eldbus_msg);
diff --git a/src/lib/eldbus/eldbus_service.h b/src/lib/eldbus/eldbus_service.h
index e5915dc..fdf272e 100644
--- a/src/lib/eldbus/eldbus_service.h
+++ b/src/lib/eldbus/eldbus_service.h
@@ -9,6 +9,7 @@
9 */ 9 */
10#define ELDBUS_METHOD_FLAG_DEPRECATED 1 10#define ELDBUS_METHOD_FLAG_DEPRECATED 1
11#define ELDBUS_METHOD_FLAG_NOREPLY (1 << 1) 11#define ELDBUS_METHOD_FLAG_NOREPLY (1 << 1)
12#define ELDBUS_METHOD_FLAG_HAS_DATA (1 << 2) // @since 1.1
12 13
13#define ELDBUS_SIGNAL_FLAG_DEPRECATED 1 14#define ELDBUS_SIGNAL_FLAG_DEPRECATED 1
14 15
@@ -32,6 +33,8 @@ typedef struct _Eldbus_Arg_Info
32typedef struct _Eldbus_Service_Interface Eldbus_Service_Interface; 33typedef struct _Eldbus_Service_Interface Eldbus_Service_Interface;
33typedef Eldbus_Message * (*Eldbus_Method_Cb)(const Eldbus_Service_Interface *iface, const Eldbus_Message *message); 34typedef Eldbus_Message * (*Eldbus_Method_Cb)(const Eldbus_Service_Interface *iface, const Eldbus_Message *message);
34 35
36typedef Eldbus_Message * (*Eldbus_Method_Data_Cb)(void* data, const Eldbus_Service_Interface *iface, const Eldbus_Message *message); // @since 1.11
37
35/** 38/**
36 * Callback function to append property value to message. 39 * Callback function to append property value to message.
37 * 40 *
@@ -69,6 +72,7 @@ typedef struct _Eldbus_Method
69 const Eldbus_Arg_Info *out; 72 const Eldbus_Arg_Info *out;
70 Eldbus_Method_Cb cb; 73 Eldbus_Method_Cb cb;
71 unsigned int flags; 74 unsigned int flags;
75 void* data; // @since 1.11
72} Eldbus_Method; 76} Eldbus_Method;
73 77
74typedef struct _Eldbus_Signal 78typedef struct _Eldbus_Signal
diff --git a/src/tests/eldbus_cxx/eldbus_cxx_suite.cc b/src/tests/eldbus_cxx/eldbus_cxx_suite.cc
new file mode 100644
index 0000000..a8be883
--- /dev/null
+++ b/src/tests/eldbus_cxx/eldbus_cxx_suite.cc
@@ -0,0 +1,106 @@
1
2#include <Eina.h>
3#include "Eldbus.hh"
4
5#include <cassert>
6#include <algorithm>
7
8#include <check.h>
9
10void eldbus_test_connection(TCase* tc);
11void eldbus_test_client(TCase* tc);
12
13typedef struct _Eldbus_Test_Case Eldbus_Test_Case;
14struct _Eldbus_Test_Case
15{
16 const char *test_case;
17 void (*build)(TCase *tc);
18};
19
20static const Eldbus_Test_Case etc[] = {
21 { "connection", eldbus_test_connection },
22 { "client", eldbus_test_client },
23 { NULL, NULL }
24};
25
26static void
27_list_tests(void)
28{
29 const Eldbus_Test_Case *itr = etc;
30 fputs("Available Test Cases:\n", stderr);
31 for (; itr->test_case; itr++)
32 fprintf(stderr, "\t%s\n", itr->test_case);
33}
34
35static Eina_Bool
36_use_test(int argc, const char **argv, const char *test_case)
37{
38 if (argc < 1)
39 return 1;
40
41 for (; argc > 0; argc--, argv++)
42 if (strcmp(test_case, *argv) == 0)
43 return 1;
44
45 return 0;
46}
47
48Suite *
49eldbus_build_suite(int argc, const char **argv)
50{
51 TCase *tc;
52 Suite *s;
53 int i;
54
55 s = suite_create("Eldbus");
56
57 for (i = 0; etc[i].test_case; ++i)
58 {
59 if (!_use_test(argc, argv, etc[i].test_case))
60 continue;
61
62 tc = tcase_create(etc[i].test_case);
63 tcase_set_timeout(tc, 0);
64
65 etc[i].build(tc);
66 suite_add_tcase(s, tc);
67 }
68
69 return s;
70}
71
72int main(int argc, char* argv[])
73{
74 Suite *s;
75 SRunner *sr;
76 int i, failed_count;
77
78 for (i = 1; i < argc; i++)
79 if ((strcmp(argv[i], "-h") == 0) ||
80 (strcmp(argv[i], "--help") == 0))
81 {
82 fprintf(stderr, "Usage:\n\t%s [test_case1 .. [test_caseN]]\n",
83 argv[0]);
84 _list_tests();
85 return 0;
86 }
87 else if ((strcmp(argv[i], "-l") == 0) ||
88 (strcmp(argv[i], "--list") == 0))
89 {
90 _list_tests();
91 return 0;
92 }
93
94 putenv(const_cast<char*>("EFL_RUN_IN_TREE=1"));
95
96 s = eldbus_build_suite(argc - 1, (const char **)argv + 1);
97 sr = srunner_create(s);
98
99 srunner_set_xml(sr, TESTS_BUILD_DIR "/check-results.xml");
100
101 srunner_run_all(sr, CK_ENV);
102 failed_count = srunner_ntests_failed(sr);
103 srunner_free(sr);
104
105 return (failed_count == 0) ? 0 : 255;
106}
diff --git a/src/tests/eldbus_cxx/eldbus_cxx_test_eldbus_client.cc b/src/tests/eldbus_cxx/eldbus_cxx_test_eldbus_client.cc
new file mode 100644
index 0000000..5355196
--- /dev/null
+++ b/src/tests/eldbus_cxx/eldbus_cxx_test_eldbus_client.cc
@@ -0,0 +1,458 @@
1
2#include "Eldbus.hh"
3#include "Ecore.hh"
4
5#include <eldbus_freedesktop.hh>
6
7#include <algorithm>
8
9#include <iostream>
10
11#include <check.h>
12
13const char bus[] = "org.Enlightenment";
14const char path[] = "/org/enlightenment";
15const char interface[] = "org.enlightenment.Test";
16
17static void
18on_name_request(std::error_code const& ec, efl::eldbus::const_message
19 , efl::eldbus::pending, unsigned int reply)
20{
21 if(!ec)
22 {
23 if(reply != ELDBUS_NAME_REQUEST_REPLY_PRIMARY_OWNER)
24 {
25 printf("error name already in use\n");
26 return;
27 }
28 }
29}
30
31START_TEST(eldbus_cxx_client)
32{
33 namespace edb = efl::eldbus;
34
35 efl::ecore::ecore_init ecore_init;
36 edb::eldbus_init init;
37
38 edb::connection c(edb::session);
39
40 namespace es = edb::service;
41
42 bool expected_bool = true;
43 char expected_byte = 0xAA;
44 uint32_t expected_uint32 = 0xFFFFFFFF;
45 int32_t expected_int32 = -1;
46 int16_t expected_int16 = -1;
47 double expected_double = 3.1415926;
48 std::string expected_string = "expected string";
49
50 edb::service_interface iface = edb::service_interface_register
51 (c, path, interface
52 , es::method("SendBool"
53 , [expected_bool] (edb::const_message, edb::service_interface, bool b)
54 {
55 ck_assert(b == expected_bool);
56 return b;
57 }
58 , es::ins<bool>("bool")
59 , es::outs<bool>("bool")
60 )
61 , es::method("SendByte"
62 , [expected_byte] (edb::const_message, edb::service_interface, char c)
63 {
64 ck_assert(c == expected_byte);
65 return c;
66 }
67 , es::ins<char>("byte")
68 , es::outs<char>("byte")
69 )
70 , es::method("SendUint32"
71 , [expected_uint32] (edb::const_message, edb::service_interface, uint32_t n)
72 {
73 ck_assert(n == expected_uint32);
74 return n;
75 }
76 , es::ins<uint32_t>("uint32")
77 , es::outs<uint32_t>("uint32")
78 )
79 , es::method("SendInt32"
80 , [expected_int32] (edb::const_message, edb::service_interface, int32_t n)
81 {
82 ck_assert(n == expected_int32);
83 return n;
84 }
85 , es::ins<int32_t>("int32")
86 , es::outs<int32_t>("int32")
87 )
88 , es::method("SendInt16"
89 , [expected_int16] (edb::const_message, edb::service_interface, int16_t n)
90 {
91 ck_assert(n == expected_int16);
92 return n;
93 }
94 , es::ins<int16_t>("int16")
95 , es::outs<int16_t>("int16")
96 )
97 , es::method("SendDouble"
98 , [expected_double] (edb::const_message, edb::service_interface, double n)
99 {
100 ck_assert(n == expected_double);
101 return n;
102 }
103 , es::ins<double>("double")
104 , es::outs<double>("double")
105 )
106 , es::method("SendString"
107 , [expected_string] (edb::const_message, edb::service_interface, std::string const& n)
108 {
109 std::cout << "SendString " << n.size() << " " << n << std::endl;
110 ck_assert(n == expected_string);
111 return n;
112 }
113 , es::ins<std::string>("string")
114 , es::outs<std::string>("string")
115 )
116 , es::method("GetVoid"
117 , [expected_bool] (edb::const_message, edb::service_interface, bool b)
118 {
119 ck_assert(b == expected_bool);
120 }
121 , es::ins<bool>("string")
122 )
123 , es::method("SendStringWithBool"
124 , [expected_string, expected_bool] (edb::const_message, edb::service_interface
125 , std::string const& n, bool b)
126 {
127 ck_assert(n == expected_string);
128 ck_assert(b == expected_bool);
129 return n;
130 }
131 , es::ins<std::string, bool>("string", "bool")
132 , es::outs<std::string>("string")
133 )
134 , es::method("SendStringAndBool"
135 , [expected_string, expected_bool] (edb::const_message, edb::service_interface
136 , std::string const& n, bool b
137 , bool* out)
138 {
139 std::cout << "Running SendStringAndBool" << std::endl;
140 ck_assert(n == expected_string);
141 ck_assert(b == expected_bool);
142 *out = b;
143 return n;
144 }
145 , es::ins<std::string, bool>("string", "bool")
146 , es::outs<std::string, bool>("string", "bool")
147 )
148 , es::method("SendStringAndBoolWithoutReturn"
149 , [expected_string, expected_bool] (edb::const_message, edb::service_interface
150 , std::string const& s, bool b
151 , std::string* out_s, bool* out_b)
152 {
153 std::cout << "Running SendStringAndBool" << std::endl;
154 ck_assert(s == expected_string);
155 ck_assert(b == expected_bool);
156 *out_s = s;
157 *out_b = b;
158 }
159 , es::ins<std::string, bool>("string", "bool")
160 , es::outs<std::string, bool>("string", "bool")
161 )
162 );
163 using namespace std::placeholders;
164 edb::name_request<std::uint32_t>(c, bus, ELDBUS_NAME_REQUEST_FLAG_DO_NOT_QUEUE
165 , & ::on_name_request);
166
167 std::cout << "registered" << std::endl;
168
169 edb::object o = c.get_object(bus, path);
170 edb::proxy p = o.get_proxy(interface);
171
172 using namespace std::placeholders;
173 p.call<bool>
174 ("SendBool"
175 , -1
176 , std::bind
177 ([expected_bool] (std::error_code const& ec, edb::const_message const& /*msg*/, bool b)
178 {
179 if(!ec)
180 {
181 std::cout << "bool received " << b << std::endl;
182 ck_assert(b == expected_bool);
183 }
184 else
185 {
186 std::cout << "error " << ec.message() << std::endl;
187 const char *errname = "", *errmsg = "";
188 // eldbus_message_error_get(msg, &errname, &errmsg);
189 std::cout << "error " << errname << " " << errmsg << std::endl;
190 std::abort();
191 }
192 }
193 , _1, _2, _4)
194 , expected_bool
195 );
196
197 p.call<char>
198 ("SendByte"
199 , -1
200 , std::bind
201 ([expected_byte] (std::error_code const& ec, edb::const_message const& msg, char c)
202 {
203 if(!ec)
204 {
205 std::cout << "char received " << c << std::endl;
206 ck_assert(c == expected_byte);
207 }
208 else
209 {
210 std::cout << "error " << ec.message() << std::endl;
211 const char *errname, *errmsg;
212 std::tie(errname, errmsg) = msg.error_get();
213 std::cout << "error " << errname << " " << errmsg << std::endl;
214 std::abort();
215 }
216 }
217 , _1, _2, _4)
218 , expected_byte
219 );
220
221 p.call<uint32_t>
222 ("SendUint32"
223 , -1
224 , std::bind
225 ([expected_uint32] (std::error_code const& ec, edb::const_message const& msg, uint32_t i)
226 {
227 if(!ec)
228 {
229 std::cout << "uint32_t received " << i << std::endl;
230 ck_assert(i == expected_uint32);
231 }
232 else
233 {
234 std::cout << "error " << ec.message() << std::endl;
235 const char *errname, *errmsg;
236 std::tie(errname, errmsg) = msg.error_get();
237 std::cout << "error " << errname << " " << errmsg << std::endl;
238 std::abort();
239 }
240 }
241 , _1, _2, _4)
242 , expected_uint32
243 );
244
245 p.call<int32_t>
246 ("SendInt32"
247 , -1
248 , std::bind
249 ([expected_int32] (std::error_code const& ec, edb::const_message const& msg, int32_t i)
250 {
251 if(!ec)
252 {
253 std::cout << "int32_t received " << i << std::endl;
254 ck_assert(i == expected_int32);
255 }
256 else
257 {
258 std::cout << "error " << ec.message() << std::endl;
259 const char *errname, *errmsg;
260 std::tie(errname, errmsg) = msg.error_get();
261 std::cout << "error " << errname << " " << errmsg << std::endl;
262 std::abort();
263 }
264 }
265 , _1, _2, _4)
266 , expected_int32
267 );
268
269 p.call<int16_t>
270 ("SendInt16"
271 , -1
272 , std::bind
273 ([expected_int16] (std::error_code const& ec, edb::const_message const& msg, int16_t i)
274 {
275 if(!ec)
276 {
277 std::cout << "int16_t received " << i << std::endl;
278 ck_assert(i == expected_int16);
279 }
280 else
281 {
282 std::cout << "error " << ec.message() << std::endl;
283 const char *errname, *errmsg;
284 std::tie(errname, errmsg) = msg.error_get();
285 std::cout << "error " << errname << " " << errmsg << std::endl;
286 std::abort();
287 }
288 }
289 , _1, _2, _4)
290 , expected_int16
291 );
292
293 p.call<double>
294 ("SendDouble"
295 , -1
296 , std::bind
297 ([expected_double] (std::error_code const& ec, edb::const_message const& msg, double i)
298 {
299 if(!ec)
300 {
301 std::cout << "double received " << i << std::endl;
302 ck_assert(i == expected_double);
303 }
304 else
305 {
306 std::cout << "error " << ec.message() << std::endl;
307 const char *errname, *errmsg;
308 std::tie(errname, errmsg) = msg.error_get();
309 std::cout << "error " << errname << " " << errmsg << std::endl;
310 std::abort();
311 }
312 }
313 , _1, _2, _4)
314 , expected_double
315 );
316
317 p.call<std::string>
318 ("SendString"
319 , -1
320 , std::bind
321 ([expected_string] (std::error_code const& ec, edb::const_message const& msg, std::string i)
322 {
323 if(!ec)
324 {
325 std::cout << "string received " << i << std::endl;
326 ck_assert(i == expected_string);
327 }
328 else
329 {
330 std::cout << "error " << ec.message() << std::endl;
331 const char *errname, *errmsg;
332 std::tie(errname, errmsg) = msg.error_get();
333 std::cout << "error " << errname << " " << errmsg << std::endl;
334 std::abort();
335 }
336 }
337 , _1, _2, _4)
338 , expected_string
339 );
340
341 p.call<void>
342 ("GetVoid"
343 , -1
344 , std::bind
345 ([] (std::error_code const& ec, edb::const_message const& msg)
346 {
347 if(!ec)
348 {
349 std::cout << "GetVoid returned succesfully" << std::endl;
350 }
351 else
352 {
353 std::cout << "error " << ec.message() << std::endl;
354 const char *errname, *errmsg;
355 std::tie(errname, errmsg) = msg.error_get();
356 std::cout << "error " << errname << " " << errmsg << std::endl;
357 std::abort();
358 }
359 }
360 , _1, _2)
361 , expected_bool
362 );
363
364 p.call<std::string>
365 ("SendStringWithBool"
366 , -1
367 , std::bind
368 ([expected_string] (std::error_code const& ec, edb::const_message const& msg, std::string i)
369 {
370 if(!ec)
371 {
372 std::cout << "string received " << i << std::endl;
373 ck_assert(i == expected_string);
374 }
375 else
376 {
377 std::cout << "error " << ec.message() << std::endl;
378 const char *errname, *errmsg;
379 std::tie(errname, errmsg) = msg.error_get();
380 std::cout << "error " << errname << " " << errmsg << std::endl;
381 std::abort();
382 }
383 }
384 , _1, _2, _4)
385 , expected_string
386 , expected_bool
387 );
388
389 p.call<std::tuple<std::string, bool> >
390 ("SendStringAndBool"
391 , -1
392 , std::bind
393 ([expected_string, expected_bool]
394 (std::error_code const& ec, edb::const_message const& msg, std::string i, bool b)
395 {
396 if(!ec)
397 {
398 std::cout << "string received " << i << std::endl;
399 ck_assert(i == expected_string);
400 ck_assert(b == expected_bool);
401 }
402 else
403 {
404 std::cout << "error " << ec.message() << std::endl;
405 const char *errname, *errmsg;
406 std::tie(errname, errmsg) = msg.error_get();
407 std::cout << "error " << errname << " " << errmsg << std::endl;
408 std::abort();
409 }
410 }
411 , _1, _2, _4, _5)
412 , expected_string
413 , expected_bool
414 );
415
416 p.call<std::tuple<std::string, bool> >
417 ("SendStringAndBoolWithoutReturn"
418 , -1
419 , std::bind
420 ([expected_string, expected_bool]
421 (std::error_code const& ec, edb::const_message const& msg, std::string i, bool b)
422 {
423 if(!ec)
424 {
425 std::cout << "string received " << i << std::endl;
426 ck_assert(i == expected_string);
427 ck_assert(b == expected_bool);
428
429 ::ecore_main_loop_quit();
430 }
431 else
432 {
433 std::cout << "error " << ec.message() << std::endl;
434 const char *errname, *errmsg;
435 std::tie(errname, errmsg) = msg.error_get();
436 std::cout << "error " << errname << " " << errmsg << std::endl;
437 std::abort();
438 }
439 }
440 , _1, _2, _4, _5)
441 , expected_string
442 , expected_bool
443 );
444
445 // eldbus_name_owner_changed_callback_add(c.native_handle(), bus, on_name_owner_changed,
446 // c.native_handle(), EINA_TRUE);
447
448 ecore_main_loop_begin();
449
450 std::cout << "out of loop" << std::endl;
451}
452END_TEST
453
454void
455eldbus_test_client(TCase* tc)
456{
457 tcase_add_test(tc, eldbus_cxx_client);
458}
diff --git a/src/tests/eldbus_cxx/eldbus_cxx_test_eldbus_connect.cc b/src/tests/eldbus_cxx/eldbus_cxx_test_eldbus_connect.cc
new file mode 100644
index 0000000..3d7716e
--- /dev/null
+++ b/src/tests/eldbus_cxx/eldbus_cxx_test_eldbus_connect.cc
@@ -0,0 +1,32 @@
1
2#include "Eldbus.hh"
3#include "Ecore.hh"
4
5#include <algorithm>
6
7#include <iostream>
8
9#include <check.h>
10
11START_TEST(eldbus_cxx_session_connection)
12{
13 efl::eldbus::eldbus_init init;
14
15 efl::eldbus::connection c(efl::eldbus::session);
16}
17END_TEST
18
19START_TEST(eldbus_cxx_system_connection)
20{
21 efl::eldbus::eldbus_init init;
22
23 efl::eldbus::connection c(efl::eldbus::system);
24}
25END_TEST
26
27void
28eldbus_test_connection(TCase* tc)
29{
30 tcase_add_test(tc, eldbus_cxx_session_connection);
31 tcase_add_test(tc, eldbus_cxx_system_connection);
32}