mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-20 00:51:42 +00:00
The default behavior is to only notify remote changes, but for some applications (e.g. GUI's) it's advantageous to know about local changes as well. This is (slightly) optimized in that local changes only result in additional resources being consumed if (any) local listeners have been created.
1237 lines
40 KiB
C++
1237 lines
40 KiB
C++
#include <jni.h>
|
|
#include <cassert>
|
|
#include <sstream>
|
|
|
|
#include "edu_wpi_first_wpilibj_networktables_NetworkTablesJNI.h"
|
|
#include "ntcore.h"
|
|
|
|
//
|
|
// Globals and load/unload
|
|
//
|
|
|
|
// Used for callback.
|
|
static JavaVM *jvm = nullptr;
|
|
static jclass booleanCls = nullptr;
|
|
static jclass doubleCls = nullptr;
|
|
static jclass stringCls = nullptr;
|
|
static jclass connectionInfoCls = nullptr;
|
|
static jclass entryInfoCls = nullptr;
|
|
static jclass keyNotDefinedEx = nullptr;
|
|
static jclass persistentEx = nullptr;
|
|
|
|
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
|
|
jvm = vm;
|
|
|
|
JNIEnv *env;
|
|
if (vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6) != JNI_OK)
|
|
return JNI_ERR;
|
|
|
|
// Cache references to classes
|
|
jclass local;
|
|
|
|
local = env->FindClass("java/lang/Boolean");
|
|
if (!local) return JNI_ERR;
|
|
booleanCls = static_cast<jclass>(env->NewGlobalRef(local));
|
|
if (!booleanCls) return JNI_ERR;
|
|
env->DeleteLocalRef(local);
|
|
|
|
local = env->FindClass("java/lang/Double");
|
|
if (!local) return JNI_ERR;
|
|
doubleCls = static_cast<jclass>(env->NewGlobalRef(local));
|
|
if (!doubleCls) return JNI_ERR;
|
|
env->DeleteLocalRef(local);
|
|
|
|
local = env->FindClass("java/lang/String");
|
|
if (!local) return JNI_ERR;
|
|
stringCls = static_cast<jclass>(env->NewGlobalRef(local));
|
|
if (!stringCls) return JNI_ERR;
|
|
env->DeleteLocalRef(local);
|
|
|
|
local = env->FindClass("edu/wpi/first/wpilibj/networktables/ConnectionInfo");
|
|
if (!local) return JNI_ERR;
|
|
connectionInfoCls = static_cast<jclass>(env->NewGlobalRef(local));
|
|
if (!connectionInfoCls) return JNI_ERR;
|
|
env->DeleteLocalRef(local);
|
|
|
|
local = env->FindClass("edu/wpi/first/wpilibj/networktables/EntryInfo");
|
|
if (!local) return JNI_ERR;
|
|
entryInfoCls = static_cast<jclass>(env->NewGlobalRef(local));
|
|
if (!entryInfoCls) return JNI_ERR;
|
|
env->DeleteLocalRef(local);
|
|
|
|
local =
|
|
env->FindClass("edu/wpi/first/wpilibj/networktables/NetworkTableKeyNotDefined");
|
|
keyNotDefinedEx = static_cast<jclass>(env->NewGlobalRef(local));
|
|
if (!keyNotDefinedEx) return JNI_ERR;
|
|
env->DeleteLocalRef(local);
|
|
|
|
local =
|
|
env->FindClass("edu/wpi/first/wpilibj/networktables/PersistentException");
|
|
persistentEx = static_cast<jclass>(env->NewGlobalRef(local));
|
|
if (!persistentEx) return JNI_ERR;
|
|
env->DeleteLocalRef(local);
|
|
|
|
return JNI_VERSION_1_6;
|
|
}
|
|
|
|
JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) {
|
|
JNIEnv *env;
|
|
if (vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6) != JNI_OK)
|
|
return;
|
|
// Delete global references
|
|
if (booleanCls) env->DeleteGlobalRef(booleanCls);
|
|
if (doubleCls) env->DeleteGlobalRef(doubleCls);
|
|
if (stringCls) env->DeleteGlobalRef(stringCls);
|
|
if (connectionInfoCls) env->DeleteGlobalRef(connectionInfoCls);
|
|
if (entryInfoCls) env->DeleteGlobalRef(entryInfoCls);
|
|
if (keyNotDefinedEx) env->DeleteGlobalRef(keyNotDefinedEx);
|
|
if (persistentEx) env->DeleteGlobalRef(persistentEx);
|
|
jvm = nullptr;
|
|
}
|
|
|
|
//
|
|
// Helper class to automatically clean up a local reference
|
|
//
|
|
template <typename T>
|
|
class JavaLocal {
|
|
public:
|
|
JavaLocal(JNIEnv *env, T obj) : m_env(env), m_obj(obj) {}
|
|
~JavaLocal() {
|
|
if (m_obj) m_env->DeleteLocalRef(m_obj);
|
|
}
|
|
operator T() { return m_obj; }
|
|
T obj() { return m_obj; }
|
|
|
|
private:
|
|
JNIEnv *m_env;
|
|
T m_obj;
|
|
};
|
|
|
|
//
|
|
// Helper class to create and clean up a global reference
|
|
//
|
|
template <typename T>
|
|
class JavaGlobal {
|
|
public:
|
|
JavaGlobal(JNIEnv *env, T obj)
|
|
: m_obj(static_cast<T>(env->NewGlobalRef(obj))) {}
|
|
~JavaGlobal() {
|
|
if (!jvm || nt::NotifierDestroyed()) return;
|
|
JNIEnv *env;
|
|
if (jvm->AttachCurrentThread(reinterpret_cast<void **>(&env), nullptr) !=
|
|
JNI_OK)
|
|
return;
|
|
if (!env || !env->functions) return;
|
|
env->DeleteGlobalRef(m_obj);
|
|
jvm->DetachCurrentThread();
|
|
}
|
|
operator T() { return m_obj; }
|
|
T obj() { return m_obj; }
|
|
|
|
private:
|
|
T m_obj;
|
|
};
|
|
|
|
//
|
|
// Helper class to create and clean up a weak global reference
|
|
//
|
|
template <typename T>
|
|
class JavaWeakGlobal {
|
|
public:
|
|
JavaWeakGlobal(JNIEnv *env, T obj)
|
|
: m_obj(static_cast<T>(env->NewWeakGlobalRef(obj))) {}
|
|
~JavaWeakGlobal() {
|
|
if (!jvm || nt::NotifierDestroyed()) return;
|
|
JNIEnv *env;
|
|
if (jvm->AttachCurrentThread(reinterpret_cast<void **>(&env), nullptr) !=
|
|
JNI_OK)
|
|
return;
|
|
if (!env || !env->functions) return;
|
|
env->DeleteWeakGlobalRef(m_obj);
|
|
jvm->DetachCurrentThread();
|
|
}
|
|
JavaLocal<T> obj(JNIEnv *env) {
|
|
return JavaLocal<T>(env, env->NewLocalRef(m_obj));
|
|
}
|
|
|
|
private:
|
|
T m_obj;
|
|
};
|
|
|
|
//
|
|
// Conversions from Java objects to C++
|
|
//
|
|
|
|
class JavaStringRef {
|
|
public:
|
|
JavaStringRef(JNIEnv *env, jstring str)
|
|
: m_env(env),
|
|
m_jstr(str),
|
|
m_str(env->GetStringUTFChars(str, nullptr)) {}
|
|
~JavaStringRef() { m_env->ReleaseStringUTFChars(m_jstr, m_str); }
|
|
|
|
operator nt::StringRef() const { return nt::StringRef(m_str); }
|
|
nt::StringRef str() const { return nt::StringRef(m_str); }
|
|
const char *c_str() const { return m_str; }
|
|
|
|
private:
|
|
JNIEnv *m_env;
|
|
jstring m_jstr;
|
|
const char *m_str;
|
|
};
|
|
|
|
class JavaByteRef {
|
|
public:
|
|
JavaByteRef(JNIEnv *env, jbyteArray jarr)
|
|
: m_env(env),
|
|
m_jarr(jarr),
|
|
m_elements(env->GetByteArrayElements(jarr, nullptr)),
|
|
m_size(env->GetArrayLength(jarr)) {}
|
|
~JavaByteRef() {
|
|
m_env->ReleaseByteArrayElements(m_jarr, m_elements, JNI_ABORT);
|
|
}
|
|
|
|
operator nt::StringRef() const {
|
|
return nt::StringRef(reinterpret_cast<char *>(m_elements), m_size);
|
|
}
|
|
|
|
private:
|
|
JNIEnv *m_env;
|
|
jbyteArray m_jarr;
|
|
jbyte *m_elements;
|
|
size_t m_size;
|
|
};
|
|
|
|
std::shared_ptr<nt::Value> FromJavaRaw(JNIEnv *env, jbyteArray jarr) {
|
|
size_t len = env->GetArrayLength(jarr);
|
|
jbyte *elements =
|
|
static_cast<jbyte *>(env->GetPrimitiveArrayCritical(jarr, nullptr));
|
|
if (!elements) return nullptr;
|
|
auto rv = nt::Value::MakeRaw(
|
|
nt::StringRef(reinterpret_cast<char *>(elements), len));
|
|
env->ReleasePrimitiveArrayCritical(jarr, elements, JNI_ABORT);
|
|
return rv;
|
|
}
|
|
|
|
std::shared_ptr<nt::Value> FromJavaRpc(JNIEnv *env, jbyteArray jarr) {
|
|
size_t len = env->GetArrayLength(jarr);
|
|
jbyte *elements =
|
|
static_cast<jbyte *>(env->GetPrimitiveArrayCritical(jarr, nullptr));
|
|
if (!elements) return nullptr;
|
|
auto rv = nt::Value::MakeRpc(
|
|
nt::StringRef(reinterpret_cast<char *>(elements), len));
|
|
env->ReleasePrimitiveArrayCritical(jarr, elements, JNI_ABORT);
|
|
return rv;
|
|
}
|
|
|
|
std::shared_ptr<nt::Value> FromJavaBooleanArray(JNIEnv *env,
|
|
jbooleanArray jarr) {
|
|
size_t len = env->GetArrayLength(jarr);
|
|
std::vector<int> arr;
|
|
arr.reserve(len);
|
|
jboolean *elements =
|
|
static_cast<jboolean*>(env->GetPrimitiveArrayCritical(jarr, nullptr));
|
|
if (!elements) return nullptr;
|
|
for (size_t i = 0; i < len; ++i) arr.push_back(elements[i]);
|
|
env->ReleasePrimitiveArrayCritical(jarr, elements, JNI_ABORT);
|
|
return nt::Value::MakeBooleanArray(arr);
|
|
}
|
|
|
|
std::shared_ptr<nt::Value> FromJavaDoubleArray(JNIEnv *env, jdoubleArray jarr) {
|
|
size_t len = env->GetArrayLength(jarr);
|
|
jdouble *elements =
|
|
static_cast<jdouble *>(env->GetPrimitiveArrayCritical(jarr, nullptr));
|
|
if (!elements) return nullptr;
|
|
auto rv = nt::Value::MakeDoubleArray(nt::ArrayRef<double>(elements, len));
|
|
env->ReleasePrimitiveArrayCritical(jarr, elements, JNI_ABORT);
|
|
return rv;
|
|
}
|
|
|
|
std::shared_ptr<nt::Value> 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) {
|
|
JavaLocal<jstring> elem(
|
|
env, static_cast<jstring>(env->GetObjectArrayElement(jarr, i)));
|
|
if (!elem) return nullptr;
|
|
arr.push_back(JavaStringRef(env, elem).str());
|
|
}
|
|
return nt::Value::MakeStringArray(std::move(arr));
|
|
}
|
|
|
|
//
|
|
// Conversions from C++ to Java objects
|
|
//
|
|
|
|
static inline jstring ToJavaString(JNIEnv *env, nt::StringRef str) {
|
|
// fastpath if string already null terminated; if not, need to make a copy
|
|
if (str.data()[str.size()] == '\0')
|
|
return env->NewStringUTF(str.data());
|
|
else
|
|
return env->NewStringUTF(str.str().c_str());
|
|
}
|
|
|
|
static jbyteArray ToJavaByteArray(JNIEnv *env, nt::StringRef str) {
|
|
jbyteArray jarr = env->NewByteArray(str.size());
|
|
if (!jarr) return nullptr;
|
|
env->SetByteArrayRegion(jarr, 0, str.size(),
|
|
reinterpret_cast<const jbyte *>(str.data()));
|
|
return jarr;
|
|
}
|
|
|
|
static jbooleanArray ToJavaBooleanArray(JNIEnv *env, nt::ArrayRef<int> arr)
|
|
{
|
|
jbooleanArray jarr = env->NewBooleanArray(arr.size());
|
|
if (!jarr) return nullptr;
|
|
jboolean *elements =
|
|
static_cast<jboolean*>(env->GetPrimitiveArrayCritical(jarr, nullptr));
|
|
if (!elements) return nullptr;
|
|
for (size_t i = 0; i < arr.size(); ++i)
|
|
elements[i] = arr[i];
|
|
env->ReleasePrimitiveArrayCritical(jarr, elements, 0);
|
|
return jarr;
|
|
}
|
|
|
|
static jdoubleArray ToJavaDoubleArray(JNIEnv *env, nt::ArrayRef<double> arr)
|
|
{
|
|
jdoubleArray jarr = env->NewDoubleArray(arr.size());
|
|
if (!jarr) return nullptr;
|
|
env->SetDoubleArrayRegion(jarr, 0, arr.size(), arr.data());
|
|
return jarr;
|
|
}
|
|
|
|
static jobjectArray ToJavaStringArray(JNIEnv *env,
|
|
nt::ArrayRef<std::string> arr) {
|
|
jobjectArray jarr = env->NewObjectArray(arr.size(), stringCls, nullptr);
|
|
if (!jarr) return nullptr;
|
|
for (size_t i = 0; i < arr.size(); ++i) {
|
|
JavaLocal<jstring> elem(env, env->NewStringUTF(arr[i].c_str()));
|
|
env->SetObjectArrayElement(jarr, i, elem.obj());
|
|
}
|
|
return jarr;
|
|
}
|
|
|
|
static jobject ToJavaObject(JNIEnv *env, const nt::Value& value) {
|
|
static jmethodID booleanConstructor = nullptr;
|
|
static jmethodID doubleConstructor = nullptr;
|
|
if (!booleanConstructor)
|
|
booleanConstructor = env->GetMethodID(booleanCls, "<init>", "(Z)V");
|
|
if (!doubleConstructor)
|
|
doubleConstructor = env->GetMethodID(doubleCls, "<init>", "(D)V");
|
|
|
|
switch (value.type()) {
|
|
case NT_BOOLEAN:
|
|
return env->NewObject(booleanCls, booleanConstructor,
|
|
(jboolean)(value.GetBoolean() ? 1 : 0));
|
|
case NT_DOUBLE:
|
|
return env->NewObject(doubleCls, doubleConstructor,
|
|
(jdouble)value.GetDouble());
|
|
case NT_STRING:
|
|
return ToJavaString(env, value.GetString());
|
|
case NT_RAW:
|
|
return ToJavaByteArray(env, value.GetRaw());
|
|
case NT_BOOLEAN_ARRAY:
|
|
return ToJavaBooleanArray(env, value.GetBooleanArray());
|
|
case NT_DOUBLE_ARRAY:
|
|
return ToJavaDoubleArray(env, value.GetDoubleArray());
|
|
case NT_STRING_ARRAY:
|
|
return ToJavaStringArray(env, value.GetStringArray());
|
|
case NT_RPC:
|
|
return ToJavaByteArray(env, value.GetRpc());
|
|
default:
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
static jobject ToJavaObject(JNIEnv *env, const nt::ConnectionInfo &info) {
|
|
static jmethodID constructor =
|
|
env->GetMethodID(connectionInfoCls, "<init>",
|
|
"(Ljava/lang/String;Ljava/lang/String;IJI)V");
|
|
JavaLocal<jstring> remote_id(env, ToJavaString(env, info.remote_id));
|
|
JavaLocal<jstring> remote_name(env, ToJavaString(env, info.remote_name));
|
|
return env->NewObject(connectionInfoCls, constructor, remote_id.obj(),
|
|
remote_name.obj(), (jint)info.remote_port,
|
|
(jlong)info.last_update, (jint)info.protocol_version);
|
|
}
|
|
|
|
static jobject ToJavaObject(JNIEnv *env, const nt::EntryInfo &info) {
|
|
static jmethodID constructor =
|
|
env->GetMethodID(entryInfoCls, "<init>", "(Ljava/lang/String;IIJ)V");
|
|
JavaLocal<jstring> name(env, ToJavaString(env, info.name));
|
|
return env->NewObject(entryInfoCls, constructor, name.obj(), (jint)info.type,
|
|
(jint)info.flags, (jlong)info.last_change);
|
|
}
|
|
|
|
//
|
|
// Exception throwers
|
|
//
|
|
|
|
static void ThrowTableKeyNotDefined(JNIEnv *env, jstring key) {
|
|
static jmethodID constructor = nullptr;
|
|
if (!constructor)
|
|
constructor =
|
|
env->GetMethodID(keyNotDefinedEx, "<init>", "(Ljava/lang/String;)V");
|
|
jobject exception = env->NewObject(keyNotDefinedEx, constructor, key);
|
|
env->Throw(static_cast<jthrowable>(exception));
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: containsKey
|
|
* Signature: (Ljava/lang/String;)Z
|
|
*/
|
|
JNIEXPORT jboolean JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_containsKey
|
|
(JNIEnv *env, jclass, jstring key)
|
|
{
|
|
auto val = nt::GetEntryValue(JavaStringRef(env, key));
|
|
if (!val) return false;
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: getType
|
|
* Signature: (Ljava/lang/String;)I
|
|
*/
|
|
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_getType
|
|
(JNIEnv *env, jclass, jstring key)
|
|
{
|
|
auto val = nt::GetEntryValue(JavaStringRef(env, key));
|
|
if (!val) return NT_UNASSIGNED;
|
|
return val->type();
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: putBoolean
|
|
* Signature: (Ljava/lang/String;Z)Z
|
|
*/
|
|
JNIEXPORT jboolean JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_putBoolean
|
|
(JNIEnv *env, jclass, jstring key, jboolean value)
|
|
{
|
|
return nt::SetEntryValue(JavaStringRef(env, key),
|
|
nt::Value::MakeBoolean(value != JNI_FALSE));
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: putDouble
|
|
* Signature: (Ljava/lang/String;D)Z
|
|
*/
|
|
JNIEXPORT jboolean JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_putDouble
|
|
(JNIEnv *env, jclass, jstring key, jdouble value)
|
|
{
|
|
return nt::SetEntryValue(JavaStringRef(env, key),
|
|
nt::Value::MakeDouble(value));
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: putString
|
|
* Signature: (Ljava/lang/String;Ljava/lang/String;)Z
|
|
*/
|
|
JNIEXPORT jboolean JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_putString
|
|
(JNIEnv *env, jclass, jstring key, jstring value)
|
|
{
|
|
return nt::SetEntryValue(JavaStringRef(env, key),
|
|
nt::Value::MakeString(JavaStringRef(env, value)));
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: putRaw
|
|
* Signature: (Ljava/lang/String;[B)Z
|
|
*/
|
|
JNIEXPORT jboolean JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_putRaw
|
|
(JNIEnv *env, jclass, jstring key, jbyteArray value)
|
|
{
|
|
auto v = FromJavaRaw(env, value);
|
|
if (!v) return false;
|
|
return nt::SetEntryValue(JavaStringRef(env, key), v);
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: putBooleanArray
|
|
* Signature: (Ljava/lang/String;[Z)Z
|
|
*/
|
|
JNIEXPORT jboolean JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_putBooleanArray
|
|
(JNIEnv *env, jclass, jstring key, jbooleanArray value)
|
|
{
|
|
auto v = FromJavaBooleanArray(env, value);
|
|
if (!v) return false;
|
|
return nt::SetEntryValue(JavaStringRef(env, key), v);
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: putDoubleArray
|
|
* Signature: (Ljava/lang/String;[D)Z
|
|
*/
|
|
JNIEXPORT jboolean JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_putDoubleArray
|
|
(JNIEnv *env, jclass, jstring key, jdoubleArray value)
|
|
{
|
|
auto v = FromJavaDoubleArray(env, value);
|
|
if (!v) return false;
|
|
return nt::SetEntryValue(JavaStringRef(env, key), v);
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: putStringArray
|
|
* Signature: (Ljava/lang/String;[Ljava/lang/String;)Z
|
|
*/
|
|
JNIEXPORT jboolean JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_putStringArray
|
|
(JNIEnv *env, jclass, jstring key, jobjectArray value)
|
|
{
|
|
auto v = FromJavaStringArray(env, value);
|
|
if (!v) return false;
|
|
return nt::SetEntryValue(JavaStringRef(env, key), v);
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: forcePutBoolean
|
|
* Signature: (Ljava/lang/String;Z)V
|
|
*/
|
|
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_forcePutBoolean
|
|
(JNIEnv *env, jclass, jstring key, jboolean value)
|
|
{
|
|
nt::SetEntryTypeValue(JavaStringRef(env, key), nt::Value::MakeBoolean(value != JNI_FALSE));
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: forcePutDouble
|
|
* Signature: (Ljava/lang/String;D)V
|
|
*/
|
|
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_forcePutDouble
|
|
(JNIEnv *env, jclass, jstring key, jdouble value)
|
|
{
|
|
nt::SetEntryTypeValue(JavaStringRef(env, key), nt::Value::MakeDouble(value));
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: forcePutString
|
|
* Signature: (Ljava/lang/String;Ljava/lang/String;)V
|
|
*/
|
|
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_forcePutString
|
|
(JNIEnv *env, jclass, jstring key, jstring value)
|
|
{
|
|
nt::SetEntryTypeValue(JavaStringRef(env, key),
|
|
nt::Value::MakeString(JavaStringRef(env, value)));
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: forcePutRaw
|
|
* Signature: (Ljava/lang/String;[B)V
|
|
*/
|
|
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_forcePutRaw
|
|
(JNIEnv *env, jclass, jstring key, jbyteArray value)
|
|
{
|
|
auto v = FromJavaRaw(env, value);
|
|
if (!v) return;
|
|
nt::SetEntryTypeValue(JavaStringRef(env, key), v);
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: forcePutBooleanArray
|
|
* Signature: (Ljava/lang/String;[Z)V
|
|
*/
|
|
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_forcePutBooleanArray
|
|
(JNIEnv *env, jclass, jstring key, jbooleanArray value)
|
|
{
|
|
auto v = FromJavaBooleanArray(env, value);
|
|
if (!v) return;
|
|
nt::SetEntryTypeValue(JavaStringRef(env, key), v);
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: forcePutDoubleArray
|
|
* Signature: (Ljava/lang/String;[D)V
|
|
*/
|
|
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_forcePutDoubleArray
|
|
(JNIEnv *env, jclass, jstring key, jdoubleArray value)
|
|
{
|
|
auto v = FromJavaDoubleArray(env, value);
|
|
if (!v) return;
|
|
nt::SetEntryTypeValue(JavaStringRef(env, key), v);
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: forcePutStringArray
|
|
* Signature: (Ljava/lang/String;[Ljava/lang/String;)V
|
|
*/
|
|
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_forcePutStringArray
|
|
(JNIEnv *env, jclass, jstring key, jobjectArray value)
|
|
{
|
|
auto v = FromJavaStringArray(env, value);
|
|
if (!v) return;
|
|
nt::SetEntryTypeValue(JavaStringRef(env, key), v);
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: getValue
|
|
* Signature: (Ljava/lang/String;)Ljava/lang/Object;
|
|
*/
|
|
JNIEXPORT jobject JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_getValue__Ljava_lang_String_2
|
|
(JNIEnv *env, jclass, jstring key)
|
|
{
|
|
auto val = nt::GetEntryValue(JavaStringRef(env, key));
|
|
if (!val || !val->IsBoolean()) {
|
|
ThrowTableKeyNotDefined(env, key);
|
|
return nullptr;
|
|
}
|
|
return ToJavaObject(env, *val);
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: getBoolean
|
|
* Signature: (Ljava/lang/String;)Z
|
|
*/
|
|
JNIEXPORT jboolean JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_getBoolean__Ljava_lang_String_2
|
|
(JNIEnv *env, jclass, jstring key)
|
|
{
|
|
auto val = nt::GetEntryValue(JavaStringRef(env, key));
|
|
if (!val || !val->IsBoolean()) {
|
|
ThrowTableKeyNotDefined(env, key);
|
|
return false;
|
|
}
|
|
return val->GetBoolean();
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: getDouble
|
|
* Signature: (Ljava/lang/String;)D
|
|
*/
|
|
JNIEXPORT jdouble JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_getDouble__Ljava_lang_String_2
|
|
(JNIEnv *env, jclass, jstring key)
|
|
{
|
|
auto val = nt::GetEntryValue(JavaStringRef(env, key));
|
|
if (!val || !val->IsDouble()) {
|
|
ThrowTableKeyNotDefined(env, key);
|
|
return 0;
|
|
}
|
|
return val->GetDouble();
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: getString
|
|
* Signature: (Ljava/lang/String;)Ljava/lang/String;
|
|
*/
|
|
JNIEXPORT jstring JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_getString__Ljava_lang_String_2
|
|
(JNIEnv *env, jclass, jstring key)
|
|
{
|
|
auto val = nt::GetEntryValue(JavaStringRef(env, key));
|
|
if (!val || !val->IsString()) {
|
|
ThrowTableKeyNotDefined(env, key);
|
|
return nullptr;
|
|
}
|
|
return ToJavaString(env, val->GetString());
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: getRaw
|
|
* Signature: (Ljava/lang/String;)[B
|
|
*/
|
|
JNIEXPORT jbyteArray JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_getRaw__Ljava_lang_String_2
|
|
(JNIEnv *env, jclass, jstring key)
|
|
{
|
|
auto val = nt::GetEntryValue(JavaStringRef(env, key));
|
|
if (!val || !val->IsRaw()) {
|
|
ThrowTableKeyNotDefined(env, key);
|
|
return nullptr;
|
|
}
|
|
return ToJavaByteArray(env, val->GetRaw());
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: getBooleanArray
|
|
* Signature: (Ljava/lang/String;)[Z
|
|
*/
|
|
JNIEXPORT jbooleanArray JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_getBooleanArray__Ljava_lang_String_2
|
|
(JNIEnv *env, jclass, jstring key)
|
|
{
|
|
auto val = nt::GetEntryValue(JavaStringRef(env, key));
|
|
if (!val || !val->IsBooleanArray()) {
|
|
ThrowTableKeyNotDefined(env, key);
|
|
return nullptr;
|
|
}
|
|
return ToJavaBooleanArray(env, val->GetBooleanArray());
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: getDoubleArray
|
|
* Signature: (Ljava/lang/String;)[D
|
|
*/
|
|
JNIEXPORT jdoubleArray JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_getDoubleArray__Ljava_lang_String_2
|
|
(JNIEnv *env, jclass, jstring key)
|
|
{
|
|
auto val = nt::GetEntryValue(JavaStringRef(env, key));
|
|
if (!val || !val->IsDoubleArray()) {
|
|
ThrowTableKeyNotDefined(env, key);
|
|
return nullptr;
|
|
}
|
|
return ToJavaDoubleArray(env, val->GetDoubleArray());
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: getStringArray
|
|
* Signature: (Ljava/lang/String;)[Ljava/lang/String;
|
|
*/
|
|
JNIEXPORT jobjectArray JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_getStringArray__Ljava_lang_String_2
|
|
(JNIEnv *env, jclass, jstring key)
|
|
{
|
|
auto val = nt::GetEntryValue(JavaStringRef(env, key));
|
|
if (!val || !val->IsStringArray()) {
|
|
ThrowTableKeyNotDefined(env, key);
|
|
return nullptr;
|
|
}
|
|
return ToJavaStringArray(env, val->GetStringArray());
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: getValue
|
|
* Signature: (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;
|
|
*/
|
|
JNIEXPORT jobject JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_getValue__Ljava_lang_String_2Ljava_lang_Object_2
|
|
(JNIEnv *env, jclass, jstring key, jobject defaultValue)
|
|
{
|
|
auto val = nt::GetEntryValue(JavaStringRef(env, key));
|
|
if (!val || !val->IsBoolean()) return defaultValue;
|
|
return ToJavaObject(env, *val);
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: getBoolean
|
|
* Signature: (Ljava/lang/String;Z)Z
|
|
*/
|
|
JNIEXPORT jboolean JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_getBoolean__Ljava_lang_String_2Z
|
|
(JNIEnv *env, jclass, jstring key, jboolean defaultValue)
|
|
{
|
|
auto val = nt::GetEntryValue(JavaStringRef(env, key));
|
|
if (!val || !val->IsBoolean()) return defaultValue;
|
|
return val->GetBoolean();
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: getDouble
|
|
* Signature: (Ljava/lang/String;D)D
|
|
*/
|
|
JNIEXPORT jdouble JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_getDouble__Ljava_lang_String_2D
|
|
(JNIEnv *env, jclass, jstring key, jdouble defaultValue)
|
|
{
|
|
auto val = nt::GetEntryValue(JavaStringRef(env, key));
|
|
if (!val || !val->IsDouble()) return defaultValue;
|
|
return val->GetDouble();
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: getString
|
|
* Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
|
|
*/
|
|
JNIEXPORT jstring JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_getString__Ljava_lang_String_2Ljava_lang_String_2
|
|
(JNIEnv *env, jclass, jstring key, jstring defaultValue)
|
|
{
|
|
auto val = nt::GetEntryValue(JavaStringRef(env, key));
|
|
if (!val || !val->IsString()) return defaultValue;
|
|
return ToJavaString(env, val->GetString());
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: getRaw
|
|
* Signature: (Ljava/lang/String;[B)[B
|
|
*/
|
|
JNIEXPORT jbyteArray JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_getRaw__Ljava_lang_String_2_3B
|
|
(JNIEnv *env, jclass, jstring key, jbyteArray defaultValue)
|
|
{
|
|
auto val = nt::GetEntryValue(JavaStringRef(env, key));
|
|
if (!val || !val->IsRaw()) return defaultValue;
|
|
return ToJavaByteArray(env, val->GetRaw());
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: getBooleanArray
|
|
* Signature: (Ljava/lang/String;[Z)[Z
|
|
*/
|
|
JNIEXPORT jbooleanArray JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_getBooleanArray__Ljava_lang_String_2_3Z
|
|
(JNIEnv *env, jclass, jstring key, jbooleanArray defaultValue)
|
|
{
|
|
auto val = nt::GetEntryValue(JavaStringRef(env, key));
|
|
if (!val || !val->IsBooleanArray()) return defaultValue;
|
|
return ToJavaBooleanArray(env, val->GetBooleanArray());
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: getDoubleArray
|
|
* Signature: (Ljava/lang/String;[D)[D
|
|
*/
|
|
JNIEXPORT jdoubleArray JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_getDoubleArray__Ljava_lang_String_2_3D
|
|
(JNIEnv *env, jclass, jstring key, jdoubleArray defaultValue)
|
|
{
|
|
auto val = nt::GetEntryValue(JavaStringRef(env, key));
|
|
if (!val || !val->IsDoubleArray()) return defaultValue;
|
|
return ToJavaDoubleArray(env, val->GetDoubleArray());
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: getStringArray
|
|
* Signature: (Ljava/lang/String;[Ljava/lang/String;)[Ljava/lang/String;
|
|
*/
|
|
JNIEXPORT jobjectArray JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_getStringArray__Ljava_lang_String_2_3Ljava_lang_String_2
|
|
(JNIEnv *env, jclass, jstring key, jobjectArray defaultValue)
|
|
{
|
|
auto val = nt::GetEntryValue(JavaStringRef(env, key));
|
|
if (!val || !val->IsStringArray()) return defaultValue;
|
|
return ToJavaStringArray(env, val->GetStringArray());
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: setEntryFlags
|
|
* Signature: (Ljava/lang/String;I)V
|
|
*/
|
|
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_setEntryFlags
|
|
(JNIEnv *env, jclass, jstring key, jint flags)
|
|
{
|
|
nt::SetEntryFlags(JavaStringRef(env, key), flags);
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: getEntryFlags
|
|
* Signature: (Ljava/lang/String;)I
|
|
*/
|
|
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_getEntryFlags
|
|
(JNIEnv *env, jclass, jstring key)
|
|
{
|
|
return nt::GetEntryFlags(JavaStringRef(env, key));
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: deleteEntry
|
|
* Signature: (Ljava/lang/String;)V
|
|
*/
|
|
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_deleteEntry
|
|
(JNIEnv *env, jclass, jstring key)
|
|
{
|
|
nt::DeleteEntry(JavaStringRef(env, key));
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: deleteAllEntries
|
|
* Signature: ()V
|
|
*/
|
|
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_deleteAllEntries
|
|
(JNIEnv *, jclass)
|
|
{
|
|
nt::DeleteAllEntries();
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: getEntries
|
|
* Signature: (Ljava/lang/String;I)[Ledu/wpi/first/wpilibj/networktables/EntryInfo;
|
|
*/
|
|
JNIEXPORT jobjectArray JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_getEntries
|
|
(JNIEnv *env, jclass, jstring prefix, jint types)
|
|
{
|
|
auto arr = nt::GetEntryInfo(JavaStringRef(env, prefix), types);
|
|
jobjectArray jarr = env->NewObjectArray(arr.size(), entryInfoCls, nullptr);
|
|
if (!jarr) return nullptr;
|
|
for (size_t i = 0; i < arr.size(); ++i) {
|
|
JavaLocal<jobject> jelem(env, ToJavaObject(env, arr[i]));
|
|
env->SetObjectArrayElement(jarr, i, jelem);
|
|
}
|
|
return jarr;
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: flush
|
|
* Signature: ()V
|
|
*/
|
|
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_flush
|
|
(JNIEnv *, jclass)
|
|
{
|
|
nt::Flush();
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: addEntryListener
|
|
* Signature: (Ljava/lang/String;Ledu/wpi/first/wpilibj/networktables/NetworkTablesJNI/EntryListenerFunction;Z)I
|
|
*/
|
|
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_addEntryListener
|
|
(JNIEnv *envouter, jclass, jstring prefix, jobject listener,
|
|
jboolean immediateNotify, jboolean localNotify)
|
|
{
|
|
// the shared pointer to the weak global will keep it around until the
|
|
// entry listener is destroyed
|
|
auto listener_global =
|
|
std::make_shared<JavaGlobal<jobject>>(envouter, listener);
|
|
|
|
// cls is a temporary here; cannot be used within callback functor
|
|
jclass cls = envouter->GetObjectClass(listener);
|
|
if (!cls) return 0;
|
|
|
|
// method ids, on the other hand, are safe to retain
|
|
jmethodID mid = envouter->GetMethodID(
|
|
cls, "apply", "(ILjava/lang/String;Ljava/lang/Object;Z)V");
|
|
if (!mid) return 0;
|
|
|
|
return nt::AddEntryListener(
|
|
JavaStringRef(envouter, prefix),
|
|
[=](unsigned int uid, nt::StringRef name,
|
|
std::shared_ptr<nt::Value> value, bool is_new) {
|
|
// need to attach as we're coming from a separate thread here
|
|
if (!jvm) return;
|
|
JNIEnv *env;
|
|
if (jvm->AttachCurrentThread(reinterpret_cast<void **>(&env),
|
|
nullptr) != JNI_OK)
|
|
return;
|
|
if (!env || !env->functions) return;
|
|
|
|
{
|
|
// get the handler
|
|
auto handler = listener_global->obj();
|
|
|
|
// convert the value into the appropriate Java type
|
|
jobject jobj = ToJavaObject(env, *value);
|
|
if (!jobj) goto done;
|
|
|
|
if (env->ExceptionCheck()) {
|
|
env->ExceptionDescribe();
|
|
goto done;
|
|
}
|
|
env->CallVoidMethod(handler, mid, (jint)uid, ToJavaString(env, name),
|
|
jobj, (jboolean)(is_new ? 1 : 0));
|
|
if (env->ExceptionCheck()) env->ExceptionDescribe();
|
|
}
|
|
done:
|
|
jvm->DetachCurrentThread();
|
|
},
|
|
immediateNotify != JNI_FALSE,
|
|
localNotify != JNI_FALSE);
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: removeEntryListener
|
|
* Signature: (I)V
|
|
*/
|
|
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_removeEntryListener
|
|
(JNIEnv *, jclass, jint entryListenerUid)
|
|
{
|
|
nt::RemoveEntryListener(entryListenerUid);
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: addConnectionListener
|
|
* Signature: (Ledu/wpi/first/wpilibj/networktables/NetworkTablesJNI/ConnectionListenerFunction;Z)I
|
|
*/
|
|
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_addConnectionListener
|
|
(JNIEnv *envouter, jclass, jobject listener, jboolean immediateNotify)
|
|
{
|
|
// the shared pointer to the weak global will keep it around until the
|
|
// entry listener is destroyed
|
|
auto listener_global =
|
|
std::make_shared<JavaGlobal<jobject>>(envouter, listener);
|
|
|
|
// cls is a temporary here; cannot be used within callback functor
|
|
jclass cls = envouter->GetObjectClass(listener);
|
|
if (!cls) return 0;
|
|
|
|
// method ids, on the other hand, are safe to retain
|
|
jmethodID mid = envouter->GetMethodID(
|
|
cls, "apply", "(IZLedu/wpi/first/wpilibj/networktables/ConnectionInfo;)V");
|
|
if (!mid) return 0;
|
|
|
|
return nt::AddConnectionListener(
|
|
[=](unsigned int uid, bool connected, const nt::ConnectionInfo& conn) {
|
|
// need to attach as we're coming from a separate thread here
|
|
if (!jvm) return;
|
|
JNIEnv *env;
|
|
if (jvm->AttachCurrentThread(reinterpret_cast<void **>(&env),
|
|
nullptr) != JNI_OK)
|
|
return;
|
|
if (!env || !env->functions) return;
|
|
|
|
{
|
|
// get the handler
|
|
auto handler = listener_global->obj();
|
|
//if (!handler) goto done; // can happen due to weak reference
|
|
|
|
// convert into the appropriate Java type
|
|
jobject jobj = ToJavaObject(env, conn);
|
|
if (!jobj) goto done;
|
|
|
|
if (env->ExceptionCheck()) {
|
|
env->ExceptionDescribe();
|
|
goto done;
|
|
}
|
|
env->CallVoidMethod(handler, mid, (jint)uid,
|
|
(jboolean)(connected ? 1 : 0), jobj);
|
|
if (env->ExceptionCheck()) env->ExceptionDescribe();
|
|
}
|
|
done:
|
|
jvm->DetachCurrentThread();
|
|
},
|
|
immediateNotify != JNI_FALSE);
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: removeConnectionListener
|
|
* Signature: (I)V
|
|
*/
|
|
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_removeConnectionListener
|
|
(JNIEnv *, jclass, jint connListenerUid)
|
|
{
|
|
nt::RemoveConnectionListener(connListenerUid);
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: getRpc
|
|
* Signature: (Ljava/lang/String;)[B
|
|
*/
|
|
JNIEXPORT jbyteArray JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_getRpc__Ljava_lang_String_2
|
|
(JNIEnv *env, jclass, jstring key)
|
|
{
|
|
auto val = nt::GetEntryValue(JavaStringRef(env, key));
|
|
if (!val || !val->IsRpc()) {
|
|
ThrowTableKeyNotDefined(env, key);
|
|
return nullptr;
|
|
}
|
|
return ToJavaByteArray(env, val->GetRpc());
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: getRpc
|
|
* Signature: (Ljava/lang/String;[B)[B
|
|
*/
|
|
JNIEXPORT jbyteArray JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_getRpc__Ljava_lang_String_2_3B
|
|
(JNIEnv *env, jclass, jstring key, jbyteArray defaultValue)
|
|
{
|
|
auto val = nt::GetEntryValue(JavaStringRef(env, key));
|
|
if (!val || !val->IsRpc()) return defaultValue;
|
|
return ToJavaByteArray(env, val->GetRpc());
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: callRpc
|
|
* Signature: (Ljava/lang/String;[B)I
|
|
*/
|
|
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_callRpc
|
|
(JNIEnv *env, jclass, jstring key, jbyteArray params)
|
|
{
|
|
return nt::CallRpc(JavaStringRef(env, key), JavaByteRef(env, params));
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: setNetworkIdentity
|
|
* Signature: (Ljava/lang/String;)V
|
|
*/
|
|
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_setNetworkIdentity
|
|
(JNIEnv *env, jclass, jstring name)
|
|
{
|
|
nt::SetNetworkIdentity(JavaStringRef(env, name));
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: startServer
|
|
* Signature: (Ljava/lang/String;Ljava/lang/String;I)V
|
|
*/
|
|
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_startServer
|
|
(JNIEnv *env, jclass, jstring persistFilename, jstring listenAddress,
|
|
jint port)
|
|
{
|
|
nt::StartServer(JavaStringRef(env, persistFilename),
|
|
JavaStringRef(env, listenAddress).c_str(), port);
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: stopServer
|
|
* Signature: ()V
|
|
*/
|
|
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_stopServer
|
|
(JNIEnv *, jclass)
|
|
{
|
|
nt::StopServer();
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: startClient
|
|
* Signature: (Ljava/lang/String;I)V
|
|
*/
|
|
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_startClient
|
|
(JNIEnv *env, jclass, jstring serverName, jint port)
|
|
{
|
|
nt::StartClient(JavaStringRef(env, serverName).c_str(), port);
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: stopClient
|
|
* Signature: ()V
|
|
*/
|
|
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_stopClient
|
|
(JNIEnv *, jclass)
|
|
{
|
|
nt::StopClient();
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: setUpdateRate
|
|
* Signature: (D)V
|
|
*/
|
|
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_setUpdateRate
|
|
(JNIEnv *, jclass, jdouble interval)
|
|
{
|
|
nt::SetUpdateRate(interval);
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: getConnections
|
|
* Signature: ()[Ledu/wpi/first/wpilibj/networktables/ConnectionInfo;
|
|
*/
|
|
JNIEXPORT jobjectArray JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_getConnections
|
|
(JNIEnv *env, jclass)
|
|
{
|
|
auto arr = nt::GetConnections();
|
|
jobjectArray jarr =
|
|
env->NewObjectArray(arr.size(), connectionInfoCls, nullptr);
|
|
if (!jarr) return nullptr;
|
|
for (size_t i = 0; i < arr.size(); ++i) {
|
|
JavaLocal<jobject> jelem(env, ToJavaObject(env, arr[i]));
|
|
env->SetObjectArrayElement(jarr, i, jelem);
|
|
}
|
|
return jarr;
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: savePersistent
|
|
* Signature: (Ljava/lang/String;)V
|
|
*/
|
|
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_savePersistent
|
|
(JNIEnv *env, jclass, jstring filename)
|
|
{
|
|
const char *err = nt::SavePersistent(JavaStringRef(env, filename));
|
|
if (err) env->ThrowNew(persistentEx, err);
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: loadPersistent
|
|
* Signature: (Ljava/lang/String;)[Ljava/lang/String;
|
|
*/
|
|
JNIEXPORT jobjectArray JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_loadPersistent
|
|
(JNIEnv *env, jclass, jstring filename)
|
|
{
|
|
std::vector<std::string> warns;
|
|
const char *err = nt::LoadPersistent(JavaStringRef(env, filename),
|
|
[&](size_t line, const char *msg) {
|
|
std::ostringstream oss;
|
|
oss << line << ": " << msg;
|
|
warns.push_back(oss.str());
|
|
});
|
|
if (err) {
|
|
env->ThrowNew(persistentEx, err);
|
|
return nullptr;
|
|
}
|
|
return ToJavaStringArray(env, warns);
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: now
|
|
* Signature: ()J
|
|
*/
|
|
JNIEXPORT jlong JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_now
|
|
(JNIEnv *, jclass)
|
|
{
|
|
return nt::Now();
|
|
}
|
|
|
|
/*
|
|
* Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
|
|
* Method: setLogger
|
|
* Signature: (Ledu/wpi/first/wpilibj/networktables/NetworkTablesJNI/LoggerFunction;I)V
|
|
*/
|
|
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_setLogger
|
|
(JNIEnv *envouter, jclass, jobject func, jint minLevel)
|
|
{
|
|
// the shared pointer to the global will keep it around until the
|
|
// a new logger is set
|
|
auto func_global = std::make_shared<JavaGlobal<jobject>>(envouter, func);
|
|
|
|
// cls is a temporary here; cannot be used within callback functor
|
|
jclass cls = envouter->GetObjectClass(func);
|
|
if (!cls) return;
|
|
|
|
// method ids, on the other hand, are safe to retain
|
|
jmethodID mid = envouter->GetMethodID(
|
|
cls, "apply", "(ILjava/lang/String;ILjava/lang/String;)V");
|
|
if (!mid) return;
|
|
|
|
return nt::SetLogger(
|
|
[=](unsigned int level, const char *file, unsigned int line,
|
|
const char *msg) {
|
|
// need to attach as we're coming from a separate thread here
|
|
if (!jvm) return;
|
|
JNIEnv *env;
|
|
if (jvm->AttachCurrentThread(reinterpret_cast<void **>(&env),
|
|
nullptr) != JNI_OK)
|
|
return;
|
|
if (!env || !env->functions) return;
|
|
|
|
{
|
|
// get the handler
|
|
auto handler = func_global->obj();
|
|
if (!handler) goto done; // shouldn't happen, but ignore if it does
|
|
|
|
env->CallVoidMethod(handler, mid, (jint)level, ToJavaString(env, file),
|
|
(jint)line, ToJavaString(env, msg));
|
|
if (env->ExceptionCheck()) env->ExceptionDescribe();
|
|
}
|
|
done:
|
|
jvm->DetachCurrentThread();
|
|
},
|
|
minLevel);
|
|
}
|