mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-25 01:41:43 +00:00
[ntcore] NetworkTables 4 (#3217)
This commit is contained in:
245
ntcore/src/generate/cpp/jni/types_jni.cpp.jinja
Normal file
245
ntcore/src/generate/cpp/jni/types_jni.cpp.jinja
Normal file
@@ -0,0 +1,245 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include <wpi/jni_util.h>
|
||||
|
||||
#include "edu_wpi_first_networktables_NetworkTablesJNI.h"
|
||||
#include "ntcore.h"
|
||||
|
||||
using namespace wpi::java;
|
||||
|
||||
//
|
||||
// Globals and load/unload
|
||||
//
|
||||
{% for t in types %}
|
||||
static JClass timestamped{{ t.TypeName }}Cls;
|
||||
{%- endfor %}
|
||||
{%- for t in types %}
|
||||
{%- if t.jni.ToJavaArray == "MakeJObjectArray" %}
|
||||
static JClass {{ t.jni.jtype }}Cls;
|
||||
{%- endif %}
|
||||
{%- endfor %}
|
||||
static JException nullPointerEx;
|
||||
|
||||
static const JClassInit classes[] = {
|
||||
{%- for t in types %}
|
||||
{"edu/wpi/first/networktables/Timestamped{{ t.TypeName }}", ×tamped{{ t.TypeName }}Cls},
|
||||
{%- endfor %}
|
||||
{%- for t in types %}
|
||||
{%- if t.jni.ToJavaArray == "MakeJObjectArray" %}
|
||||
{"{{ t.jni.jtypestr }}", &{{ t.jni.jtype }}Cls},
|
||||
{%- endif %}
|
||||
{%- endfor %}
|
||||
};
|
||||
|
||||
static const JExceptionInit exceptions[] = {
|
||||
{"java/lang/NullPointerException", &nullPointerEx},
|
||||
};
|
||||
|
||||
namespace nt {
|
||||
|
||||
bool JNI_LoadTypes(JNIEnv* env) {
|
||||
// Cache references to classes
|
||||
for (auto& c : classes) {
|
||||
*c.cls = JClass(env, c.name);
|
||||
if (!*c.cls) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& c : exceptions) {
|
||||
*c.cls = JException(env, c.name);
|
||||
if (!*c.cls) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void JNI_UnloadTypes(JNIEnv* env) {
|
||||
// Delete global references
|
||||
for (auto& c : classes) {
|
||||
c.cls->free(env);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace nt
|
||||
|
||||
static std::vector<int> FromJavaBooleanArray(JNIEnv* env, jbooleanArray jarr) {
|
||||
CriticalJBooleanArrayRef ref{env, jarr};
|
||||
if (!ref) {
|
||||
return {};
|
||||
}
|
||||
wpi::span<const jboolean> elements{ref};
|
||||
size_t len = elements.size();
|
||||
std::vector<int> arr;
|
||||
arr.reserve(len);
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
arr.push_back(elements[i]);
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
static std::vector<std::string> FromJavaStringArray(JNIEnv* env, jobjectArray jarr) {
|
||||
size_t len = env->GetArrayLength(jarr);
|
||||
std::vector<std::string> arr;
|
||||
arr.reserve(len);
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
JLocal<jstring> elem{
|
||||
env, static_cast<jstring>(env->GetObjectArrayElement(jarr, i))};
|
||||
if (!elem) {
|
||||
return {};
|
||||
}
|
||||
arr.emplace_back(JStringRef{env, elem}.str());
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
{% for t in types %}
|
||||
static jobject MakeJObject(JNIEnv* env, nt::Timestamped{{ t.TypeName }} value) {
|
||||
static jmethodID constructor = env->GetMethodID(
|
||||
timestamped{{ t.TypeName }}Cls, "<init>", "(JJ{{ t.jni.jtypestr }})V");
|
||||
{%- if t.jni.JavaObject %}
|
||||
JLocal<{{ t.jni.jtype }}> val{env, {{ t.jni.ToJavaBegin }}value.value{{ t.jni.ToJavaEnd }}};
|
||||
return env->NewObject(timestamped{{ t.TypeName }}Cls, constructor,
|
||||
static_cast<jlong>(value.time),
|
||||
static_cast<jlong>(value.serverTime), val.obj());
|
||||
{%- else %}
|
||||
return env->NewObject(timestamped{{ t.TypeName }}Cls, constructor,
|
||||
static_cast<jlong>(value.time),
|
||||
static_cast<jlong>(value.serverTime),
|
||||
{{ t.jni.ToJavaBegin }}value.value{{ t.jni.ToJavaEnd }});
|
||||
{%- endif %}
|
||||
}
|
||||
{% endfor %}
|
||||
{%- for t in types %}
|
||||
static jobjectArray MakeJObject(JNIEnv* env,
|
||||
wpi::span<const nt::Timestamped{{ t.TypeName }}> arr) {
|
||||
jobjectArray jarr =
|
||||
env->NewObjectArray(arr.size(), timestamped{{ t.TypeName }}Cls, nullptr);
|
||||
if (!jarr) {
|
||||
return nullptr;
|
||||
}
|
||||
for (size_t i = 0; i < arr.size(); ++i) {
|
||||
JLocal<jobject> elem{env, MakeJObject(env, arr[i])};
|
||||
env->SetObjectArrayElement(jarr, i, elem.obj());
|
||||
}
|
||||
return jarr;
|
||||
}
|
||||
{% endfor %}
|
||||
{%- for t in types %}
|
||||
{%- if t.jni.ToJavaArray == "MakeJObjectArray" %}
|
||||
static jobjectArray MakeJObjectArray(JNIEnv* env, wpi::span<const {{ t.cpp.ValueType }}> arr) {
|
||||
jobjectArray jarr =
|
||||
env->NewObjectArray(arr.size(), {{ t.jni.jtype }}Cls, nullptr);
|
||||
if (!jarr) {
|
||||
return nullptr;
|
||||
}
|
||||
for (size_t i = 0; i < arr.size(); ++i) {
|
||||
JLocal<jobject> elem{env, {{ t.jni.ToJavaBegin }}arr[i]{{ t.jni.ToJavaEnd }}};
|
||||
env->SetObjectArrayElement(jarr, i, elem.obj());
|
||||
}
|
||||
return jarr;
|
||||
}
|
||||
{% endif %}
|
||||
{%- endfor %}
|
||||
|
||||
extern "C" {
|
||||
{% for t in types %}
|
||||
/*
|
||||
* Class: edu_wpi_first_networktables_NetworkTablesJNI
|
||||
* Method: getAtomic{{ t.TypeName }}
|
||||
* Signature: (I{{ t.jni.jtypestr }})Ledu/wpi/first/networktables/Timestamped{{ t.TypeName }};
|
||||
*/
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_edu_wpi_first_networktables_NetworkTablesJNI_getAtomic{{ t.TypeName }}
|
||||
(JNIEnv* env, jclass, jint subentry, {{ t.jni.jtype }} defaultValue)
|
||||
{
|
||||
return MakeJObject(env, nt::GetAtomic{{ t.TypeName }}(subentry, {{ t.jni.FromJavaBegin }}defaultValue{{ t.jni.FromJavaEnd }}));
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_networktables_NetworkTablesJNI
|
||||
* Method: readQueue{{ t.TypeName }}
|
||||
* Signature: (I)[Ledu/wpi/first/networktables/Timestamped{{ t.TypeName }};
|
||||
*/
|
||||
JNIEXPORT jobjectArray JNICALL
|
||||
Java_edu_wpi_first_networktables_NetworkTablesJNI_readQueue{{ t.TypeName }}
|
||||
(JNIEnv* env, jclass, jint subentry)
|
||||
{
|
||||
return MakeJObject(env, nt::ReadQueue{{ t.TypeName }}(subentry));
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_networktables_NetworkTablesJNI
|
||||
* Method: readQueueValues{{ t.TypeName }}
|
||||
* Signature: (I)[{{ t.jni.jtypestr }}
|
||||
*/
|
||||
JNIEXPORT {% if t.jni.JavaObject %}jobject{% else %}{{ t.jni.jtype }}{% endif %}Array JNICALL
|
||||
Java_edu_wpi_first_networktables_NetworkTablesJNI_readQueueValues{{ t.TypeName }}
|
||||
(JNIEnv* env, jclass, jint subentry)
|
||||
{
|
||||
return {{ t.jni.ToJavaArray }}(env, nt::ReadQueueValues{{ t.TypeName }}(subentry));
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_networktables_NetworkTablesJNI
|
||||
* Method: set{{ t.TypeName }}
|
||||
* Signature: (IJ{{ t.jni.jtypestr }})Z
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_edu_wpi_first_networktables_NetworkTablesJNI_set{{ t.TypeName }}
|
||||
(JNIEnv*{% if t.jni.JavaObject %} env{% endif %}, jclass, jint entry, jlong time, {{ t.jni.jtype }} value)
|
||||
{
|
||||
{%- if t.jni.JavaObject %}
|
||||
if (!value) {
|
||||
nullPointerEx.Throw(env, "value cannot be null");
|
||||
return false;
|
||||
}
|
||||
{%- endif %}
|
||||
return nt::Set{{ t.TypeName }}(entry, {{ t.jni.FromJavaBegin }}value{{ t.jni.FromJavaEnd }}, time);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_networktables_NetworkTablesJNI
|
||||
* Method: get{{ t.TypeName }}
|
||||
* Signature: (I{{ t.jni.jtypestr }}){{ t.jni.jtypestr }}
|
||||
*/
|
||||
JNIEXPORT {{ t.jni.jtype }} JNICALL
|
||||
Java_edu_wpi_first_networktables_NetworkTablesJNI_get{{ t.TypeName }}
|
||||
(JNIEnv*{% if t.jni.JavaObject %} env{% endif %}, jclass, jint entry, {{ t.jni.jtype }} defaultValue)
|
||||
{
|
||||
{%- if t.jni.JavaObject %}
|
||||
auto val = nt::GetEntryValue(entry);
|
||||
if (!val || !val.Is{{ t.TypeName }}()) {
|
||||
return defaultValue;
|
||||
}
|
||||
return {{ t.jni.ToJavaBegin }}val.Get{{ t.TypeName }}(){{ t.jni.ToJavaEnd }};
|
||||
{%- else %}
|
||||
return nt::Get{{ t.TypeName }}(entry, defaultValue);
|
||||
{%- endif %}
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_networktables_NetworkTablesJNI
|
||||
* Method: setDefault{{ t.TypeName }}
|
||||
* Signature: (IJ{{ t.jni.jtypestr }})Z
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_edu_wpi_first_networktables_NetworkTablesJNI_setDefault{{ t.TypeName }}
|
||||
(JNIEnv*{% if t.jni.JavaObject %} env{% endif %}, jclass, jint entry, jlong, {{ t.jni.jtype }} defaultValue)
|
||||
{
|
||||
{%- if t.jni.JavaObject %}
|
||||
if (!defaultValue) {
|
||||
nullPointerEx.Throw(env, "defaultValue cannot be null");
|
||||
return false;
|
||||
}
|
||||
{%- endif %}
|
||||
return nt::SetDefault{{ t.TypeName }}(entry, {{ t.jni.FromJavaBegin }}defaultValue{{ t.jni.FromJavaEnd }});
|
||||
}
|
||||
{% endfor %}
|
||||
} // extern "C"
|
||||
106
ntcore/src/generate/cpp/ntcore_c_types.cpp.jinja
Normal file
106
ntcore/src/generate/cpp/ntcore_c_types.cpp.jinja
Normal file
@@ -0,0 +1,106 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include "ntcore_c_types.h"
|
||||
|
||||
#include "Value_internal.h"
|
||||
#include "ntcore_cpp.h"
|
||||
|
||||
using namespace nt;
|
||||
|
||||
template <typename T>
|
||||
static inline wpi::span<const T> ConvertFromC(const T* arr, size_t size) {
|
||||
return {arr, size};
|
||||
}
|
||||
|
||||
static inline std::string_view ConvertFromC(const char* arr, size_t size) {
|
||||
return {arr, size};
|
||||
}
|
||||
|
||||
static std::vector<std::string> ConvertFromC(const NT_String* arr, size_t size) {
|
||||
std::vector<std::string> v;
|
||||
v.reserve(size);
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
v.emplace_back(ConvertFromC(arr[i]));
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
{% for t in types %}
|
||||
static void ConvertToC(const nt::Timestamped{{ t.TypeName }}& in, NT_Timestamped{{ t.TypeName }}* out) {
|
||||
out->time = in.time;
|
||||
out->serverTime = in.serverTime;
|
||||
{%- if t.c.IsArray %}
|
||||
out->value = ConvertToC<{{ t.c.ValueType[:-1] }}>(in.value, &out->len);
|
||||
{% else %}
|
||||
out->value = in.value;
|
||||
{% endif -%}
|
||||
}
|
||||
{% endfor %}
|
||||
|
||||
extern "C" {
|
||||
{% for t in types %}
|
||||
NT_Bool NT_Set{{ t.TypeName }}(NT_Handle pubentry, int64_t time, {{ t.c.ParamType }} value{% if t.c.IsArray %}, size_t len{% endif %}) {
|
||||
{%- if t.c.IsArray %}
|
||||
return nt::Set{{ t.TypeName }}(pubentry, ConvertFromC(value, len), time);
|
||||
{%- else %}
|
||||
return nt::Set{{ t.TypeName }}(pubentry, value, time);
|
||||
{%- endif %}
|
||||
}
|
||||
|
||||
NT_Bool NT_SetDefault{{ t.TypeName }}(NT_Handle pubentry, {{ t.c.ParamType }} defaultValue{% if t.c.IsArray %}, size_t defaultValueLen{% endif %}) {
|
||||
{%- if t.c.IsArray %}
|
||||
return nt::SetDefault{{ t.TypeName }}(pubentry, ConvertFromC(defaultValue, defaultValueLen));
|
||||
{%- else %}
|
||||
return nt::SetDefault{{ t.TypeName }}(pubentry, defaultValue);
|
||||
{%- endif %}
|
||||
}
|
||||
|
||||
{{ t.c.ValueType }} NT_Get{{ t.TypeName }}(NT_Handle subentry, {{ t.c.ParamType }} defaultValue{% if t.c.IsArray %}, size_t defaultValueLen, size_t* len{% endif %}) {
|
||||
{%- if t.c.IsArray %}
|
||||
auto cppValue = nt::Get{{ t.TypeName }}(subentry, ConvertFromC(defaultValue, defaultValueLen));
|
||||
return ConvertToC<{{ t.c.ValueType[:-1] }}>(cppValue, len);
|
||||
{%- else %}
|
||||
return nt::Get{{ t.TypeName }}(subentry, defaultValue);
|
||||
{%- endif %}
|
||||
}
|
||||
|
||||
void NT_GetAtomic{{ t.TypeName }}(NT_Handle subentry, {{ t.c.ParamType }} defaultValue{% if t.c.IsArray %}, size_t defaultValueLen{% endif %}, struct NT_Timestamped{{ t.TypeName }}* value) {
|
||||
{%- if t.c.IsArray %}
|
||||
auto cppValue = nt::GetAtomic{{ t.TypeName }}(subentry, ConvertFromC(defaultValue, defaultValueLen));
|
||||
{%- else %}
|
||||
auto cppValue = nt::GetAtomic{{ t.TypeName }}(subentry, defaultValue);
|
||||
{%- endif %}
|
||||
ConvertToC(cppValue, value);
|
||||
}
|
||||
|
||||
void NT_DisposeTimestamped{{ t.TypeName }}(struct NT_Timestamped{{ t.TypeName }}* value) {
|
||||
{%- if t.TypeName == "StringArray" %}
|
||||
NT_FreeStringArray(value->value, value->len);
|
||||
{%- elif t.c.IsArray %}
|
||||
std::free(value->value);
|
||||
{%- endif %}
|
||||
}
|
||||
|
||||
struct NT_Timestamped{{ t.TypeName }}* NT_ReadQueue{{ t.TypeName }}(NT_Handle subentry, size_t* len) {
|
||||
auto arr = nt::ReadQueue{{ t.TypeName }}(subentry);
|
||||
return ConvertToC<NT_Timestamped{{ t.TypeName }}>(arr, len);
|
||||
}
|
||||
|
||||
void NT_FreeQueue{{ t.TypeName }}(struct NT_Timestamped{{ t.TypeName }}* arr, size_t len) {
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
NT_DisposeTimestamped{{ t.TypeName }}(&arr[i]);
|
||||
}
|
||||
std::free(arr);
|
||||
}
|
||||
|
||||
{%- if not t.c.IsArray %}
|
||||
{{ t.c.ValueType }}* NT_ReadQueueValues{{ t.TypeName }}(NT_Handle subentry, size_t* len) {
|
||||
auto arr = nt::ReadQueueValues{{ t.TypeName }}(subentry);
|
||||
return ConvertToC<{{ t.c.ValueType }}>(arr, len);
|
||||
}
|
||||
{%- endif %}
|
||||
|
||||
{% endfor %}
|
||||
} // extern "C"
|
||||
76
ntcore/src/generate/cpp/ntcore_cpp_types.cpp.jinja
Normal file
76
ntcore/src/generate/cpp/ntcore_cpp_types.cpp.jinja
Normal file
@@ -0,0 +1,76 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include "ntcore_cpp_types.h"
|
||||
|
||||
#include "Handle.h"
|
||||
#include "InstanceImpl.h"
|
||||
|
||||
namespace nt {
|
||||
{% for t in types %}
|
||||
bool Set{{ t.TypeName }}(NT_Handle pubentry, {{ t.cpp.ParamType }} value, int64_t time) {
|
||||
if (auto ii = InstanceImpl::Get(Handle{pubentry}.GetInst())) {
|
||||
return ii->localStorage.SetEntryValue(pubentry,
|
||||
Value::Make{{ t.TypeName }}(value, time == 0 ? Now() : time));
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
bool SetDefault{{ t.TypeName }}(NT_Handle pubentry, {{ t.cpp.ParamType }} defaultValue) {
|
||||
if (auto ii = InstanceImpl::Get(Handle{pubentry}.GetInst())) {
|
||||
return ii->localStorage.SetDefaultEntryValue(pubentry,
|
||||
Value::Make{{ t.TypeName }}(defaultValue, 1));
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
{{ t.cpp.ValueType }} Get{{ t.TypeName }}(NT_Handle subentry, {{ t.cpp.ParamType }} defaultValue) {
|
||||
return GetAtomic{{ t.TypeName }}(subentry, defaultValue).value;
|
||||
}
|
||||
|
||||
Timestamped{{ t.TypeName }} GetAtomic{{ t.TypeName }}(NT_Handle subentry, {{ t.cpp.ParamType }} defaultValue) {
|
||||
if (auto ii = InstanceImpl::Get(Handle{subentry}.GetInst())) {
|
||||
return ii->localStorage.GetAtomic{{ t.TypeName }}(subentry, defaultValue);
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Timestamped{{ t.TypeName }}> ReadQueue{{ t.TypeName }}(NT_Handle subentry) {
|
||||
if (auto ii = InstanceImpl::Get(Handle{subentry}.GetInst())) {
|
||||
return ii->localStorage.ReadQueue{{ t.TypeName }}(subentry);
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<{% if t.cpp.ValueType == "bool" %}int{% else %}{{ t.cpp.ValueType }}{% endif %}> ReadQueueValues{{ t.TypeName }}(NT_Handle subentry) {
|
||||
std::vector<{% if t.cpp.ValueType == "bool" %}int{% else %}{{ t.cpp.ValueType }}{% endif %}> rv;
|
||||
auto arr = ReadQueue{{ t.TypeName }}(subentry);
|
||||
rv.reserve(arr.size());
|
||||
for (auto&& elem : arr) {
|
||||
rv.emplace_back(std::move(elem.value));
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
{% if t.cpp.SmallRetType and t.cpp.SmallElemType %}
|
||||
{{ t.cpp.SmallRetType }} Get{{ t.TypeName }}(NT_Handle subentry, wpi::SmallVectorImpl<{{ t.cpp.SmallElemType }}>& buf, {{ t.cpp.ParamType }} defaultValue) {
|
||||
return GetAtomic{{ t.TypeName }}(subentry, buf, defaultValue).value;
|
||||
}
|
||||
|
||||
Timestamped{{ t.TypeName }}View GetAtomic{{ t.TypeName }}(
|
||||
NT_Handle subentry,
|
||||
wpi::SmallVectorImpl<{{ t.cpp.SmallElemType }}>& buf,
|
||||
{{ t.cpp.ParamType }} defaultValue) {
|
||||
if (auto ii = InstanceImpl::Get(Handle{subentry}.GetInst())) {
|
||||
return ii->localStorage.GetAtomic{{ t.TypeName }}(subentry, buf, defaultValue);
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
} // namespace nt
|
||||
Reference in New Issue
Block a user