diff --git a/include/ntcore_c.h b/include/ntcore_c.h index 9f7e755621..eefd35efa3 100644 --- a/include/ntcore_c.h +++ b/include/ntcore_c.h @@ -96,7 +96,7 @@ struct NT_EntryInfo { /** NetworkTables Connection Information */ struct NT_ConnectionInfo { struct NT_String remote_id; - const char *remote_name; + char *remote_name; unsigned int remote_port; unsigned long long last_update; unsigned int protocol_version; @@ -237,7 +237,7 @@ void NT_Flush(void); typedef void (*NT_EntryListenerCallback)( unsigned int uid, void *data, const char *name, size_t name_len, - struct NT_Value *value); + const struct NT_Value *value); typedef void (*NT_ConnectionListenerCallback)( unsigned int uid, void *data, int connected, @@ -254,18 +254,18 @@ void NT_RemoveConnectionListener(unsigned int conn_listener_uid); * Remote Procedure Call Functions */ -typedef NT_Value *(*NT_RpcCallback)(unsigned int uid, void *data, - const char *name, size_t name_len, - NT_Value *params, size_t params_len, - size_t *results_len); +typedef NT_Value **(*NT_RpcCallback)(unsigned int uid, void *data, + const char *name, size_t name_len, + const struct NT_Value **params, + size_t params_len, size_t *results_len); unsigned int NT_CreateRpc(const char *name, size_t name_len, - const NT_RpcDefinition *def, void *data, + const struct NT_RpcDefinition *def, void *data, NT_RpcCallback callback); void NT_DeleteRpc(unsigned int rpc_uid); unsigned int NT_CallRpc(const char *name, size_t name_len, - const NT_Value *params, size_t params_len); -NT_Value *NT_GetRpcResult(unsigned int result_uid, size_t *results_len); + const struct NT_Value **params, size_t params_len); +struct NT_Value **NT_GetRpcResult(unsigned int result_uid, size_t *results_len); /* * Client/Server Functions diff --git a/src/ntcore_c.cpp b/src/ntcore_c.cpp index d6514c7773..38ef667a0d 100644 --- a/src/ntcore_c.cpp +++ b/src/ntcore_c.cpp @@ -9,12 +9,69 @@ #include #include -#include #include "Value_internal.h" using namespace nt; +// Conversion helpers + +static void ConvertToC(llvm::StringRef in, char** out) { + *out = static_cast(std::malloc(in.size() + 1)); + std::memmove(*out, in.data(), in.size()); + out[in.size()] = '\0'; +} + +static void ConvertToC(const EntryInfo& in, NT_EntryInfo* out) { + ConvertToC(in.name, &out->name); + out->type = in.type; + out->flags = in.flags; + out->last_change = in.last_change; +} + +static void ConvertToC(const ConnectionInfo& in, NT_ConnectionInfo* out) { + ConvertToC(in.remote_id, &out->remote_id); + ConvertToC(in.remote_name, &out->remote_name); + out->remote_port = in.remote_port; + out->last_update = in.last_update; + out->protocol_version = in.protocol_version; +} + +static void DisposeConnectionInfo(NT_ConnectionInfo *info) { + std::free(info->remote_id.str); + std::free(info->remote_name); +} + +static RpcParamDef ConvertFromC(const NT_RpcParamDef& in) { + RpcParamDef out; + out.name = ConvertFromC(in.name); + out.def_value = ConvertFromC(in.def_value); + return out; +} + +static RpcResultDef ConvertFromC(const NT_RpcResultDef& in) { + RpcResultDef out; + out.name = ConvertFromC(in.name); + out.type = in.type; + return out; +} + +static RpcDefinition ConvertFromC(const NT_RpcDefinition& in) { + RpcDefinition out; + out.version = in.version; + out.name = ConvertFromC(in.name); + + out.params.reserve(in.num_params); + for (size_t i = 0; i < in.num_params; ++i) + out.params.push_back(ConvertFromC(in.params[i])); + + out.results.reserve(in.num_results); + for (size_t i = 0; i < in.num_results; ++i) + out.results.push_back(ConvertFromC(in.results[i])); + + return out; +} + /* * Table Functions */ @@ -54,7 +111,15 @@ void NT_DeleteAllEntries(void) { nt::DeleteAllEntries(); } struct NT_EntryInfo *NT_GetEntryInfo(const char *prefix, unsigned int prefix_len, int types, unsigned int *count) { - return nullptr; + auto info_v = nt::GetEntryInfo(StringRef(prefix, prefix_len), types); + *count = info_v.size(); + if (info_v.size() == 0) return nullptr; + + // create array and copy into it + NT_EntryInfo* info = static_cast( + std::malloc(info_v.size() * sizeof(NT_EntryInfo))); + for (size_t i = 0; i < info_v.size(); ++i) ConvertToC(info_v[i], &info[i]); + return info; } void NT_Flush(void) { nt::Flush(); } @@ -66,15 +131,28 @@ void NT_Flush(void) { nt::Flush(); } unsigned int NT_AddEntryListener(const char *prefix, size_t prefix_len, void *data, NT_EntryListenerCallback callback) { - return 0; + return nt::AddEntryListener( + StringRef(prefix, prefix_len), + [=](unsigned int uid, StringRef name, std::shared_ptr value) { + callback(uid, data, name.data(), name.size(), &value->value()); + }); } + void NT_RemoveEntryListener(unsigned int entry_listener_uid) { nt::RemoveEntryListener(entry_listener_uid); } + unsigned int NT_AddConnectionListener(void *data, NT_ConnectionListenerCallback callback) { - return 0; + return nt::AddConnectionListener( + [=](unsigned int uid, int connected, const ConnectionInfo &conn) { + NT_ConnectionInfo conn_c; + ConvertToC(conn, &conn_c); + callback(uid, data, connected, &conn_c); + DisposeConnectionInfo(&conn_c); + }); } + void NT_RemoveConnectionListener(unsigned int conn_listener_uid) { nt::RemoveConnectionListener(conn_listener_uid); } @@ -85,29 +163,69 @@ void NT_RemoveConnectionListener(unsigned int conn_listener_uid) { unsigned int NT_CreateRpc(const char *name, size_t name_len, const NT_RpcDefinition *def, void *data, - NT_RpcCallback callback); + NT_RpcCallback callback) { + return nt::CreateRpc( + StringRef(name, name_len), + ConvertFromC(*def), + [=](unsigned int uid, StringRef name, + ArrayRef> params) + -> std::vector> { + // convert params to NT_Value* array + std::vector params_c(params.size()); + for (size_t i = 0; i < params.size(); ++i) + params_c[i] = ¶ms[i]->value(); + + size_t results_len; + NT_Value** results_c = callback(uid, data, name.data(), name.size(), + params_c.data(), params.size(), + &results_len); + + // convert results to Value array + std::vector> results; + results.reserve(results_len); + for (size_t i = 0; i < results_len; ++i) + results.push_back(ConvertFromC(*results_c[i])); + + // dispose the C version + for (size_t i = 0; i < results_len; ++i) { + NT_DisposeValue(results_c[i]); + std::free(results_c[i]); + } + std::free(results_c); + + return results; + }); +} void NT_DeleteRpc(unsigned int rpc_uid) { nt::DeleteRpc(rpc_uid); } unsigned int NT_CallRpc(const char *name, size_t name_len, - const NT_Value *params, size_t params_len) { + const NT_Value **params, size_t params_len) { + // create input vector std::vector> params_v; params_v.reserve(params_len); - for (size_t i=0; i(std::malloc(results_v.size() * sizeof(NT_Value))); - for (size_t i=0; i( + std::malloc(results_v.size() * sizeof(NT_Value*))); + for (size_t i = 0; i < results_v.size(); ++i) { + results[i] = static_cast(std::malloc(sizeof(NT_Value))); + NT_InitValue(results[i]); + ConvertToC(*results_v[i], results[i]); + } return results; } @@ -139,7 +257,15 @@ void NT_SetUpdateRate(double interval) { } struct NT_ConnectionInfo *NT_GetConnections(size_t *count) { - return nullptr; + auto conn_v = nt::GetConnections(); + *count = conn_v.size(); + if (conn_v.size() == 0) return nullptr; + + // create array and copy into it + NT_ConnectionInfo *conn = static_cast( + std::malloc(conn_v.size() * sizeof(NT_ConnectionInfo))); + for (size_t i = 0; i < conn_v.size(); ++i) ConvertToC(conn_v[i], &conn[i]); + return conn; } /* @@ -183,7 +309,7 @@ void NT_DisposeValue(NT_Value *value) { break; } default: - assert(0 && "unknown value type"); + assert(false && "unknown value type"); } value->type = NT_UNASSIGNED; value->last_change = 0; @@ -206,8 +332,6 @@ void NT_InitString(NT_String *str) { } void NT_DisposeConnectionInfoArray(NT_ConnectionInfo *arr, size_t count) { - unsigned int i; - for (i = 0; i < count; i++) - std::free(arr[i].remote_id.str); + for (size_t i = 0; i < count; i++) DisposeConnectionInfo(&arr[i]); std::free(arr); }