blob: 6b0e54499c18e42c3b6126217ff18d2b5aae71d2 [file] [log] [blame]
/*
* Copyright (C) 2014-2019 Amlogic, Inc. All rights reserved.
*
* All information contained herein is Amlogic confidential.
*
* This software is provided to you pursuant to Software License Agreement
* (SLA) with Amlogic Inc ("Amlogic"). This software may be used
* only in accordance with the terms of this agreement.
*
* Redistribution and use in source and binary forms, with or without
* modification is strictly prohibited without prior written permission from
* Amlogic.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "aml-dbus.h"
#include <ctype.h>
#include <string>
#include <vector>
const char *test_service = "amlogic.yocto.test";
const char *test_object = "/amlogic/yocto/test/obj1";
const char *test_interface = "amlogic.yocto.test.intf1";
struct TestStruct {
std::string name;
int ival;
float fval;
bool bval;
};
int test_func1(int a1, const int a2, const int &a3, int &a4) {
a4 = a1 + a2 + a3;
int ret = a1;
fprintf(stderr, "call test_func1(a1=%d,a2=%d, a3=%d, a4=%d, ret=%d\n", a1, a2, a3, a4, ret);
return ret;
}
int test_func2(const std::string &arg1, std::vector<std::string> &out1, TestStruct & out2) {
fprintf(stderr, "call test_func2 %s\n", arg1.c_str());
out1 = {"1", "2", "3", arg1};
out2 = {arg1, arg1.size(), arg1.size() * 1.0, isdigit(arg1[0])};
return 0;
}
std::unordered_map<std::string, TestStruct> test_func3() {
return {{"key1", {"n1", 10, 0.123, true}}, {"key2", {"n2", 20, 0.456, false}}};
}
AMBUS_STRUCT_DEFINE(TestStruct, name, ival, fval, bval);
static int ambus_method_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
struct ambus_method_call<> *pcall = (struct ambus_method_call<> *)userdata;
return pcall->call(m);
}
#define NEW_METHOD_ITEM(P, f, ...) new ambus_method_call<decltype(&f)>(#f, &f),
#define NEW_METHOD_VTABLE(P, f, ...) \
SD_BUS_METHOD_WITH_OFFSET(#f, ambus_method_call<decltype(&f)>::data_pack::signature_input::value, \
ambus_method_call<decltype(&f)>::signature_output::value, ambus_method_handler, \
(size_t)*P##_methods_ptr++, 0),
#define REGISTER_DBUS_METHOD(P, ...) \
static const ambus_method_call<> *P##_methods[] = {MACRO_MAP(NEW_METHOD_ITEM, P, __VA_ARGS__)}, \
**P##_methods_ptr = P##_methods; \
static const sd_bus_vtable P##_vtable[] = {SD_BUS_VTABLE_START(0), \
MACRO_MAP(NEW_METHOD_VTABLE, P, __VA_ARGS__) SD_BUS_VTABLE_END};
#define CALL_DBUS(f, ...) \
ambus_method_proxy<decltype(&f)>::call(ambus, test_service, test_object, test_interface, #f, ##__VA_ARGS__)
REGISTER_DBUS_METHOD(test, test_func1, test_func2, test_func3);
// above macro will generate code similar as the comment line below:
#if 0
static const ambus_method_call<> *test_methods[] = {
new ambus_method_call<decltype(&test_func1)>("test_func1", &test_func1),
new ambus_method_call<decltype(&test_func2)>("test_func2", &test_func2),
};
static const sd_bus_vtable test_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_METHOD_WITH_OFFSET("test_func1", ambus_method_call<decltype(&test_func1)>::data_pack::signature_input::value,
ambus_method_call<decltype(&test_func1)>::signature_output::value, ambus_method_handler,
(size_t)test_methods[0], 0),
SD_BUS_METHOD_WITH_OFFSET("test_func2", ambus_method_call<decltype(&test_func2)>::data_pack::signature_input::value,
ambus_method_call<decltype(&test_func2)>::signature_output::value, ambus_method_handler,
(size_t)test_methods[1], 0),
SD_BUS_VTABLE_END};
#endif
int main(int argc, char *argv[]) {
int r;
if (argc != 2) {
printf("USAGE: %s server/client\n", argv[0]);
return 1;
}
if (strcmp(argv[1], "server") == 0) {
struct aml_dbus *ambus = ambus_new(NULL, 0);
sd_bus_add_object_vtable(ambus_sdbus(ambus), NULL, test_object, test_interface, test_vtable, NULL);
sd_bus_request_name(ambus_sdbus(ambus), test_service, 0LL);
ambus_run(ambus);
} else if (strcmp(argv[1], "client") == 0) {
struct aml_dbus *ambus = ambus_ensure_run(NULL);
int a1 = 1;
int a2 = 2;
const int a3 = 10;
int a4 = 0;
// int r = ambus_method_proxy<decltype(&test_func1)>::call(ambus, test_service, test_object,
// test_interface, "test_func1", a1, a2, a3, a4);
int r = CALL_DBUS(test_func1, a1, a2, a3, a4);
printf("call test_func1 %d %d %d %d ret %d\n", a1, a2, a3, a4, r);
const std::string arg1 = "arg1";
std::vector<std::string> out1;
TestStruct out2;
r = ambus_method_proxy<decltype(&test_func2)>::call(ambus, test_service, test_object, test_interface, "test_func2",
arg1, out1, out2);
printf("call test_func2(%s) ret %d, out2: name:%s ival:%d fval:%f bval:%d out1:", arg1.c_str(), r,
out2.name.c_str(), out2.ival, out2.fval, out2.bval);
for (auto &e : out1)
printf("%s ", e.c_str());
printf("\n");
const std::unordered_map<std::string, TestStruct> &out3 = CALL_DBUS(test_func3);
printf("call test_func3 return ");
for (auto &e : out3)
printf("%s:(%s,%d,%f,%d),", e.first.c_str(), e.second.name.c_str(), e.second.ival, e.second.fval, e.second.bval);
printf("\n");
}
return 0;
}