mirror of
https://github.com/odriverobotics/ODrive.git
synced 2026-09-20 14:38:18 +08:00
implement function return values on protocol
(this time for real)
This commit is contained in:
@@ -92,6 +92,7 @@ public:
|
||||
void NVIC_SystemReset_helper() { NVIC_SystemReset(); }
|
||||
void enter_dfu_mode_helper() { enter_dfu_mode(); }
|
||||
float get_oscilloscope_val(uint32_t index) { return oscilloscope[index]; }
|
||||
int32_t test_function(int32_t delta) { static int cnt = 0; return cnt += delta; }
|
||||
} static_functions;
|
||||
|
||||
// When adding new functions/variables to the protocol, be careful not to
|
||||
@@ -120,7 +121,8 @@ static inline auto make_obj_tree() {
|
||||
),
|
||||
make_protocol_object("axis0", axes[0]->make_protocol_definitions()),
|
||||
make_protocol_object("axis1", axes[1]->make_protocol_definitions()),
|
||||
make_protocol_function_with_ret("get_oscilloscope_val", static_functions, &StaticFunctions::get_oscilloscope_val, "index"),
|
||||
make_protocol_function("get_oscilloscope_val", static_functions, &StaticFunctions::get_oscilloscope_val, "index"),
|
||||
make_protocol_function("test_function", static_functions, &StaticFunctions::test_function, "delta"),
|
||||
make_protocol_function("save_configuration", static_functions, &StaticFunctions::save_configuration_helper),
|
||||
make_protocol_function("erase_configuration", static_functions, &StaticFunctions::erase_configuration_helper),
|
||||
make_protocol_function("reboot", static_functions, &StaticFunctions::NVIC_SystemReset_helper),
|
||||
|
||||
@@ -775,89 +775,50 @@ struct PropertyListFactory<TProperty, TProperties...> {
|
||||
};
|
||||
|
||||
|
||||
template<typename TObj, typename TRet, typename ... TArgs>
|
||||
class ProtocolFunction : public Endpoint {
|
||||
template<typename ... Types>
|
||||
struct return_type;
|
||||
|
||||
template<>
|
||||
struct return_type<> { typedef void type; };
|
||||
template<typename T>
|
||||
struct return_type<T> { typedef T type; };
|
||||
template<typename T, typename ... Ts>
|
||||
struct return_type<T, Ts...> { typedef std::tuple<T, Ts...> type; };
|
||||
|
||||
|
||||
|
||||
template<typename TObj, typename ... TInputsAndOutputs>
|
||||
class ProtocolFunction;
|
||||
|
||||
template<typename TObj, typename ... TInputs, typename ... TOutputs>
|
||||
//template <typename ... TInputs> typename asd,
|
||||
//template <typename ... TOutputs> typename ssss>
|
||||
class ProtocolFunction<TObj, std::tuple<TInputs...>, std::tuple<TOutputs...>> : Endpoint {
|
||||
public:
|
||||
static constexpr size_t endpoint_count = 1 + MemberList<ProtocolProperty<TArgs>...>::endpoint_count;
|
||||
template<typename ... TNames>
|
||||
ProtocolFunction(const char * name, TObj& obj, TRet(TObj::*func_ptr)(TArgs...), TNames ... names) :
|
||||
name_(name), all_arg_names_{names...}, obj_(obj), func_ptr_(func_ptr),
|
||||
input_properties_(PropertyListFactory<TArgs...>::template make_property_list<0>(all_arg_names_, in_args_))
|
||||
|
||||
// @brief The return type of the function as written by a C++ programmer
|
||||
using TRet = typename return_type<TOutputs...>::type;
|
||||
|
||||
static constexpr size_t endpoint_count = 1 + MemberList<ProtocolProperty<TInputs>...>::endpoint_count + MemberList<ProtocolProperty<TOutputs>...>::endpoint_count;
|
||||
|
||||
ProtocolFunction(const char * name, TObj& obj, TRet(TObj::*func_ptr)(TInputs...),
|
||||
std::array<const char *, sizeof...(TInputs)> input_names,
|
||||
std::array<const char *, sizeof...(TOutputs)> output_names) :
|
||||
name_(name), obj_(obj), func_ptr_(func_ptr),
|
||||
input_names_{input_names}, output_names_{output_names},
|
||||
input_properties_(PropertyListFactory<TInputs...>::template make_property_list<0>(input_names_, in_args_)),
|
||||
output_properties_(PropertyListFactory<TOutputs...>::template make_property_list<0>(output_names_, out_args_))
|
||||
{
|
||||
LOG_PROTO("my tuple is at %x and of size %u\r\n", (uintptr_t)&in_args_, sizeof(in_args_));
|
||||
}
|
||||
|
||||
ProtocolFunction(const ProtocolFunction& other) :
|
||||
name_(other.name_), all_arg_names_(other.all_arg_names_), obj_(other.obj_), func_ptr_(other.func_ptr_),
|
||||
input_properties_(PropertyListFactory<TArgs...>::template make_property_list<0>(
|
||||
all_arg_names_, in_args_))
|
||||
{
|
||||
LOG_PROTO("COPIED! my tuple is at %x and of size %u\r\n", (uintptr_t)&in_args_, sizeof(in_args_));
|
||||
}
|
||||
|
||||
void write_json(size_t id, StreamSink* output) {
|
||||
// write name
|
||||
write_string("{\"name\":\"", output);
|
||||
write_string(name_, output);
|
||||
|
||||
// write endpoint ID
|
||||
write_string("\",\"id\":", output);
|
||||
char id_buf[10];
|
||||
snprintf(id_buf, sizeof(id_buf), "%u", id); // TODO: get rid of printf
|
||||
write_string(id_buf, output);
|
||||
|
||||
// write arguments
|
||||
write_string(",\"type\":\"function\",\"arguments\":[", output);
|
||||
input_properties_.write_json(id + 1, output),
|
||||
write_string("]}", output);
|
||||
}
|
||||
|
||||
Endpoint* get_by_name(const char * name, size_t length) {
|
||||
return nullptr; // can't address functions by name
|
||||
}
|
||||
|
||||
void register_endpoints(Endpoint** list, size_t id, size_t length) {
|
||||
if (id < length)
|
||||
list[id] = this;
|
||||
input_properties_.register_endpoints(list, id + 1, length);
|
||||
}
|
||||
|
||||
void handle(const uint8_t* input, size_t input_length, StreamSink* output) {
|
||||
(void) input;
|
||||
(void) input_length;
|
||||
(void) output;
|
||||
LOG_PROTO("tuple still at %x and of size %u\r\n", (uintptr_t)&in_args_, sizeof(in_args_));
|
||||
LOG_PROTO("invoke function using %d and %.3f\r\n", std::get<0>(in_args_), std::get<1>(in_args_));
|
||||
invoke_function_with_tuple(obj_, func_ptr_, in_args_);
|
||||
}
|
||||
|
||||
const char * name_;
|
||||
std::array<const char *, sizeof...(TArgs)> all_arg_names_; // TODO: remove
|
||||
TObj& obj_;
|
||||
TRet(TObj::*func_ptr_)(TArgs...);
|
||||
std::tuple<TArgs...> in_args_;
|
||||
MemberList<ProtocolProperty<TArgs>...> input_properties_;
|
||||
};
|
||||
|
||||
template<typename TObj, typename TRet, typename ... TArgs>
|
||||
class ProtocolFunctionWithRet : Endpoint {
|
||||
public:
|
||||
static constexpr size_t endpoint_count = 1 + MemberList<ProtocolProperty<TRet>>::endpoint_count + MemberList<ProtocolProperty<TArgs>...>::endpoint_count;
|
||||
template<typename ... TNames>
|
||||
ProtocolFunctionWithRet(const char * name, TObj& obj, TRet(TObj::*func_ptr)(TArgs...), TNames ... names) :
|
||||
name_(name), out_arg_names_{"out"}, all_arg_names_{names...}, obj_(obj), func_ptr_(func_ptr),
|
||||
output_properties_(PropertyListFactory<TRet>::template make_property_list<0>(out_arg_names_, out_args_)),
|
||||
input_properties_(PropertyListFactory<TArgs...>::template make_property_list<0>(all_arg_names_, in_args_))
|
||||
{
|
||||
LOG_PROTO("my tuple is at %x and of size %u\r\n", (uintptr_t)&in_args_, sizeof(in_args_));
|
||||
}
|
||||
|
||||
ProtocolFunctionWithRet(const ProtocolFunctionWithRet& other) :
|
||||
name_(other.name_), all_arg_names_(other.all_arg_names_), obj_(other.obj_), func_ptr_(other.func_ptr_),
|
||||
output_properties_(PropertyListFactory<TRet>::template make_property_list<0>(
|
||||
out_arg_names_, out_args_)),
|
||||
input_properties_(PropertyListFactory<TArgs...>::template make_property_list<0>(
|
||||
all_arg_names_, in_args_))
|
||||
name_(other.name_), obj_(other.obj_), func_ptr_(other.func_ptr_),
|
||||
input_names_(other.input_names_), output_names_(other.output_names_),
|
||||
input_properties_(PropertyListFactory<TInputs...>::template make_property_list<0>(
|
||||
input_names_, in_args_)),
|
||||
output_properties_(PropertyListFactory<TOutputs...>::template make_property_list<0>(
|
||||
output_names_, out_args_))
|
||||
{
|
||||
LOG_PROTO("COPIED! my tuple is at %x and of size %u\r\n", (uintptr_t)&in_args_, sizeof(in_args_));
|
||||
}
|
||||
@@ -881,6 +842,10 @@ public:
|
||||
write_string("]}", output);
|
||||
}
|
||||
|
||||
Endpoint* get_by_name(const char * name, size_t length) {
|
||||
return nullptr; // can't address functions by name
|
||||
}
|
||||
|
||||
void register_endpoints(Endpoint** list, size_t id, size_t length) {
|
||||
if (id < length)
|
||||
list[id] = this;
|
||||
@@ -888,40 +853,51 @@ public:
|
||||
output_properties_.register_endpoints(list, id + 1 + decltype(input_properties_)::endpoint_count, length);
|
||||
}
|
||||
|
||||
template<typename> std::enable_if_t<sizeof...(TOutputs) == 0>
|
||||
handle_ex() {
|
||||
invoke_function_with_tuple(obj_, func_ptr_, in_args_);
|
||||
}
|
||||
|
||||
template<typename> std::enable_if_t<sizeof...(TOutputs) == 1>
|
||||
handle_ex() {
|
||||
std::get<0>(out_args_) = invoke_function_with_tuple(obj_, func_ptr_, in_args_);
|
||||
}
|
||||
|
||||
template<typename> std::enable_if_t<sizeof...(TOutputs) >= 2>
|
||||
handle_ex() {
|
||||
out_args_ = invoke_function_with_tuple(obj_, func_ptr_, in_args_);
|
||||
}
|
||||
|
||||
void handle(const uint8_t* input, size_t input_length, StreamSink* output) {
|
||||
(void) input;
|
||||
(void) input_length;
|
||||
(void) output;
|
||||
LOG_PROTO("tuple still at %x and of size %u\r\n", (uintptr_t)&in_args_, sizeof(in_args_));
|
||||
LOG_PROTO("invoke function using %d and %.3f\r\n", std::get<0>(in_args_), std::get<1>(in_args_));
|
||||
std::get<0>(out_args_) = invoke_function_with_tuple(obj_, func_ptr_, in_args_);
|
||||
handle_ex<void>();
|
||||
}
|
||||
|
||||
const char * name_;
|
||||
std::array<const char *, 1> out_arg_names_; // TODO: remove
|
||||
std::array<const char *, sizeof...(TArgs)> all_arg_names_; // TODO: remove
|
||||
TObj& obj_;
|
||||
TRet(TObj::*func_ptr_)(TArgs...);
|
||||
//TRet ret_val_;
|
||||
std::tuple<TRet> out_args_;
|
||||
std::tuple<TArgs...> in_args_;
|
||||
MemberList<ProtocolProperty<TRet>> output_properties_;
|
||||
MemberList<ProtocolProperty<TArgs>...> input_properties_;
|
||||
TRet(TObj::*func_ptr_)(TInputs...);
|
||||
std::array<const char *, sizeof...(TInputs)> input_names_; // TODO: remove
|
||||
std::array<const char *, sizeof...(TOutputs)> output_names_; // TODO: remove
|
||||
std::tuple<TInputs...> in_args_;
|
||||
std::tuple<TOutputs...> out_args_;
|
||||
MemberList<ProtocolProperty<TInputs>...> input_properties_;
|
||||
MemberList<ProtocolProperty<TOutputs>...> output_properties_;
|
||||
};
|
||||
|
||||
//template<typename TObj, typename TRet = void, typename ... TArgs, typename ... TNames, typename = std::enable_if_t<sizeof...(TArgs) == sizeof...(TNames)>>
|
||||
//ProtocolFunction<TObj, TRet, TArgs...> make_protocol_function(const char * name, TObj& obj, TRet(TObj::*func_ptr)(TArgs...), TNames ... names) {
|
||||
// return ProtocolFunction<TObj, int, TArgs...>(name, obj, func_ptr, names...);
|
||||
//}
|
||||
|
||||
template<typename TObj, typename TRet, typename ... TArgs, typename ... TNames, typename = std::enable_if_t<sizeof...(TArgs) == sizeof...(TNames)>>
|
||||
ProtocolFunction<TObj, TRet, TArgs...> make_protocol_function(const char * name, TObj& obj, TRet(TObj::*func_ptr)(TArgs...), TNames ... names) {
|
||||
return ProtocolFunction<TObj, TRet, TArgs...>(name, obj, func_ptr, names...);
|
||||
template<typename TObj, typename ... TArgs, typename ... TNames,
|
||||
typename = std::enable_if_t<sizeof...(TArgs) == sizeof...(TNames)>>
|
||||
ProtocolFunction<TObj, std::tuple<TArgs...>, std::tuple<>> make_protocol_function(const char * name, TObj& obj, void(TObj::*func_ptr)(TArgs...), TNames ... names) {
|
||||
return ProtocolFunction<TObj, std::tuple<TArgs...>, std::tuple<>>(name, obj, func_ptr, {names...}, {});
|
||||
}
|
||||
|
||||
template<typename TObj, typename TRet, typename ... TArgs, typename ... TNames, typename = std::enable_if_t<sizeof...(TArgs) == sizeof...(TNames)>>
|
||||
ProtocolFunctionWithRet<TObj, TRet, TArgs...> make_protocol_function_with_ret(const char * name, TObj& obj, TRet(TObj::*func_ptr)(TArgs...), TNames ... names) {
|
||||
return ProtocolFunctionWithRet<TObj, TRet, TArgs...>(name, obj, func_ptr, names...);
|
||||
template<typename TObj, typename TRet, typename ... TArgs, typename ... TNames,
|
||||
typename = std::enable_if_t<sizeof...(TArgs) == sizeof...(TNames) && !std::is_void<TRet>::value>>
|
||||
ProtocolFunction<TObj, std::tuple<TArgs...>, std::tuple<TRet>> make_protocol_function(const char * name, TObj& obj, TRet(TObj::*func_ptr)(TArgs...), TNames ... names) {
|
||||
return ProtocolFunction<TObj, std::tuple<TArgs...>, std::tuple<TRet>>(name, obj, func_ptr, {names...}, {"result"});
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user