Squashed 'third_party/ntcore_2016/' content from commit d8de5e4
Change-Id: Id4839f41b6a620d8bae58dcf1710016671cc4992
git-subtree-dir: third_party/ntcore_2016
git-subtree-split: d8de5e4f19e612e7102172c0dbf152ce82d3d63a
diff --git a/java/arm-linux/LICENSE b/java/arm-linux/LICENSE
new file mode 100644
index 0000000..b40a0f4
--- /dev/null
+++ b/java/arm-linux/LICENSE
@@ -0,0 +1,347 @@
+The GNU General Public License (GPL)
+
+Version 2, June 1991
+
+Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Everyone is permitted to copy and distribute verbatim copies of this license
+document, but changing it is not allowed.
+
+Preamble
+
+The licenses for most software are designed to take away your freedom to share
+and change it. By contrast, the GNU General Public License is intended to
+guarantee your freedom to share and change free software--to make sure the
+software is free for all its users. This General Public License applies to
+most of the Free Software Foundation's software and to any other program whose
+authors commit to using it. (Some other Free Software Foundation software is
+covered by the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+When we speak of free software, we are referring to freedom, not price. Our
+General Public Licenses are designed to make sure that you have the freedom to
+distribute copies of free software (and charge for this service if you wish),
+that you receive source code or can get it if you want it, that you can change
+the software or use pieces of it in new free programs; and that you know you
+can do these things.
+
+To protect your rights, we need to make restrictions that forbid anyone to deny
+you these rights or to ask you to surrender the rights. These restrictions
+translate to certain responsibilities for you if you distribute copies of the
+software, or if you modify it.
+
+For example, if you distribute copies of such a program, whether gratis or for
+a fee, you must give the recipients all the rights that you have. You must
+make sure that they, too, receive or can get the source code. And you must
+show them these terms so they know their rights.
+
+We protect your rights with two steps: (1) copyright the software, and (2)
+offer you this license which gives you legal permission to copy, distribute
+and/or modify the software.
+
+Also, for each author's protection and ours, we want to make certain that
+everyone understands that there is no warranty for this free software. If the
+software is modified by someone else and passed on, we want its recipients to
+know that what they have is not the original, so that any problems introduced
+by others will not reflect on the original authors' reputations.
+
+Finally, any free program is threatened constantly by software patents. We
+wish to avoid the danger that redistributors of a free program will
+individually obtain patent licenses, in effect making the program proprietary.
+To prevent this, we have made it clear that any patent must be licensed for
+everyone's free use or not licensed at all.
+
+The precise terms and conditions for copying, distribution and modification
+follow.
+
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+0. This License applies to any program or other work which contains a notice
+placed by the copyright holder saying it may be distributed under the terms of
+this General Public License. The "Program", below, refers to any such program
+or work, and a "work based on the Program" means either the Program or any
+derivative work under copyright law: that is to say, a work containing the
+Program or a portion of it, either verbatim or with modifications and/or
+translated into another language. (Hereinafter, translation is included
+without limitation in the term "modification".) Each licensee is addressed as
+"you".
+
+Activities other than copying, distribution and modification are not covered by
+this License; they are outside its scope. The act of running the Program is
+not restricted, and the output from the Program is covered only if its contents
+constitute a work based on the Program (independent of having been made by
+running the Program). Whether that is true depends on what the Program does.
+
+1. You may copy and distribute verbatim copies of the Program's source code as
+you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this License
+and to the absence of any warranty; and give any other recipients of the
+Program a copy of this License along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and you may
+at your option offer warranty protection in exchange for a fee.
+
+2. You may modify your copy or copies of the Program or any portion of it, thus
+forming a work based on the Program, and copy and distribute such modifications
+or work under the terms of Section 1 above, provided that you also meet all of
+these conditions:
+
+ a) You must cause the modified files to carry prominent notices stating
+ that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in whole or
+ in part contains or is derived from the Program or any part thereof, to be
+ licensed as a whole at no charge to all third parties under the terms of
+ this License.
+
+ c) If the modified program normally reads commands interactively when run,
+ you must cause it, when started running for such interactive use in the
+ most ordinary way, to print or display an announcement including an
+ appropriate copyright notice and a notice that there is no warranty (or
+ else, saying that you provide a warranty) and that users may redistribute
+ the program under these conditions, and telling the user how to view a copy
+ of this License. (Exception: if the Program itself is interactive but does
+ not normally print such an announcement, your work based on the Program is
+ not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If identifiable
+sections of that work are not derived from the Program, and can be reasonably
+considered independent and separate works in themselves, then this License, and
+its terms, do not apply to those sections when you distribute them as separate
+works. But when you distribute the same sections as part of a whole which is a
+work based on the Program, the distribution of the whole must be on the terms
+of this License, whose permissions for other licensees extend to the entire
+whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your
+rights to work written entirely by you; rather, the intent is to exercise the
+right to control the distribution of derivative or collective works based on
+the Program.
+
+In addition, mere aggregation of another work not based on the Program with the
+Program (or with a work based on the Program) on a volume of a storage or
+distribution medium does not bring the other work under the scope of this
+License.
+
+3. You may copy and distribute the Program (or a work based on it, under
+Section 2) in object code or executable form under the terms of Sections 1 and
+2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable source
+ code, which must be distributed under the terms of Sections 1 and 2 above
+ on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three years, to
+ give any third party, for a charge no more than your cost of physically
+ performing source distribution, a complete machine-readable copy of the
+ corresponding source code, to be distributed under the terms of Sections 1
+ and 2 above on a medium customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer to
+ distribute corresponding source code. (This alternative is allowed only
+ for noncommercial distribution and only if you received the program in
+ object code or executable form with such an offer, in accord with
+ Subsection b above.)
+
+The source code for a work means the preferred form of the work for making
+modifications to it. For an executable work, complete source code means all
+the source code for all modules it contains, plus any associated interface
+definition files, plus the scripts used to control compilation and installation
+of the executable. However, as a special exception, the source code
+distributed need not include anything that is normally distributed (in either
+source or binary form) with the major components (compiler, kernel, and so on)
+of the operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the source
+code from the same place counts as distribution of the source code, even though
+third parties are not compelled to copy the source along with the object code.
+
+4. You may not copy, modify, sublicense, or distribute the Program except as
+expressly provided under this License. Any attempt otherwise to copy, modify,
+sublicense or distribute the Program is void, and will automatically terminate
+your rights under this License. However, parties who have received copies, or
+rights, from you under this License will not have their licenses terminated so
+long as such parties remain in full compliance.
+
+5. You are not required to accept this License, since you have not signed it.
+However, nothing else grants you permission to modify or distribute the Program
+or its derivative works. These actions are prohibited by law if you do not
+accept this License. Therefore, by modifying or distributing the Program (or
+any work based on the Program), you indicate your acceptance of this License to
+do so, and all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+6. Each time you redistribute the Program (or any work based on the Program),
+the recipient automatically receives a license from the original licensor to
+copy, distribute or modify the Program subject to these terms and conditions.
+You may not impose any further restrictions on the recipients' exercise of the
+rights granted herein. You are not responsible for enforcing compliance by
+third parties to this License.
+
+7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues), conditions
+are imposed on you (whether by court order, agreement or otherwise) that
+contradict the conditions of this License, they do not excuse you from the
+conditions of this License. If you cannot distribute so as to satisfy
+simultaneously your obligations under this License and any other pertinent
+obligations, then as a consequence you may not distribute the Program at all.
+For example, if a patent license would not permit royalty-free redistribution
+of the Program by all those who receive copies directly or indirectly through
+you, then the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply and
+the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or
+other property right claims or to contest validity of any such claims; this
+section has the sole purpose of protecting the integrity of the free software
+distribution system, which is implemented by public license practices. Many
+people have made generous contributions to the wide range of software
+distributed through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing to
+distribute software through any other system and a licensee cannot impose that
+choice.
+
+This section is intended to make thoroughly clear what is believed to be a
+consequence of the rest of this License.
+
+8. If the distribution and/or use of the Program is restricted in certain
+countries either by patents or by copyrighted interfaces, the original
+copyright holder who places the Program under this License may add an explicit
+geographical distribution limitation excluding those countries, so that
+distribution is permitted only in or among countries not thus excluded. In
+such case, this License incorporates the limitation as if written in the body
+of this License.
+
+9. The Free Software Foundation may publish revised and/or new versions of the
+General Public License from time to time. Such new versions will be similar in
+spirit to the present version, but may differ in detail to address new problems
+or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any later
+version", you have the option of following the terms and conditions either of
+that version or of any later version published by the Free Software Foundation.
+If the Program does not specify a version number of this License, you may
+choose any version ever published by the Free Software Foundation.
+
+10. If you wish to incorporate parts of the Program into other free programs
+whose distribution conditions are different, write to the author to ask for
+permission. For software which is copyrighted by the Free Software Foundation,
+write to the Free Software Foundation; we sometimes make exceptions for this.
+Our decision will be guided by the two goals of preserving the free status of
+all derivatives of our free software and of promoting the sharing and reuse of
+software generally.
+
+NO WARRANTY
+
+11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
+THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE
+STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE
+PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
+PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE,
+YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL
+ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE
+PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
+INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
+BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER
+OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+END OF TERMS AND CONDITIONS
+
+How to Apply These Terms to Your New Programs
+
+If you develop a new program, and you want it to be of the greatest possible
+use to the public, the best way to achieve this is to make it free software
+which everyone can redistribute and change under these terms.
+
+To do so, attach the following notices to the program. It is safest to attach
+them to the start of each source file to most effectively convey the exclusion
+of warranty; and each file should have at least the "copyright" line and a
+pointer to where the full notice is found.
+
+ One line to give the program's name and a brief idea of what it does.
+
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this when it
+starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author Gnomovision comes
+ with ABSOLUTELY NO WARRANTY; for details type 'show w'. This is free
+ software, and you are welcome to redistribute it under certain conditions;
+ type 'show c' for details.
+
+The hypothetical commands 'show w' and 'show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may be
+called something other than 'show w' and 'show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your school,
+if any, to sign a "copyright disclaimer" for the program, if necessary. Here
+is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ 'Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ signature of Ty Coon, 1 April 1989
+
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General Public
+License instead of this License.
+
+
+"CLASSPATH" EXCEPTION TO THE GPL
+
+Certain source files distributed by Oracle America and/or its affiliates are
+subject to the following clarification and special exception to the GPL, but
+only where Oracle has expressly included in the particular source file's header
+the words "Oracle designates this particular file as subject to the "Classpath"
+exception as provided by Oracle in the LICENSE file that accompanied this code."
+
+ Linking this library statically or dynamically with other modules is making
+ a combined work based on this library. Thus, the terms and conditions of
+ the GNU General Public License cover the whole combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent modules,
+ and to copy and distribute the resulting executable under terms of your
+ choice, provided that you also meet, for each linked independent module,
+ the terms and conditions of the license of that module. An independent
+ module is a module which is not derived from or based on this library. If
+ you modify this library, you may extend this exception to your version of
+ the library, but you are not obligated to do so. If you do not wish to do
+ so, delete this exception statement from your version.
diff --git a/java/arm-linux/jni.h b/java/arm-linux/jni.h
new file mode 100644
index 0000000..2e83cb7
--- /dev/null
+++ b/java/arm-linux/jni.h
@@ -0,0 +1,1960 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * We used part of Netscape's Java Runtime Interface (JRI) as the starting
+ * point of our design and implementation.
+ */
+
+/******************************************************************************
+ * Java Runtime Interface
+ * Copyright (c) 1996 Netscape Communications Corporation. All rights reserved.
+ *****************************************************************************/
+
+#ifndef _JAVASOFT_JNI_H_
+#define _JAVASOFT_JNI_H_
+
+#include <stdio.h>
+#include <stdarg.h>
+
+/* jni_md.h contains the machine-dependent typedefs for jbyte, jint
+ and jlong */
+
+#include "jni_md.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * JNI Types
+ */
+
+#ifndef JNI_TYPES_ALREADY_DEFINED_IN_JNI_MD_H
+
+typedef unsigned char jboolean;
+typedef unsigned short jchar;
+typedef short jshort;
+typedef float jfloat;
+typedef double jdouble;
+
+typedef jint jsize;
+
+#ifdef __cplusplus
+
+class _jobject {};
+class _jclass : public _jobject {};
+class _jthrowable : public _jobject {};
+class _jstring : public _jobject {};
+class _jarray : public _jobject {};
+class _jbooleanArray : public _jarray {};
+class _jbyteArray : public _jarray {};
+class _jcharArray : public _jarray {};
+class _jshortArray : public _jarray {};
+class _jintArray : public _jarray {};
+class _jlongArray : public _jarray {};
+class _jfloatArray : public _jarray {};
+class _jdoubleArray : public _jarray {};
+class _jobjectArray : public _jarray {};
+
+typedef _jobject *jobject;
+typedef _jclass *jclass;
+typedef _jthrowable *jthrowable;
+typedef _jstring *jstring;
+typedef _jarray *jarray;
+typedef _jbooleanArray *jbooleanArray;
+typedef _jbyteArray *jbyteArray;
+typedef _jcharArray *jcharArray;
+typedef _jshortArray *jshortArray;
+typedef _jintArray *jintArray;
+typedef _jlongArray *jlongArray;
+typedef _jfloatArray *jfloatArray;
+typedef _jdoubleArray *jdoubleArray;
+typedef _jobjectArray *jobjectArray;
+
+#else
+
+struct _jobject;
+
+typedef struct _jobject *jobject;
+typedef jobject jclass;
+typedef jobject jthrowable;
+typedef jobject jstring;
+typedef jobject jarray;
+typedef jarray jbooleanArray;
+typedef jarray jbyteArray;
+typedef jarray jcharArray;
+typedef jarray jshortArray;
+typedef jarray jintArray;
+typedef jarray jlongArray;
+typedef jarray jfloatArray;
+typedef jarray jdoubleArray;
+typedef jarray jobjectArray;
+
+#endif
+
+typedef jobject jweak;
+
+typedef union jvalue {
+ jboolean z;
+ jbyte b;
+ jchar c;
+ jshort s;
+ jint i;
+ jlong j;
+ jfloat f;
+ jdouble d;
+ jobject l;
+} jvalue;
+
+struct _jfieldID;
+typedef struct _jfieldID *jfieldID;
+
+struct _jmethodID;
+typedef struct _jmethodID *jmethodID;
+
+/* Return values from jobjectRefType */
+typedef enum _jobjectType {
+ JNIInvalidRefType = 0,
+ JNILocalRefType = 1,
+ JNIGlobalRefType = 2,
+ JNIWeakGlobalRefType = 3
+} jobjectRefType;
+
+
+#endif /* JNI_TYPES_ALREADY_DEFINED_IN_JNI_MD_H */
+
+/*
+ * jboolean constants
+ */
+
+#define JNI_FALSE 0
+#define JNI_TRUE 1
+
+/*
+ * possible return values for JNI functions.
+ */
+
+#define JNI_OK 0 /* success */
+#define JNI_ERR (-1) /* unknown error */
+#define JNI_EDETACHED (-2) /* thread detached from the VM */
+#define JNI_EVERSION (-3) /* JNI version error */
+#define JNI_ENOMEM (-4) /* not enough memory */
+#define JNI_EEXIST (-5) /* VM already created */
+#define JNI_EINVAL (-6) /* invalid arguments */
+
+/*
+ * used in ReleaseScalarArrayElements
+ */
+
+#define JNI_COMMIT 1
+#define JNI_ABORT 2
+
+/*
+ * used in RegisterNatives to describe native method name, signature,
+ * and function pointer.
+ */
+
+typedef struct {
+ char *name;
+ char *signature;
+ void *fnPtr;
+} JNINativeMethod;
+
+/*
+ * JNI Native Method Interface.
+ */
+
+struct JNINativeInterface_;
+
+struct JNIEnv_;
+
+#ifdef __cplusplus
+typedef JNIEnv_ JNIEnv;
+#else
+typedef const struct JNINativeInterface_ *JNIEnv;
+#endif
+
+/*
+ * JNI Invocation Interface.
+ */
+
+struct JNIInvokeInterface_;
+
+struct JavaVM_;
+
+#ifdef __cplusplus
+typedef JavaVM_ JavaVM;
+#else
+typedef const struct JNIInvokeInterface_ *JavaVM;
+#endif
+
+struct JNINativeInterface_ {
+ void *reserved0;
+ void *reserved1;
+ void *reserved2;
+
+ void *reserved3;
+ jint (JNICALL *GetVersion)(JNIEnv *env);
+
+ jclass (JNICALL *DefineClass)
+ (JNIEnv *env, const char *name, jobject loader, const jbyte *buf,
+ jsize len);
+ jclass (JNICALL *FindClass)
+ (JNIEnv *env, const char *name);
+
+ jmethodID (JNICALL *FromReflectedMethod)
+ (JNIEnv *env, jobject method);
+ jfieldID (JNICALL *FromReflectedField)
+ (JNIEnv *env, jobject field);
+
+ jobject (JNICALL *ToReflectedMethod)
+ (JNIEnv *env, jclass cls, jmethodID methodID, jboolean isStatic);
+
+ jclass (JNICALL *GetSuperclass)
+ (JNIEnv *env, jclass sub);
+ jboolean (JNICALL *IsAssignableFrom)
+ (JNIEnv *env, jclass sub, jclass sup);
+
+ jobject (JNICALL *ToReflectedField)
+ (JNIEnv *env, jclass cls, jfieldID fieldID, jboolean isStatic);
+
+ jint (JNICALL *Throw)
+ (JNIEnv *env, jthrowable obj);
+ jint (JNICALL *ThrowNew)
+ (JNIEnv *env, jclass clazz, const char *msg);
+ jthrowable (JNICALL *ExceptionOccurred)
+ (JNIEnv *env);
+ void (JNICALL *ExceptionDescribe)
+ (JNIEnv *env);
+ void (JNICALL *ExceptionClear)
+ (JNIEnv *env);
+ void (JNICALL *FatalError)
+ (JNIEnv *env, const char *msg);
+
+ jint (JNICALL *PushLocalFrame)
+ (JNIEnv *env, jint capacity);
+ jobject (JNICALL *PopLocalFrame)
+ (JNIEnv *env, jobject result);
+
+ jobject (JNICALL *NewGlobalRef)
+ (JNIEnv *env, jobject lobj);
+ void (JNICALL *DeleteGlobalRef)
+ (JNIEnv *env, jobject gref);
+ void (JNICALL *DeleteLocalRef)
+ (JNIEnv *env, jobject obj);
+ jboolean (JNICALL *IsSameObject)
+ (JNIEnv *env, jobject obj1, jobject obj2);
+ jobject (JNICALL *NewLocalRef)
+ (JNIEnv *env, jobject ref);
+ jint (JNICALL *EnsureLocalCapacity)
+ (JNIEnv *env, jint capacity);
+
+ jobject (JNICALL *AllocObject)
+ (JNIEnv *env, jclass clazz);
+ jobject (JNICALL *NewObject)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jobject (JNICALL *NewObjectV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jobject (JNICALL *NewObjectA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jclass (JNICALL *GetObjectClass)
+ (JNIEnv *env, jobject obj);
+ jboolean (JNICALL *IsInstanceOf)
+ (JNIEnv *env, jobject obj, jclass clazz);
+
+ jmethodID (JNICALL *GetMethodID)
+ (JNIEnv *env, jclass clazz, const char *name, const char *sig);
+
+ jobject (JNICALL *CallObjectMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jobject (JNICALL *CallObjectMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jobject (JNICALL *CallObjectMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args);
+
+ jboolean (JNICALL *CallBooleanMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jboolean (JNICALL *CallBooleanMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jboolean (JNICALL *CallBooleanMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args);
+
+ jbyte (JNICALL *CallByteMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jbyte (JNICALL *CallByteMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jbyte (JNICALL *CallByteMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ jchar (JNICALL *CallCharMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jchar (JNICALL *CallCharMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jchar (JNICALL *CallCharMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ jshort (JNICALL *CallShortMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jshort (JNICALL *CallShortMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jshort (JNICALL *CallShortMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ jint (JNICALL *CallIntMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jint (JNICALL *CallIntMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jint (JNICALL *CallIntMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ jlong (JNICALL *CallLongMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jlong (JNICALL *CallLongMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jlong (JNICALL *CallLongMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ jfloat (JNICALL *CallFloatMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jfloat (JNICALL *CallFloatMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jfloat (JNICALL *CallFloatMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ jdouble (JNICALL *CallDoubleMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jdouble (JNICALL *CallDoubleMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jdouble (JNICALL *CallDoubleMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ void (JNICALL *CallVoidMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ void (JNICALL *CallVoidMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ void (JNICALL *CallVoidMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args);
+
+ jobject (JNICALL *CallNonvirtualObjectMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jobject (JNICALL *CallNonvirtualObjectMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jobject (JNICALL *CallNonvirtualObjectMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue * args);
+
+ jboolean (JNICALL *CallNonvirtualBooleanMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jboolean (JNICALL *CallNonvirtualBooleanMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jboolean (JNICALL *CallNonvirtualBooleanMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue * args);
+
+ jbyte (JNICALL *CallNonvirtualByteMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jbyte (JNICALL *CallNonvirtualByteMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jbyte (JNICALL *CallNonvirtualByteMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ jchar (JNICALL *CallNonvirtualCharMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jchar (JNICALL *CallNonvirtualCharMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jchar (JNICALL *CallNonvirtualCharMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ jshort (JNICALL *CallNonvirtualShortMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jshort (JNICALL *CallNonvirtualShortMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jshort (JNICALL *CallNonvirtualShortMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ jint (JNICALL *CallNonvirtualIntMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jint (JNICALL *CallNonvirtualIntMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jint (JNICALL *CallNonvirtualIntMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ jlong (JNICALL *CallNonvirtualLongMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jlong (JNICALL *CallNonvirtualLongMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jlong (JNICALL *CallNonvirtualLongMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ jfloat (JNICALL *CallNonvirtualFloatMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jfloat (JNICALL *CallNonvirtualFloatMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jfloat (JNICALL *CallNonvirtualFloatMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ jdouble (JNICALL *CallNonvirtualDoubleMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jdouble (JNICALL *CallNonvirtualDoubleMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jdouble (JNICALL *CallNonvirtualDoubleMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ void (JNICALL *CallNonvirtualVoidMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ void (JNICALL *CallNonvirtualVoidMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ void (JNICALL *CallNonvirtualVoidMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue * args);
+
+ jfieldID (JNICALL *GetFieldID)
+ (JNIEnv *env, jclass clazz, const char *name, const char *sig);
+
+ jobject (JNICALL *GetObjectField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jboolean (JNICALL *GetBooleanField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jbyte (JNICALL *GetByteField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jchar (JNICALL *GetCharField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jshort (JNICALL *GetShortField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jint (JNICALL *GetIntField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jlong (JNICALL *GetLongField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jfloat (JNICALL *GetFloatField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jdouble (JNICALL *GetDoubleField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+
+ void (JNICALL *SetObjectField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jobject val);
+ void (JNICALL *SetBooleanField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jboolean val);
+ void (JNICALL *SetByteField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jbyte val);
+ void (JNICALL *SetCharField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jchar val);
+ void (JNICALL *SetShortField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jshort val);
+ void (JNICALL *SetIntField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jint val);
+ void (JNICALL *SetLongField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jlong val);
+ void (JNICALL *SetFloatField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jfloat val);
+ void (JNICALL *SetDoubleField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jdouble val);
+
+ jmethodID (JNICALL *GetStaticMethodID)
+ (JNIEnv *env, jclass clazz, const char *name, const char *sig);
+
+ jobject (JNICALL *CallStaticObjectMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jobject (JNICALL *CallStaticObjectMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jobject (JNICALL *CallStaticObjectMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jboolean (JNICALL *CallStaticBooleanMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jboolean (JNICALL *CallStaticBooleanMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jboolean (JNICALL *CallStaticBooleanMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jbyte (JNICALL *CallStaticByteMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jbyte (JNICALL *CallStaticByteMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jbyte (JNICALL *CallStaticByteMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jchar (JNICALL *CallStaticCharMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jchar (JNICALL *CallStaticCharMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jchar (JNICALL *CallStaticCharMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jshort (JNICALL *CallStaticShortMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jshort (JNICALL *CallStaticShortMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jshort (JNICALL *CallStaticShortMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jint (JNICALL *CallStaticIntMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jint (JNICALL *CallStaticIntMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jint (JNICALL *CallStaticIntMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jlong (JNICALL *CallStaticLongMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jlong (JNICALL *CallStaticLongMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jlong (JNICALL *CallStaticLongMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jfloat (JNICALL *CallStaticFloatMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jfloat (JNICALL *CallStaticFloatMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jfloat (JNICALL *CallStaticFloatMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jdouble (JNICALL *CallStaticDoubleMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jdouble (JNICALL *CallStaticDoubleMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jdouble (JNICALL *CallStaticDoubleMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ void (JNICALL *CallStaticVoidMethod)
+ (JNIEnv *env, jclass cls, jmethodID methodID, ...);
+ void (JNICALL *CallStaticVoidMethodV)
+ (JNIEnv *env, jclass cls, jmethodID methodID, va_list args);
+ void (JNICALL *CallStaticVoidMethodA)
+ (JNIEnv *env, jclass cls, jmethodID methodID, const jvalue * args);
+
+ jfieldID (JNICALL *GetStaticFieldID)
+ (JNIEnv *env, jclass clazz, const char *name, const char *sig);
+ jobject (JNICALL *GetStaticObjectField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jboolean (JNICALL *GetStaticBooleanField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jbyte (JNICALL *GetStaticByteField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jchar (JNICALL *GetStaticCharField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jshort (JNICALL *GetStaticShortField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jint (JNICALL *GetStaticIntField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jlong (JNICALL *GetStaticLongField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jfloat (JNICALL *GetStaticFloatField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jdouble (JNICALL *GetStaticDoubleField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+
+ void (JNICALL *SetStaticObjectField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value);
+ void (JNICALL *SetStaticBooleanField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jboolean value);
+ void (JNICALL *SetStaticByteField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jbyte value);
+ void (JNICALL *SetStaticCharField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jchar value);
+ void (JNICALL *SetStaticShortField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jshort value);
+ void (JNICALL *SetStaticIntField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jint value);
+ void (JNICALL *SetStaticLongField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jlong value);
+ void (JNICALL *SetStaticFloatField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jfloat value);
+ void (JNICALL *SetStaticDoubleField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jdouble value);
+
+ jstring (JNICALL *NewString)
+ (JNIEnv *env, const jchar *unicode, jsize len);
+ jsize (JNICALL *GetStringLength)
+ (JNIEnv *env, jstring str);
+ const jchar *(JNICALL *GetStringChars)
+ (JNIEnv *env, jstring str, jboolean *isCopy);
+ void (JNICALL *ReleaseStringChars)
+ (JNIEnv *env, jstring str, const jchar *chars);
+
+ jstring (JNICALL *NewStringUTF)
+ (JNIEnv *env, const char *utf);
+ jsize (JNICALL *GetStringUTFLength)
+ (JNIEnv *env, jstring str);
+ const char* (JNICALL *GetStringUTFChars)
+ (JNIEnv *env, jstring str, jboolean *isCopy);
+ void (JNICALL *ReleaseStringUTFChars)
+ (JNIEnv *env, jstring str, const char* chars);
+
+
+ jsize (JNICALL *GetArrayLength)
+ (JNIEnv *env, jarray array);
+
+ jobjectArray (JNICALL *NewObjectArray)
+ (JNIEnv *env, jsize len, jclass clazz, jobject init);
+ jobject (JNICALL *GetObjectArrayElement)
+ (JNIEnv *env, jobjectArray array, jsize index);
+ void (JNICALL *SetObjectArrayElement)
+ (JNIEnv *env, jobjectArray array, jsize index, jobject val);
+
+ jbooleanArray (JNICALL *NewBooleanArray)
+ (JNIEnv *env, jsize len);
+ jbyteArray (JNICALL *NewByteArray)
+ (JNIEnv *env, jsize len);
+ jcharArray (JNICALL *NewCharArray)
+ (JNIEnv *env, jsize len);
+ jshortArray (JNICALL *NewShortArray)
+ (JNIEnv *env, jsize len);
+ jintArray (JNICALL *NewIntArray)
+ (JNIEnv *env, jsize len);
+ jlongArray (JNICALL *NewLongArray)
+ (JNIEnv *env, jsize len);
+ jfloatArray (JNICALL *NewFloatArray)
+ (JNIEnv *env, jsize len);
+ jdoubleArray (JNICALL *NewDoubleArray)
+ (JNIEnv *env, jsize len);
+
+ jboolean * (JNICALL *GetBooleanArrayElements)
+ (JNIEnv *env, jbooleanArray array, jboolean *isCopy);
+ jbyte * (JNICALL *GetByteArrayElements)
+ (JNIEnv *env, jbyteArray array, jboolean *isCopy);
+ jchar * (JNICALL *GetCharArrayElements)
+ (JNIEnv *env, jcharArray array, jboolean *isCopy);
+ jshort * (JNICALL *GetShortArrayElements)
+ (JNIEnv *env, jshortArray array, jboolean *isCopy);
+ jint * (JNICALL *GetIntArrayElements)
+ (JNIEnv *env, jintArray array, jboolean *isCopy);
+ jlong * (JNICALL *GetLongArrayElements)
+ (JNIEnv *env, jlongArray array, jboolean *isCopy);
+ jfloat * (JNICALL *GetFloatArrayElements)
+ (JNIEnv *env, jfloatArray array, jboolean *isCopy);
+ jdouble * (JNICALL *GetDoubleArrayElements)
+ (JNIEnv *env, jdoubleArray array, jboolean *isCopy);
+
+ void (JNICALL *ReleaseBooleanArrayElements)
+ (JNIEnv *env, jbooleanArray array, jboolean *elems, jint mode);
+ void (JNICALL *ReleaseByteArrayElements)
+ (JNIEnv *env, jbyteArray array, jbyte *elems, jint mode);
+ void (JNICALL *ReleaseCharArrayElements)
+ (JNIEnv *env, jcharArray array, jchar *elems, jint mode);
+ void (JNICALL *ReleaseShortArrayElements)
+ (JNIEnv *env, jshortArray array, jshort *elems, jint mode);
+ void (JNICALL *ReleaseIntArrayElements)
+ (JNIEnv *env, jintArray array, jint *elems, jint mode);
+ void (JNICALL *ReleaseLongArrayElements)
+ (JNIEnv *env, jlongArray array, jlong *elems, jint mode);
+ void (JNICALL *ReleaseFloatArrayElements)
+ (JNIEnv *env, jfloatArray array, jfloat *elems, jint mode);
+ void (JNICALL *ReleaseDoubleArrayElements)
+ (JNIEnv *env, jdoubleArray array, jdouble *elems, jint mode);
+
+ void (JNICALL *GetBooleanArrayRegion)
+ (JNIEnv *env, jbooleanArray array, jsize start, jsize l, jboolean *buf);
+ void (JNICALL *GetByteArrayRegion)
+ (JNIEnv *env, jbyteArray array, jsize start, jsize len, jbyte *buf);
+ void (JNICALL *GetCharArrayRegion)
+ (JNIEnv *env, jcharArray array, jsize start, jsize len, jchar *buf);
+ void (JNICALL *GetShortArrayRegion)
+ (JNIEnv *env, jshortArray array, jsize start, jsize len, jshort *buf);
+ void (JNICALL *GetIntArrayRegion)
+ (JNIEnv *env, jintArray array, jsize start, jsize len, jint *buf);
+ void (JNICALL *GetLongArrayRegion)
+ (JNIEnv *env, jlongArray array, jsize start, jsize len, jlong *buf);
+ void (JNICALL *GetFloatArrayRegion)
+ (JNIEnv *env, jfloatArray array, jsize start, jsize len, jfloat *buf);
+ void (JNICALL *GetDoubleArrayRegion)
+ (JNIEnv *env, jdoubleArray array, jsize start, jsize len, jdouble *buf);
+
+ void (JNICALL *SetBooleanArrayRegion)
+ (JNIEnv *env, jbooleanArray array, jsize start, jsize l, const jboolean *buf);
+ void (JNICALL *SetByteArrayRegion)
+ (JNIEnv *env, jbyteArray array, jsize start, jsize len, const jbyte *buf);
+ void (JNICALL *SetCharArrayRegion)
+ (JNIEnv *env, jcharArray array, jsize start, jsize len, const jchar *buf);
+ void (JNICALL *SetShortArrayRegion)
+ (JNIEnv *env, jshortArray array, jsize start, jsize len, const jshort *buf);
+ void (JNICALL *SetIntArrayRegion)
+ (JNIEnv *env, jintArray array, jsize start, jsize len, const jint *buf);
+ void (JNICALL *SetLongArrayRegion)
+ (JNIEnv *env, jlongArray array, jsize start, jsize len, const jlong *buf);
+ void (JNICALL *SetFloatArrayRegion)
+ (JNIEnv *env, jfloatArray array, jsize start, jsize len, const jfloat *buf);
+ void (JNICALL *SetDoubleArrayRegion)
+ (JNIEnv *env, jdoubleArray array, jsize start, jsize len, const jdouble *buf);
+
+ jint (JNICALL *RegisterNatives)
+ (JNIEnv *env, jclass clazz, const JNINativeMethod *methods,
+ jint nMethods);
+ jint (JNICALL *UnregisterNatives)
+ (JNIEnv *env, jclass clazz);
+
+ jint (JNICALL *MonitorEnter)
+ (JNIEnv *env, jobject obj);
+ jint (JNICALL *MonitorExit)
+ (JNIEnv *env, jobject obj);
+
+ jint (JNICALL *GetJavaVM)
+ (JNIEnv *env, JavaVM **vm);
+
+ void (JNICALL *GetStringRegion)
+ (JNIEnv *env, jstring str, jsize start, jsize len, jchar *buf);
+ void (JNICALL *GetStringUTFRegion)
+ (JNIEnv *env, jstring str, jsize start, jsize len, char *buf);
+
+ void * (JNICALL *GetPrimitiveArrayCritical)
+ (JNIEnv *env, jarray array, jboolean *isCopy);
+ void (JNICALL *ReleasePrimitiveArrayCritical)
+ (JNIEnv *env, jarray array, void *carray, jint mode);
+
+ const jchar * (JNICALL *GetStringCritical)
+ (JNIEnv *env, jstring string, jboolean *isCopy);
+ void (JNICALL *ReleaseStringCritical)
+ (JNIEnv *env, jstring string, const jchar *cstring);
+
+ jweak (JNICALL *NewWeakGlobalRef)
+ (JNIEnv *env, jobject obj);
+ void (JNICALL *DeleteWeakGlobalRef)
+ (JNIEnv *env, jweak ref);
+
+ jboolean (JNICALL *ExceptionCheck)
+ (JNIEnv *env);
+
+ jobject (JNICALL *NewDirectByteBuffer)
+ (JNIEnv* env, void* address, jlong capacity);
+ void* (JNICALL *GetDirectBufferAddress)
+ (JNIEnv* env, jobject buf);
+ jlong (JNICALL *GetDirectBufferCapacity)
+ (JNIEnv* env, jobject buf);
+
+ /* New JNI 1.6 Features */
+
+ jobjectRefType (JNICALL *GetObjectRefType)
+ (JNIEnv* env, jobject obj);
+};
+
+/*
+ * We use inlined functions for C++ so that programmers can write:
+ *
+ * env->FindClass("java/lang/String")
+ *
+ * in C++ rather than:
+ *
+ * (*env)->FindClass(env, "java/lang/String")
+ *
+ * in C.
+ */
+
+struct JNIEnv_ {
+ const struct JNINativeInterface_ *functions;
+#ifdef __cplusplus
+
+ jint GetVersion() {
+ return functions->GetVersion(this);
+ }
+ jclass DefineClass(const char *name, jobject loader, const jbyte *buf,
+ jsize len) {
+ return functions->DefineClass(this, name, loader, buf, len);
+ }
+ jclass FindClass(const char *name) {
+ return functions->FindClass(this, name);
+ }
+ jmethodID FromReflectedMethod(jobject method) {
+ return functions->FromReflectedMethod(this,method);
+ }
+ jfieldID FromReflectedField(jobject field) {
+ return functions->FromReflectedField(this,field);
+ }
+
+ jobject ToReflectedMethod(jclass cls, jmethodID methodID, jboolean isStatic) {
+ return functions->ToReflectedMethod(this, cls, methodID, isStatic);
+ }
+
+ jclass GetSuperclass(jclass sub) {
+ return functions->GetSuperclass(this, sub);
+ }
+ jboolean IsAssignableFrom(jclass sub, jclass sup) {
+ return functions->IsAssignableFrom(this, sub, sup);
+ }
+
+ jobject ToReflectedField(jclass cls, jfieldID fieldID, jboolean isStatic) {
+ return functions->ToReflectedField(this,cls,fieldID,isStatic);
+ }
+
+ jint Throw(jthrowable obj) {
+ return functions->Throw(this, obj);
+ }
+ jint ThrowNew(jclass clazz, const char *msg) {
+ return functions->ThrowNew(this, clazz, msg);
+ }
+ jthrowable ExceptionOccurred() {
+ return functions->ExceptionOccurred(this);
+ }
+ void ExceptionDescribe() {
+ functions->ExceptionDescribe(this);
+ }
+ void ExceptionClear() {
+ functions->ExceptionClear(this);
+ }
+ void FatalError(const char *msg) {
+ functions->FatalError(this, msg);
+ }
+
+ jint PushLocalFrame(jint capacity) {
+ return functions->PushLocalFrame(this,capacity);
+ }
+ jobject PopLocalFrame(jobject result) {
+ return functions->PopLocalFrame(this,result);
+ }
+
+ jobject NewGlobalRef(jobject lobj) {
+ return functions->NewGlobalRef(this,lobj);
+ }
+ void DeleteGlobalRef(jobject gref) {
+ functions->DeleteGlobalRef(this,gref);
+ }
+ void DeleteLocalRef(jobject obj) {
+ functions->DeleteLocalRef(this, obj);
+ }
+
+ jboolean IsSameObject(jobject obj1, jobject obj2) {
+ return functions->IsSameObject(this,obj1,obj2);
+ }
+
+ jobject NewLocalRef(jobject ref) {
+ return functions->NewLocalRef(this,ref);
+ }
+ jint EnsureLocalCapacity(jint capacity) {
+ return functions->EnsureLocalCapacity(this,capacity);
+ }
+
+ jobject AllocObject(jclass clazz) {
+ return functions->AllocObject(this,clazz);
+ }
+ jobject NewObject(jclass clazz, jmethodID methodID, ...) {
+ va_list args;
+ jobject result;
+ va_start(args, methodID);
+ result = functions->NewObjectV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jobject NewObjectV(jclass clazz, jmethodID methodID,
+ va_list args) {
+ return functions->NewObjectV(this,clazz,methodID,args);
+ }
+ jobject NewObjectA(jclass clazz, jmethodID methodID,
+ const jvalue *args) {
+ return functions->NewObjectA(this,clazz,methodID,args);
+ }
+
+ jclass GetObjectClass(jobject obj) {
+ return functions->GetObjectClass(this,obj);
+ }
+ jboolean IsInstanceOf(jobject obj, jclass clazz) {
+ return functions->IsInstanceOf(this,obj,clazz);
+ }
+
+ jmethodID GetMethodID(jclass clazz, const char *name,
+ const char *sig) {
+ return functions->GetMethodID(this,clazz,name,sig);
+ }
+
+ jobject CallObjectMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jobject result;
+ va_start(args,methodID);
+ result = functions->CallObjectMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jobject CallObjectMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallObjectMethodV(this,obj,methodID,args);
+ }
+ jobject CallObjectMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallObjectMethodA(this,obj,methodID,args);
+ }
+
+ jboolean CallBooleanMethod(jobject obj,
+ jmethodID methodID, ...) {
+ va_list args;
+ jboolean result;
+ va_start(args,methodID);
+ result = functions->CallBooleanMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jboolean CallBooleanMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallBooleanMethodV(this,obj,methodID,args);
+ }
+ jboolean CallBooleanMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallBooleanMethodA(this,obj,methodID, args);
+ }
+
+ jbyte CallByteMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jbyte result;
+ va_start(args,methodID);
+ result = functions->CallByteMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jbyte CallByteMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallByteMethodV(this,obj,methodID,args);
+ }
+ jbyte CallByteMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallByteMethodA(this,obj,methodID,args);
+ }
+
+ jchar CallCharMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jchar result;
+ va_start(args,methodID);
+ result = functions->CallCharMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jchar CallCharMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallCharMethodV(this,obj,methodID,args);
+ }
+ jchar CallCharMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallCharMethodA(this,obj,methodID,args);
+ }
+
+ jshort CallShortMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jshort result;
+ va_start(args,methodID);
+ result = functions->CallShortMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jshort CallShortMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallShortMethodV(this,obj,methodID,args);
+ }
+ jshort CallShortMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallShortMethodA(this,obj,methodID,args);
+ }
+
+ jint CallIntMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jint result;
+ va_start(args,methodID);
+ result = functions->CallIntMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jint CallIntMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallIntMethodV(this,obj,methodID,args);
+ }
+ jint CallIntMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallIntMethodA(this,obj,methodID,args);
+ }
+
+ jlong CallLongMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jlong result;
+ va_start(args,methodID);
+ result = functions->CallLongMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jlong CallLongMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallLongMethodV(this,obj,methodID,args);
+ }
+ jlong CallLongMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallLongMethodA(this,obj,methodID,args);
+ }
+
+ jfloat CallFloatMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jfloat result;
+ va_start(args,methodID);
+ result = functions->CallFloatMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jfloat CallFloatMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallFloatMethodV(this,obj,methodID,args);
+ }
+ jfloat CallFloatMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallFloatMethodA(this,obj,methodID,args);
+ }
+
+ jdouble CallDoubleMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jdouble result;
+ va_start(args,methodID);
+ result = functions->CallDoubleMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jdouble CallDoubleMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallDoubleMethodV(this,obj,methodID,args);
+ }
+ jdouble CallDoubleMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallDoubleMethodA(this,obj,methodID,args);
+ }
+
+ void CallVoidMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ va_start(args,methodID);
+ functions->CallVoidMethodV(this,obj,methodID,args);
+ va_end(args);
+ }
+ void CallVoidMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ functions->CallVoidMethodV(this,obj,methodID,args);
+ }
+ void CallVoidMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ functions->CallVoidMethodA(this,obj,methodID,args);
+ }
+
+ jobject CallNonvirtualObjectMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jobject result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualObjectMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jobject CallNonvirtualObjectMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualObjectMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jobject CallNonvirtualObjectMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualObjectMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jboolean CallNonvirtualBooleanMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jboolean result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualBooleanMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jboolean CallNonvirtualBooleanMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualBooleanMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jboolean CallNonvirtualBooleanMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualBooleanMethodA(this,obj,clazz,
+ methodID, args);
+ }
+
+ jbyte CallNonvirtualByteMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jbyte result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualByteMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jbyte CallNonvirtualByteMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualByteMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jbyte CallNonvirtualByteMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualByteMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jchar CallNonvirtualCharMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jchar result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualCharMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jchar CallNonvirtualCharMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualCharMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jchar CallNonvirtualCharMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualCharMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jshort CallNonvirtualShortMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jshort result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualShortMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jshort CallNonvirtualShortMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualShortMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jshort CallNonvirtualShortMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualShortMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jint CallNonvirtualIntMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jint result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualIntMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jint CallNonvirtualIntMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualIntMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jint CallNonvirtualIntMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualIntMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jlong CallNonvirtualLongMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jlong result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualLongMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jlong CallNonvirtualLongMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualLongMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jlong CallNonvirtualLongMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualLongMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jfloat CallNonvirtualFloatMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jfloat result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualFloatMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jfloat CallNonvirtualFloatMethodV(jobject obj, jclass clazz,
+ jmethodID methodID,
+ va_list args) {
+ return functions->CallNonvirtualFloatMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jfloat CallNonvirtualFloatMethodA(jobject obj, jclass clazz,
+ jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallNonvirtualFloatMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jdouble CallNonvirtualDoubleMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jdouble result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualDoubleMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jdouble CallNonvirtualDoubleMethodV(jobject obj, jclass clazz,
+ jmethodID methodID,
+ va_list args) {
+ return functions->CallNonvirtualDoubleMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jdouble CallNonvirtualDoubleMethodA(jobject obj, jclass clazz,
+ jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallNonvirtualDoubleMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ void CallNonvirtualVoidMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ va_start(args,methodID);
+ functions->CallNonvirtualVoidMethodV(this,obj,clazz,methodID,args);
+ va_end(args);
+ }
+ void CallNonvirtualVoidMethodV(jobject obj, jclass clazz,
+ jmethodID methodID,
+ va_list args) {
+ functions->CallNonvirtualVoidMethodV(this,obj,clazz,methodID,args);
+ }
+ void CallNonvirtualVoidMethodA(jobject obj, jclass clazz,
+ jmethodID methodID,
+ const jvalue * args) {
+ functions->CallNonvirtualVoidMethodA(this,obj,clazz,methodID,args);
+ }
+
+ jfieldID GetFieldID(jclass clazz, const char *name,
+ const char *sig) {
+ return functions->GetFieldID(this,clazz,name,sig);
+ }
+
+ jobject GetObjectField(jobject obj, jfieldID fieldID) {
+ return functions->GetObjectField(this,obj,fieldID);
+ }
+ jboolean GetBooleanField(jobject obj, jfieldID fieldID) {
+ return functions->GetBooleanField(this,obj,fieldID);
+ }
+ jbyte GetByteField(jobject obj, jfieldID fieldID) {
+ return functions->GetByteField(this,obj,fieldID);
+ }
+ jchar GetCharField(jobject obj, jfieldID fieldID) {
+ return functions->GetCharField(this,obj,fieldID);
+ }
+ jshort GetShortField(jobject obj, jfieldID fieldID) {
+ return functions->GetShortField(this,obj,fieldID);
+ }
+ jint GetIntField(jobject obj, jfieldID fieldID) {
+ return functions->GetIntField(this,obj,fieldID);
+ }
+ jlong GetLongField(jobject obj, jfieldID fieldID) {
+ return functions->GetLongField(this,obj,fieldID);
+ }
+ jfloat GetFloatField(jobject obj, jfieldID fieldID) {
+ return functions->GetFloatField(this,obj,fieldID);
+ }
+ jdouble GetDoubleField(jobject obj, jfieldID fieldID) {
+ return functions->GetDoubleField(this,obj,fieldID);
+ }
+
+ void SetObjectField(jobject obj, jfieldID fieldID, jobject val) {
+ functions->SetObjectField(this,obj,fieldID,val);
+ }
+ void SetBooleanField(jobject obj, jfieldID fieldID,
+ jboolean val) {
+ functions->SetBooleanField(this,obj,fieldID,val);
+ }
+ void SetByteField(jobject obj, jfieldID fieldID,
+ jbyte val) {
+ functions->SetByteField(this,obj,fieldID,val);
+ }
+ void SetCharField(jobject obj, jfieldID fieldID,
+ jchar val) {
+ functions->SetCharField(this,obj,fieldID,val);
+ }
+ void SetShortField(jobject obj, jfieldID fieldID,
+ jshort val) {
+ functions->SetShortField(this,obj,fieldID,val);
+ }
+ void SetIntField(jobject obj, jfieldID fieldID,
+ jint val) {
+ functions->SetIntField(this,obj,fieldID,val);
+ }
+ void SetLongField(jobject obj, jfieldID fieldID,
+ jlong val) {
+ functions->SetLongField(this,obj,fieldID,val);
+ }
+ void SetFloatField(jobject obj, jfieldID fieldID,
+ jfloat val) {
+ functions->SetFloatField(this,obj,fieldID,val);
+ }
+ void SetDoubleField(jobject obj, jfieldID fieldID,
+ jdouble val) {
+ functions->SetDoubleField(this,obj,fieldID,val);
+ }
+
+ jmethodID GetStaticMethodID(jclass clazz, const char *name,
+ const char *sig) {
+ return functions->GetStaticMethodID(this,clazz,name,sig);
+ }
+
+ jobject CallStaticObjectMethod(jclass clazz, jmethodID methodID,
+ ...) {
+ va_list args;
+ jobject result;
+ va_start(args,methodID);
+ result = functions->CallStaticObjectMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jobject CallStaticObjectMethodV(jclass clazz, jmethodID methodID,
+ va_list args) {
+ return functions->CallStaticObjectMethodV(this,clazz,methodID,args);
+ }
+ jobject CallStaticObjectMethodA(jclass clazz, jmethodID methodID,
+ const jvalue *args) {
+ return functions->CallStaticObjectMethodA(this,clazz,methodID,args);
+ }
+
+ jboolean CallStaticBooleanMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jboolean result;
+ va_start(args,methodID);
+ result = functions->CallStaticBooleanMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jboolean CallStaticBooleanMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticBooleanMethodV(this,clazz,methodID,args);
+ }
+ jboolean CallStaticBooleanMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticBooleanMethodA(this,clazz,methodID,args);
+ }
+
+ jbyte CallStaticByteMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jbyte result;
+ va_start(args,methodID);
+ result = functions->CallStaticByteMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jbyte CallStaticByteMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticByteMethodV(this,clazz,methodID,args);
+ }
+ jbyte CallStaticByteMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticByteMethodA(this,clazz,methodID,args);
+ }
+
+ jchar CallStaticCharMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jchar result;
+ va_start(args,methodID);
+ result = functions->CallStaticCharMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jchar CallStaticCharMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticCharMethodV(this,clazz,methodID,args);
+ }
+ jchar CallStaticCharMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticCharMethodA(this,clazz,methodID,args);
+ }
+
+ jshort CallStaticShortMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jshort result;
+ va_start(args,methodID);
+ result = functions->CallStaticShortMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jshort CallStaticShortMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticShortMethodV(this,clazz,methodID,args);
+ }
+ jshort CallStaticShortMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticShortMethodA(this,clazz,methodID,args);
+ }
+
+ jint CallStaticIntMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jint result;
+ va_start(args,methodID);
+ result = functions->CallStaticIntMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jint CallStaticIntMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticIntMethodV(this,clazz,methodID,args);
+ }
+ jint CallStaticIntMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticIntMethodA(this,clazz,methodID,args);
+ }
+
+ jlong CallStaticLongMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jlong result;
+ va_start(args,methodID);
+ result = functions->CallStaticLongMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jlong CallStaticLongMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticLongMethodV(this,clazz,methodID,args);
+ }
+ jlong CallStaticLongMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticLongMethodA(this,clazz,methodID,args);
+ }
+
+ jfloat CallStaticFloatMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jfloat result;
+ va_start(args,methodID);
+ result = functions->CallStaticFloatMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jfloat CallStaticFloatMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticFloatMethodV(this,clazz,methodID,args);
+ }
+ jfloat CallStaticFloatMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticFloatMethodA(this,clazz,methodID,args);
+ }
+
+ jdouble CallStaticDoubleMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jdouble result;
+ va_start(args,methodID);
+ result = functions->CallStaticDoubleMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jdouble CallStaticDoubleMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticDoubleMethodV(this,clazz,methodID,args);
+ }
+ jdouble CallStaticDoubleMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticDoubleMethodA(this,clazz,methodID,args);
+ }
+
+ void CallStaticVoidMethod(jclass cls, jmethodID methodID, ...) {
+ va_list args;
+ va_start(args,methodID);
+ functions->CallStaticVoidMethodV(this,cls,methodID,args);
+ va_end(args);
+ }
+ void CallStaticVoidMethodV(jclass cls, jmethodID methodID,
+ va_list args) {
+ functions->CallStaticVoidMethodV(this,cls,methodID,args);
+ }
+ void CallStaticVoidMethodA(jclass cls, jmethodID methodID,
+ const jvalue * args) {
+ functions->CallStaticVoidMethodA(this,cls,methodID,args);
+ }
+
+ jfieldID GetStaticFieldID(jclass clazz, const char *name,
+ const char *sig) {
+ return functions->GetStaticFieldID(this,clazz,name,sig);
+ }
+ jobject GetStaticObjectField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticObjectField(this,clazz,fieldID);
+ }
+ jboolean GetStaticBooleanField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticBooleanField(this,clazz,fieldID);
+ }
+ jbyte GetStaticByteField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticByteField(this,clazz,fieldID);
+ }
+ jchar GetStaticCharField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticCharField(this,clazz,fieldID);
+ }
+ jshort GetStaticShortField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticShortField(this,clazz,fieldID);
+ }
+ jint GetStaticIntField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticIntField(this,clazz,fieldID);
+ }
+ jlong GetStaticLongField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticLongField(this,clazz,fieldID);
+ }
+ jfloat GetStaticFloatField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticFloatField(this,clazz,fieldID);
+ }
+ jdouble GetStaticDoubleField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticDoubleField(this,clazz,fieldID);
+ }
+
+ void SetStaticObjectField(jclass clazz, jfieldID fieldID,
+ jobject value) {
+ functions->SetStaticObjectField(this,clazz,fieldID,value);
+ }
+ void SetStaticBooleanField(jclass clazz, jfieldID fieldID,
+ jboolean value) {
+ functions->SetStaticBooleanField(this,clazz,fieldID,value);
+ }
+ void SetStaticByteField(jclass clazz, jfieldID fieldID,
+ jbyte value) {
+ functions->SetStaticByteField(this,clazz,fieldID,value);
+ }
+ void SetStaticCharField(jclass clazz, jfieldID fieldID,
+ jchar value) {
+ functions->SetStaticCharField(this,clazz,fieldID,value);
+ }
+ void SetStaticShortField(jclass clazz, jfieldID fieldID,
+ jshort value) {
+ functions->SetStaticShortField(this,clazz,fieldID,value);
+ }
+ void SetStaticIntField(jclass clazz, jfieldID fieldID,
+ jint value) {
+ functions->SetStaticIntField(this,clazz,fieldID,value);
+ }
+ void SetStaticLongField(jclass clazz, jfieldID fieldID,
+ jlong value) {
+ functions->SetStaticLongField(this,clazz,fieldID,value);
+ }
+ void SetStaticFloatField(jclass clazz, jfieldID fieldID,
+ jfloat value) {
+ functions->SetStaticFloatField(this,clazz,fieldID,value);
+ }
+ void SetStaticDoubleField(jclass clazz, jfieldID fieldID,
+ jdouble value) {
+ functions->SetStaticDoubleField(this,clazz,fieldID,value);
+ }
+
+ jstring NewString(const jchar *unicode, jsize len) {
+ return functions->NewString(this,unicode,len);
+ }
+ jsize GetStringLength(jstring str) {
+ return functions->GetStringLength(this,str);
+ }
+ const jchar *GetStringChars(jstring str, jboolean *isCopy) {
+ return functions->GetStringChars(this,str,isCopy);
+ }
+ void ReleaseStringChars(jstring str, const jchar *chars) {
+ functions->ReleaseStringChars(this,str,chars);
+ }
+
+ jstring NewStringUTF(const char *utf) {
+ return functions->NewStringUTF(this,utf);
+ }
+ jsize GetStringUTFLength(jstring str) {
+ return functions->GetStringUTFLength(this,str);
+ }
+ const char* GetStringUTFChars(jstring str, jboolean *isCopy) {
+ return functions->GetStringUTFChars(this,str,isCopy);
+ }
+ void ReleaseStringUTFChars(jstring str, const char* chars) {
+ functions->ReleaseStringUTFChars(this,str,chars);
+ }
+
+ jsize GetArrayLength(jarray array) {
+ return functions->GetArrayLength(this,array);
+ }
+
+ jobjectArray NewObjectArray(jsize len, jclass clazz,
+ jobject init) {
+ return functions->NewObjectArray(this,len,clazz,init);
+ }
+ jobject GetObjectArrayElement(jobjectArray array, jsize index) {
+ return functions->GetObjectArrayElement(this,array,index);
+ }
+ void SetObjectArrayElement(jobjectArray array, jsize index,
+ jobject val) {
+ functions->SetObjectArrayElement(this,array,index,val);
+ }
+
+ jbooleanArray NewBooleanArray(jsize len) {
+ return functions->NewBooleanArray(this,len);
+ }
+ jbyteArray NewByteArray(jsize len) {
+ return functions->NewByteArray(this,len);
+ }
+ jcharArray NewCharArray(jsize len) {
+ return functions->NewCharArray(this,len);
+ }
+ jshortArray NewShortArray(jsize len) {
+ return functions->NewShortArray(this,len);
+ }
+ jintArray NewIntArray(jsize len) {
+ return functions->NewIntArray(this,len);
+ }
+ jlongArray NewLongArray(jsize len) {
+ return functions->NewLongArray(this,len);
+ }
+ jfloatArray NewFloatArray(jsize len) {
+ return functions->NewFloatArray(this,len);
+ }
+ jdoubleArray NewDoubleArray(jsize len) {
+ return functions->NewDoubleArray(this,len);
+ }
+
+ jboolean * GetBooleanArrayElements(jbooleanArray array, jboolean *isCopy) {
+ return functions->GetBooleanArrayElements(this,array,isCopy);
+ }
+ jbyte * GetByteArrayElements(jbyteArray array, jboolean *isCopy) {
+ return functions->GetByteArrayElements(this,array,isCopy);
+ }
+ jchar * GetCharArrayElements(jcharArray array, jboolean *isCopy) {
+ return functions->GetCharArrayElements(this,array,isCopy);
+ }
+ jshort * GetShortArrayElements(jshortArray array, jboolean *isCopy) {
+ return functions->GetShortArrayElements(this,array,isCopy);
+ }
+ jint * GetIntArrayElements(jintArray array, jboolean *isCopy) {
+ return functions->GetIntArrayElements(this,array,isCopy);
+ }
+ jlong * GetLongArrayElements(jlongArray array, jboolean *isCopy) {
+ return functions->GetLongArrayElements(this,array,isCopy);
+ }
+ jfloat * GetFloatArrayElements(jfloatArray array, jboolean *isCopy) {
+ return functions->GetFloatArrayElements(this,array,isCopy);
+ }
+ jdouble * GetDoubleArrayElements(jdoubleArray array, jboolean *isCopy) {
+ return functions->GetDoubleArrayElements(this,array,isCopy);
+ }
+
+ void ReleaseBooleanArrayElements(jbooleanArray array,
+ jboolean *elems,
+ jint mode) {
+ functions->ReleaseBooleanArrayElements(this,array,elems,mode);
+ }
+ void ReleaseByteArrayElements(jbyteArray array,
+ jbyte *elems,
+ jint mode) {
+ functions->ReleaseByteArrayElements(this,array,elems,mode);
+ }
+ void ReleaseCharArrayElements(jcharArray array,
+ jchar *elems,
+ jint mode) {
+ functions->ReleaseCharArrayElements(this,array,elems,mode);
+ }
+ void ReleaseShortArrayElements(jshortArray array,
+ jshort *elems,
+ jint mode) {
+ functions->ReleaseShortArrayElements(this,array,elems,mode);
+ }
+ void ReleaseIntArrayElements(jintArray array,
+ jint *elems,
+ jint mode) {
+ functions->ReleaseIntArrayElements(this,array,elems,mode);
+ }
+ void ReleaseLongArrayElements(jlongArray array,
+ jlong *elems,
+ jint mode) {
+ functions->ReleaseLongArrayElements(this,array,elems,mode);
+ }
+ void ReleaseFloatArrayElements(jfloatArray array,
+ jfloat *elems,
+ jint mode) {
+ functions->ReleaseFloatArrayElements(this,array,elems,mode);
+ }
+ void ReleaseDoubleArrayElements(jdoubleArray array,
+ jdouble *elems,
+ jint mode) {
+ functions->ReleaseDoubleArrayElements(this,array,elems,mode);
+ }
+
+ void GetBooleanArrayRegion(jbooleanArray array,
+ jsize start, jsize len, jboolean *buf) {
+ functions->GetBooleanArrayRegion(this,array,start,len,buf);
+ }
+ void GetByteArrayRegion(jbyteArray array,
+ jsize start, jsize len, jbyte *buf) {
+ functions->GetByteArrayRegion(this,array,start,len,buf);
+ }
+ void GetCharArrayRegion(jcharArray array,
+ jsize start, jsize len, jchar *buf) {
+ functions->GetCharArrayRegion(this,array,start,len,buf);
+ }
+ void GetShortArrayRegion(jshortArray array,
+ jsize start, jsize len, jshort *buf) {
+ functions->GetShortArrayRegion(this,array,start,len,buf);
+ }
+ void GetIntArrayRegion(jintArray array,
+ jsize start, jsize len, jint *buf) {
+ functions->GetIntArrayRegion(this,array,start,len,buf);
+ }
+ void GetLongArrayRegion(jlongArray array,
+ jsize start, jsize len, jlong *buf) {
+ functions->GetLongArrayRegion(this,array,start,len,buf);
+ }
+ void GetFloatArrayRegion(jfloatArray array,
+ jsize start, jsize len, jfloat *buf) {
+ functions->GetFloatArrayRegion(this,array,start,len,buf);
+ }
+ void GetDoubleArrayRegion(jdoubleArray array,
+ jsize start, jsize len, jdouble *buf) {
+ functions->GetDoubleArrayRegion(this,array,start,len,buf);
+ }
+
+ void SetBooleanArrayRegion(jbooleanArray array, jsize start, jsize len,
+ const jboolean *buf) {
+ functions->SetBooleanArrayRegion(this,array,start,len,buf);
+ }
+ void SetByteArrayRegion(jbyteArray array, jsize start, jsize len,
+ const jbyte *buf) {
+ functions->SetByteArrayRegion(this,array,start,len,buf);
+ }
+ void SetCharArrayRegion(jcharArray array, jsize start, jsize len,
+ const jchar *buf) {
+ functions->SetCharArrayRegion(this,array,start,len,buf);
+ }
+ void SetShortArrayRegion(jshortArray array, jsize start, jsize len,
+ const jshort *buf) {
+ functions->SetShortArrayRegion(this,array,start,len,buf);
+ }
+ void SetIntArrayRegion(jintArray array, jsize start, jsize len,
+ const jint *buf) {
+ functions->SetIntArrayRegion(this,array,start,len,buf);
+ }
+ void SetLongArrayRegion(jlongArray array, jsize start, jsize len,
+ const jlong *buf) {
+ functions->SetLongArrayRegion(this,array,start,len,buf);
+ }
+ void SetFloatArrayRegion(jfloatArray array, jsize start, jsize len,
+ const jfloat *buf) {
+ functions->SetFloatArrayRegion(this,array,start,len,buf);
+ }
+ void SetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len,
+ const jdouble *buf) {
+ functions->SetDoubleArrayRegion(this,array,start,len,buf);
+ }
+
+ jint RegisterNatives(jclass clazz, const JNINativeMethod *methods,
+ jint nMethods) {
+ return functions->RegisterNatives(this,clazz,methods,nMethods);
+ }
+ jint UnregisterNatives(jclass clazz) {
+ return functions->UnregisterNatives(this,clazz);
+ }
+
+ jint MonitorEnter(jobject obj) {
+ return functions->MonitorEnter(this,obj);
+ }
+ jint MonitorExit(jobject obj) {
+ return functions->MonitorExit(this,obj);
+ }
+
+ jint GetJavaVM(JavaVM **vm) {
+ return functions->GetJavaVM(this,vm);
+ }
+
+ void GetStringRegion(jstring str, jsize start, jsize len, jchar *buf) {
+ functions->GetStringRegion(this,str,start,len,buf);
+ }
+ void GetStringUTFRegion(jstring str, jsize start, jsize len, char *buf) {
+ functions->GetStringUTFRegion(this,str,start,len,buf);
+ }
+
+ void * GetPrimitiveArrayCritical(jarray array, jboolean *isCopy) {
+ return functions->GetPrimitiveArrayCritical(this,array,isCopy);
+ }
+ void ReleasePrimitiveArrayCritical(jarray array, void *carray, jint mode) {
+ functions->ReleasePrimitiveArrayCritical(this,array,carray,mode);
+ }
+
+ const jchar * GetStringCritical(jstring string, jboolean *isCopy) {
+ return functions->GetStringCritical(this,string,isCopy);
+ }
+ void ReleaseStringCritical(jstring string, const jchar *cstring) {
+ functions->ReleaseStringCritical(this,string,cstring);
+ }
+
+ jweak NewWeakGlobalRef(jobject obj) {
+ return functions->NewWeakGlobalRef(this,obj);
+ }
+ void DeleteWeakGlobalRef(jweak ref) {
+ functions->DeleteWeakGlobalRef(this,ref);
+ }
+
+ jboolean ExceptionCheck() {
+ return functions->ExceptionCheck(this);
+ }
+
+ jobject NewDirectByteBuffer(void* address, jlong capacity) {
+ return functions->NewDirectByteBuffer(this, address, capacity);
+ }
+ void* GetDirectBufferAddress(jobject buf) {
+ return functions->GetDirectBufferAddress(this, buf);
+ }
+ jlong GetDirectBufferCapacity(jobject buf) {
+ return functions->GetDirectBufferCapacity(this, buf);
+ }
+ jobjectRefType GetObjectRefType(jobject obj) {
+ return functions->GetObjectRefType(this, obj);
+ }
+
+#endif /* __cplusplus */
+};
+
+typedef struct JavaVMOption {
+ char *optionString;
+ void *extraInfo;
+} JavaVMOption;
+
+typedef struct JavaVMInitArgs {
+ jint version;
+
+ jint nOptions;
+ JavaVMOption *options;
+ jboolean ignoreUnrecognized;
+} JavaVMInitArgs;
+
+typedef struct JavaVMAttachArgs {
+ jint version;
+
+ char *name;
+ jobject group;
+} JavaVMAttachArgs;
+
+/* These will be VM-specific. */
+
+#define JDK1_2
+#define JDK1_4
+
+/* End VM-specific. */
+
+struct JNIInvokeInterface_ {
+ void *reserved0;
+ void *reserved1;
+ void *reserved2;
+
+ jint (JNICALL *DestroyJavaVM)(JavaVM *vm);
+
+ jint (JNICALL *AttachCurrentThread)(JavaVM *vm, void **penv, void *args);
+
+ jint (JNICALL *DetachCurrentThread)(JavaVM *vm);
+
+ jint (JNICALL *GetEnv)(JavaVM *vm, void **penv, jint version);
+
+ jint (JNICALL *AttachCurrentThreadAsDaemon)(JavaVM *vm, void **penv, void *args);
+};
+
+struct JavaVM_ {
+ const struct JNIInvokeInterface_ *functions;
+#ifdef __cplusplus
+
+ jint DestroyJavaVM() {
+ return functions->DestroyJavaVM(this);
+ }
+ jint AttachCurrentThread(void **penv, void *args) {
+ return functions->AttachCurrentThread(this, penv, args);
+ }
+ jint DetachCurrentThread() {
+ return functions->DetachCurrentThread(this);
+ }
+
+ jint GetEnv(void **penv, jint version) {
+ return functions->GetEnv(this, penv, version);
+ }
+ jint AttachCurrentThreadAsDaemon(void **penv, void *args) {
+ return functions->AttachCurrentThreadAsDaemon(this, penv, args);
+ }
+#endif
+};
+
+#ifdef _JNI_IMPLEMENTATION_
+#define _JNI_IMPORT_OR_EXPORT_ JNIEXPORT
+#else
+#define _JNI_IMPORT_OR_EXPORT_ JNIIMPORT
+#endif
+_JNI_IMPORT_OR_EXPORT_ jint JNICALL
+JNI_GetDefaultJavaVMInitArgs(void *args);
+
+_JNI_IMPORT_OR_EXPORT_ jint JNICALL
+JNI_CreateJavaVM(JavaVM **pvm, void **penv, void *args);
+
+_JNI_IMPORT_OR_EXPORT_ jint JNICALL
+JNI_GetCreatedJavaVMs(JavaVM **, jsize, jsize *);
+
+/* Defined by native libraries. */
+JNIEXPORT jint JNICALL
+JNI_OnLoad(JavaVM *vm, void *reserved);
+
+JNIEXPORT void JNICALL
+JNI_OnUnload(JavaVM *vm, void *reserved);
+
+#define JNI_VERSION_1_1 0x00010001
+#define JNI_VERSION_1_2 0x00010002
+#define JNI_VERSION_1_4 0x00010004
+#define JNI_VERSION_1_6 0x00010006
+#define JNI_VERSION_1_8 0x00010008
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* !_JAVASOFT_JNI_H_ */
diff --git a/java/arm-linux/linux/jni_md.h b/java/arm-linux/linux/jni_md.h
new file mode 100644
index 0000000..80eedf3
--- /dev/null
+++ b/java/arm-linux/linux/jni_md.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef _JAVASOFT_JNI_MD_H_
+#define _JAVASOFT_JNI_MD_H_
+
+#ifndef __has_attribute
+ #define __has_attribute(x) 0
+#endif
+#if (defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ > 2))) || __has_attribute(visibility)
+ #define JNIEXPORT __attribute__((visibility("default")))
+ #define JNIIMPORT __attribute__((visibility("default")))
+#else
+ #define JNIEXPORT
+ #define JNIIMPORT
+#endif
+
+#define JNICALL
+
+typedef int jint;
+#ifdef _LP64 /* 64-bit Solaris */
+typedef long jlong;
+#else
+typedef long long jlong;
+#endif
+
+typedef signed char jbyte;
+
+#endif /* !_JAVASOFT_JNI_MD_H_ */
diff --git a/java/java.gradle b/java/java.gradle
new file mode 100644
index 0000000..8ff6a7b
--- /dev/null
+++ b/java/java.gradle
@@ -0,0 +1,134 @@
+import org.gradle.internal.os.OperatingSystem
+
+apply plugin: 'java'
+
+def generatedJNIHeaderLoc = '../build/include'
+
+sourceSets {
+ main {
+ java {
+ srcDirs = ['../java/src']
+ }
+ }
+}
+
+jar {
+ description = 'Generates NetworkTables jar, with the JNI shared libraries embedded'
+ baseName = 'ntcore'
+ classifier = "$buildPlatform"
+
+ dependsOn { classes }
+ binaries.withType(SharedLibraryBinary) { binary ->
+ from(file(binary.sharedLibraryFile)) {
+ into getPlatformPath(binary)
+ }
+ }
+}
+
+project.tasks.whenTaskAdded { task->
+ if (isArm) {
+ if (task.name == 'ntcoreSharedLibrary') jar.dependsOn task
+ } else {
+ if (task.name == 'x64NtcoreSharedLibrary' || task.name == 'x86NtcoreSharedLibrary')
+ jar.dependsOn task
+ }
+}
+
+task networktablesJavaSource(type: Jar, dependsOn: classes) {
+ description = 'Generates the source jar for NetworkTables java'
+ group = 'WPILib'
+ baseName = 'ntcore'
+ classifier = "sources"
+ from sourceSets.main.allJava
+}
+
+task networktablesJavadoc(type: Jar, dependsOn: javadoc) {
+ description = 'Generates the javadoc jar for NetworkTables java'
+ group = 'WPILib'
+ baseName = 'ntcore'
+ classifier = "javadoc"
+ from javadoc.destinationDir
+}
+
+build.dependsOn networktablesJavaSource
+build.dependsOn networktablesJavadoc
+
+/**
+ * Generates the JNI headers
+ */
+task jniHeadersNetworkTables {
+ description = 'Generates JNI headers from edu.wpi.first.wpilibj.networktables.*'
+ group = 'WPILib'
+ def outputFolder = file(generatedJNIHeaderLoc)
+ inputs.files sourceSets.main.output
+ outputs.file outputFolder
+ doLast {
+ outputFolder.mkdirs()
+ exec {
+ executable org.gradle.internal.jvm.Jvm.current().getExecutable('javah')
+ args '-d', outputFolder
+ args '-classpath', sourceSets.main.output.classesDir
+ args 'edu.wpi.first.wpilibj.networktables.NetworkTablesJNI'
+ }
+ }
+}
+
+clean {
+ delete generatedJNIHeaderLoc
+}
+
+compileJava {
+ options.compilerArgs << '-Xlint:unchecked'
+}
+
+javadoc {
+ options.addStringOption('Xdoclint:none', '-quiet')
+}
+
+// This creates a lambda that the main build.gradle can access, which sets up the JNI includes for the
+// target build platform. This lambda is exposed as a property in the main build.gradle.
+ext.setupJniIncludes = { binaries ->
+ def platformSpecificIncludeFlag = { loc, cppCompiler ->
+ if (OperatingSystem.current().isWindows()) {
+ cppCompiler.args "/I$loc"
+ } else {
+ cppCompiler.args '-I', loc
+ }
+ }
+ binaries.all {
+ tasks.withType(CppCompile) {
+ if (buildPlatform == 'arm') {
+ cppCompiler.args '-I', file('../java/arm-linux').absolutePath
+ cppCompiler.args '-I', file('../java/arm-linux/linux').absolutePath
+ } else {
+ def jdkLocation = org.gradle.internal.jvm.Jvm.current().javaHome
+ platformSpecificIncludeFlag("${jdkLocation}/include", cppCompiler)
+
+ if (targetPlatform.operatingSystem.macOsX) {
+ platformSpecificIncludeFlag("${jdkLocation}/include/darwin", cppCompiler)
+ } else if (targetPlatform.operatingSystem.linux) {
+ platformSpecificIncludeFlag("${jdkLocation}/include/linux", cppCompiler)
+ } else if (targetPlatform.operatingSystem.windows) {
+ platformSpecificIncludeFlag("${jdkLocation}/include/win32", cppCompiler)
+ } else if (targetPlatform.operatingSystem.freeBSD) {
+ platformSpecificIncludeFlag("${jdkLocation}/include/freebsd", cppCompiler)
+ } else if (file("$jdkLocation/include/darwin").exists()) {
+ // TODO: As of Gradle 2.8, targetPlatform.operatingSystem.macOsX returns false
+ // on El Capitan. We therefore manually test for the darwin folder and include it
+ // if it exists
+ platformSpecificIncludeFlag("${jdkLocation}/include/darwin", cppCompiler)
+ }
+ }
+
+ jniHeadersNetworkTables.outputs.files.each { file ->
+ if (buildPlatform == 'arm') {
+ cppCompiler.args '-I', file.getPath()
+ } else {
+ platformSpecificIncludeFlag(file.getPath(), cppCompiler)
+ }
+ }
+
+ dependsOn jniHeadersNetworkTables
+ }
+ }
+}
diff --git a/java/lib/NetworkTablesJNI.cpp b/java/lib/NetworkTablesJNI.cpp
new file mode 100644
index 0000000..d235fd3
--- /dev/null
+++ b/java/lib/NetworkTablesJNI.cpp
@@ -0,0 +1,1454 @@
+#include <jni.h>
+#include <atomic>
+#include <cassert>
+#include <condition_variable>
+#include <mutex>
+#include <sstream>
+#include <queue>
+#include <thread>
+
+#include "edu_wpi_first_wpilibj_networktables_NetworkTablesJNI.h"
+#include "ntcore.h"
+#include "atomic_static.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;
+// Thread-attached environment for listener callbacks.
+static JNIEnv *listenerEnv = nullptr;
+
+static void ListenerOnStart() {
+ if (!jvm) return;
+ JNIEnv *env;
+ if (jvm->AttachCurrentThread(reinterpret_cast<void **>(&env),
+ nullptr) != JNI_OK)
+ return;
+ if (!env || !env->functions) return;
+ listenerEnv = env;
+}
+
+static void ListenerOnExit() {
+ listenerEnv = nullptr;
+ if (!jvm) return;
+ jvm->DetachCurrentThread();
+}
+
+extern "C" {
+
+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);
+
+ // Initial configuration of listener start/exit
+ nt::SetListenerOnStart(ListenerOnStart);
+ nt::SetListenerOnExit(ListenerOnExit);
+
+ 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;
+}
+
+} // extern "C"
+
+//
+// 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;
+};
+
+class JavaByteRefBB {
+ public:
+ JavaByteRefBB(JNIEnv *env, jobject bb, int len)
+ : m_elements(env->GetDirectBufferAddress(bb)), m_size(len) {}
+
+ operator nt::StringRef() const {
+ return nt::StringRef(reinterpret_cast<char *>(m_elements), m_size);
+ }
+
+ private:
+ void *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> FromJavaRawBB(JNIEnv *env, jobject jbb, int len) {
+ void* elements = env->GetDirectBufferAddress(jbb);
+ if (!elements) return nullptr;
+ auto rv = nt::Value::MakeRaw(
+ nt::StringRef(reinterpret_cast<char *>(elements), len));
+ 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));
+}
+
+extern "C" {
+
+/*
+ * 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__Ljava_lang_String_2_3B
+ (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: putRaw
+ * Signature: (Ljava/lang/String;Ljava/nio/ByteBuffer;I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_putRaw__Ljava_lang_String_2Ljava_nio_ByteBuffer_2I
+ (JNIEnv *env, jclass, jstring key, jobject value, jint len)
+{
+ auto v = FromJavaRawBB(env, value, len);
+ 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__Ljava_lang_String_2_3B
+ (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: forcePutRaw
+ * Signature: (Ljava/lang/String;Ljava/nio/ByteBuffer;I)V
+ */
+JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_forcePutRaw__Ljava_lang_String_2Ljava_nio_ByteBuffer_2I
+ (JNIEnv *env, jclass, jstring key, jobject value, jint len)
+{
+ auto v = FromJavaRawBB(env, value, len);
+ 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) {
+ 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) 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, jint flags)
+{
+ // 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;I)V");
+ if (!mid) return 0;
+
+ return nt::AddEntryListener(
+ JavaStringRef(envouter, prefix),
+ [=](unsigned int uid, nt::StringRef name,
+ std::shared_ptr<nt::Value> value, unsigned int flags_) {
+ JNIEnv *env = listenerEnv;
+ 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) return;
+
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ return;
+ }
+ env->CallVoidMethod(handler, mid, (jint)uid, ToJavaString(env, name),
+ jobj, (jint)(flags_));
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ }
+ },
+ flags);
+}
+
+/*
+ * 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) {
+ JNIEnv *env = listenerEnv;
+ 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) return;
+
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ return;
+ }
+ env->CallVoidMethod(handler, mid, (jint)uid,
+ (jboolean)(connected ? 1 : 0), jobj);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ }
+ },
+ 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__Ljava_lang_String_2_3B
+ (JNIEnv *env, jclass, jstring key, jbyteArray params)
+{
+ return nt::CallRpc(JavaStringRef(env, key), JavaByteRef(env, params));
+}
+
+/*
+ * Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI
+ * Method: callRpc
+ * Signature: (Ljava/lang/String;Ljava/nio/ByteBuffer;I)I
+ */
+JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_callRpc__Ljava_lang_String_2Ljava_nio_ByteBuffer_2I
+ (JNIEnv *env, jclass, jstring key, jobject params, jint params_len)
+{
+ return nt::CallRpc(JavaStringRef(env, key),
+ JavaByteRefBB(env, params, params_len));
+}
+
+/*
+ * 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();
+}
+
+} // extern "C"
+
+// Thread where log callbacks are actually performed.
+//
+// JNI's AttachCurrentThread() creates a Java Thread object on every
+// invocation, which is both time inefficient and causes issues with Eclipse
+// (which tries to keep a thread list up-to-date and thus gets swamped).
+//
+// Instead, this class attaches just once. When a hardware notification
+// occurs, a condition variable wakes up this thread and this thread actually
+// makes the call into Java.
+class LoggerThreadJNI {
+ public:
+ static LoggerThreadJNI& GetInstance() {
+ ATOMIC_STATIC(LoggerThreadJNI, instance);
+ return instance;
+ }
+ LoggerThreadJNI();
+ ~LoggerThreadJNI();
+ void SetFunc(JNIEnv* env, jobject func, jmethodID mid);
+ void Start();
+ void Stop();
+
+ void Log(unsigned int level, const char* file, unsigned int line,
+ const char* msg);
+
+ private:
+ void ThreadMain();
+
+ std::thread m_thread;
+ std::mutex m_mutex;
+ std::condition_variable m_cond;
+ std::atomic_bool m_active;
+ struct LogMessage {
+ LogMessage(unsigned int level_, const char* file_, unsigned int line_,
+ const char* msg_)
+ : level(level_), file(file_), line(line_), msg(msg_) {}
+ unsigned int level;
+ const char* file;
+ unsigned int line;
+ std::string msg;
+ };
+ std::queue<LogMessage> m_queue;
+ std::mutex m_shutdown_mutex;
+ std::condition_variable m_shutdown_cv;
+ bool m_shutdown = false;
+ jobject m_func = nullptr;
+ jmethodID m_mid;
+
+ ATOMIC_STATIC_DECL(LoggerThreadJNI)
+};
+
+ATOMIC_STATIC_INIT(LoggerThreadJNI)
+
+LoggerThreadJNI::LoggerThreadJNI() {
+ m_active = false;
+}
+
+LoggerThreadJNI::~LoggerThreadJNI() {
+ Stop();
+}
+
+void LoggerThreadJNI::SetFunc(JNIEnv* env, jobject func, jmethodID mid) {
+ std::lock_guard<std::mutex> lock(m_mutex);
+ // free global reference
+ if (m_func) env->DeleteGlobalRef(m_func);
+ // create global reference
+ m_func = env->NewGlobalRef(func);
+ m_mid = mid;
+}
+
+void LoggerThreadJNI::Start() {
+ {
+ std::lock_guard<std::mutex> lock(m_mutex);
+ if (m_active) return;
+ m_active = true;
+ }
+ {
+ std::lock_guard<std::mutex> lock(m_shutdown_mutex);
+ m_shutdown = false;
+ }
+ m_thread = std::thread(&LoggerThreadJNI::ThreadMain, this);
+}
+
+void LoggerThreadJNI::Stop() {
+ {
+ std::lock_guard<std::mutex> lock(m_mutex);
+ if (!m_active) return;
+ m_active = false;
+ }
+ m_cond.notify_one(); // wake up thread
+
+ // join threads, with timeout
+ if (m_thread.joinable()) {
+ std::unique_lock<std::mutex> lock(m_shutdown_mutex);
+ auto timeout_time =
+ std::chrono::steady_clock::now() + std::chrono::seconds(1);
+ if (m_shutdown_cv.wait_until(lock, timeout_time,
+ [&] { return m_shutdown; }))
+ m_thread.join();
+ else
+ m_thread.detach(); // timed out, detach it
+ }
+}
+
+void LoggerThreadJNI::Log(unsigned int level, const char *file,
+ unsigned int line, const char *msg) {
+ std::lock_guard<std::mutex> lock(m_mutex);
+ if (!m_active) return;
+ m_queue.emplace(level, file, line, msg);
+ m_cond.notify_one();
+}
+
+void LoggerThreadJNI::ThreadMain() {
+ JNIEnv *env;
+ jint rs = jvm->AttachCurrentThread((void**)&env, NULL);
+ if (rs != JNI_OK) return;
+
+ std::unique_lock<std::mutex> lock(m_mutex);
+ while (m_active) {
+ m_cond.wait(lock, [&] { return !m_active || !m_queue.empty(); });
+ if (!m_active) break;
+ while (!m_queue.empty()) {
+ if (!m_active) break;
+ auto item = std::move(m_queue.front());
+ m_queue.pop();
+ auto func = m_func;
+ auto mid = m_mid;
+ lock.unlock(); // don't hold mutex during callback execution
+ env->CallVoidMethod(func, mid, (jint)item.level,
+ ToJavaString(env, item.file), (jint)item.line,
+ ToJavaString(env, item.msg));
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ }
+ lock.lock();
+ }
+ }
+
+ if (jvm) jvm->DetachCurrentThread();
+
+ // use condition variable to signal thread shutdown
+ {
+ std::lock_guard<std::mutex> lock(m_shutdown_mutex);
+ m_shutdown = true;
+ m_shutdown_cv.notify_one();
+ }
+}
+
+extern "C" {
+
+/*
+ * 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 *env, jclass, jobject func, jint minLevel)
+{
+ // cls is a temporary here; cannot be used within callback functor
+ jclass cls = env->GetObjectClass(func);
+ if (!cls) return;
+
+ // method ids, on the other hand, are safe to retain
+ jmethodID mid = env->GetMethodID(
+ cls, "apply", "(ILjava/lang/String;ILjava/lang/String;)V");
+ if (!mid) return;
+
+ auto& thread = LoggerThreadJNI::GetInstance();
+ thread.SetFunc(env, func, mid);
+ thread.Start();
+
+ nt::SetLogger(
+ [](unsigned int level, const char *file, unsigned int line,
+ const char *msg) {
+ LoggerThreadJNI::GetInstance().Log(level, file, line, msg);
+ },
+ minLevel);
+}
+
+} // extern "C"
diff --git a/java/src/edu/wpi/first/wpilibj/networktables/ConnectionInfo.java b/java/src/edu/wpi/first/wpilibj/networktables/ConnectionInfo.java
new file mode 100644
index 0000000..d9f0e1d
--- /dev/null
+++ b/java/src/edu/wpi/first/wpilibj/networktables/ConnectionInfo.java
@@ -0,0 +1,17 @@
+package edu.wpi.first.wpilibj.networktables;
+
+public class ConnectionInfo {
+ final String remote_id;
+ final String remote_name;
+ final int remote_port;
+ final long last_update;
+ final int protocol_version;
+
+ ConnectionInfo(String remote_id, String remote_name, int remote_port, long last_update, int protocol_version) {
+ this.remote_id = remote_id;
+ this.remote_name = remote_name;
+ this.remote_port = remote_port;
+ this.last_update = last_update;
+ this.protocol_version = protocol_version;
+ }
+}
diff --git a/java/src/edu/wpi/first/wpilibj/networktables/EntryInfo.java b/java/src/edu/wpi/first/wpilibj/networktables/EntryInfo.java
new file mode 100644
index 0000000..164d789
--- /dev/null
+++ b/java/src/edu/wpi/first/wpilibj/networktables/EntryInfo.java
@@ -0,0 +1,15 @@
+package edu.wpi.first.wpilibj.networktables;
+
+public class EntryInfo {
+ final String name;
+ final int type;
+ final int flags;
+ final long last_change;
+
+ EntryInfo(String name, int type, int flags, long last_change) {
+ this.name = name;
+ this.type = type;
+ this.flags = flags;
+ this.last_change = last_change;
+ }
+}
diff --git a/java/src/edu/wpi/first/wpilibj/networktables/NetworkTable.java b/java/src/edu/wpi/first/wpilibj/networktables/NetworkTable.java
new file mode 100644
index 0000000..a2d1eb6
--- /dev/null
+++ b/java/src/edu/wpi/first/wpilibj/networktables/NetworkTable.java
@@ -0,0 +1,958 @@
+package edu.wpi.first.wpilibj.networktables;
+
+import edu.wpi.first.wpilibj.tables.*;
+import edu.wpi.first.wpilibj.networktables2.type.*;
+import java.io.*;
+import java.nio.ByteBuffer;
+import java.util.*;
+
+/**
+ * A network table that knows its subtable path.
+ */
+public class NetworkTable implements ITable, IRemote {
+ /**
+ * The path separator for sub-tables and keys
+ *
+ */
+ public static final char PATH_SEPARATOR = '/';
+ /**
+ * The default port that network tables operates on
+ */
+ public static final int DEFAULT_PORT = 1735;
+
+ private static boolean client = false;
+ private static boolean running = false;
+ private static int port = DEFAULT_PORT;
+ private static String ipAddress = "";
+ private static String persistentFilename = "networktables.ini";
+
+ private synchronized static void checkInit() {
+ if (running)
+ throw new IllegalStateException(
+ "Network tables has already been initialized");
+ }
+
+ /**
+ * initializes network tables
+ */
+ public synchronized static void initialize() {
+ if (running)
+ shutdown();
+ if (client)
+ NetworkTablesJNI.startClient(ipAddress, port);
+ else
+ NetworkTablesJNI.startServer(persistentFilename, "", port);
+ running = true;
+ }
+
+ /**
+ * shuts down network tables
+ */
+ public synchronized static void shutdown() {
+ if (!running)
+ return;
+ if (client)
+ NetworkTablesJNI.stopClient();
+ else
+ NetworkTablesJNI.stopServer();
+ running = false;
+ }
+
+ /**
+ * set that network tables should be a server
+ * This must be called before initialize or getTable
+ */
+ public synchronized static void setServerMode() {
+ if (!client)
+ return;
+ checkInit();
+ client = false;
+ }
+
+ /**
+ * set that network tables should be a client
+ * This must be called before initialize or getTable
+ */
+ public synchronized static void setClientMode() {
+ if (client)
+ return;
+ checkInit();
+ client = true;
+ }
+
+ /**
+ * set the team the robot is configured for (this will set the mdns address that
+ * network tables will connect to in client mode)
+ * This must be called before initialize or getTable
+ * @param team the team number
+ */
+ public synchronized static void setTeam(int team) {
+ setIPAddress("roboRIO-" + team + "-FRC.local");
+ }
+
+ /**
+ * @param address the adress that network tables will connect to in client
+ * mode
+ */
+ public synchronized static void setIPAddress(final String address) {
+ if (ipAddress.equals(address))
+ return;
+ checkInit();
+ ipAddress = address;
+ }
+
+ /**
+ * @param aport the port number that network tables will connect to in client
+ * mode or listen to in server mode
+ */
+ public synchronized static void setPort(int aport) {
+ if (port == aport)
+ return;
+ checkInit();
+ port = aport;
+ }
+
+ /**
+ * Sets the persistent filename.
+ * @param filename the filename that the network tables server uses for
+ * automatic loading and saving of persistent values
+ */
+ public synchronized static void setPersistentFilename(final String filename) {
+ if (persistentFilename.equals(filename))
+ return;
+ checkInit();
+ persistentFilename = filename;
+ }
+
+ /**
+ * Sets the network identity.
+ * This is provided in the connection info on the remote end.
+ * @param name identity
+ */
+ public static void setNetworkIdentity(String name) {
+ NetworkTablesJNI.setNetworkIdentity(name);
+ }
+
+ public static boolean[] toNative(Boolean[] arr) {
+ boolean[] out = new boolean[arr.length];
+ for (int i = 0; i < arr.length; i++)
+ out[i] = arr[i];
+ return out;
+ }
+
+ public static double[] toNative(Double[] arr) {
+ double[] out = new double[arr.length];
+ for (int i = 0; i < arr.length; i++)
+ out[i] = arr[i];
+ return out;
+ }
+
+ public static Boolean[] fromNative(boolean[] arr) {
+ Boolean[] out = new Boolean[arr.length];
+ for (int i = 0; i < arr.length; i++)
+ out[i] = arr[i];
+ return out;
+ }
+
+ public static Double[] fromNative(double[] arr) {
+ Double[] out = new Double[arr.length];
+ for (int i = 0; i < arr.length; i++)
+ out[i] = arr[i];
+ return out;
+ }
+
+ /**
+ * Gets the table with the specified key. If the table does not exist, a new
+ *table will be created.<br>
+ * This will automatically initialize network tables if it has not been
+ *already
+ *
+ * @param key
+ * the key name
+ * @return the network table requested
+ */
+ public synchronized static NetworkTable getTable(String key) {
+ if (!running)
+ initialize();
+ if (key.isEmpty())
+ return new NetworkTable(key);
+ return new NetworkTable(PATH_SEPARATOR + key);
+ }
+
+ private final String path;
+
+ NetworkTable(String path) {
+ this.path = path;
+ }
+ public String toString() { return "NetworkTable: " + path; }
+
+ public static ConnectionInfo[] connections() {
+ return NetworkTablesJNI.getConnections();
+ }
+
+ public boolean isConnected() {
+ ConnectionInfo[] conns = NetworkTablesJNI.getConnections();
+ return conns.length > 0;
+ }
+
+ public boolean isServer() {
+ return !client;
+ }
+
+ private class ListenerBase {
+ public int uid;
+ }
+
+ private class ConnectionListenerAdapter extends ListenerBase implements NetworkTablesJNI.ConnectionListenerFunction {
+ private final IRemote targetSource;
+ private final IRemoteConnectionListener targetListener;
+
+ public ConnectionListenerAdapter(IRemote targetSource, IRemoteConnectionListener targetListener) {
+ this.targetSource = targetSource;
+ this.targetListener = targetListener;
+ }
+
+ public void apply(int uid, boolean connected, ConnectionInfo conn) {
+ if (connected)
+ targetListener.connected(targetSource);
+ else
+ targetListener.disconnected(targetSource);
+ }
+ }
+
+ private final Hashtable<IRemoteConnectionListener,ConnectionListenerAdapter> connectionListenerMap = new Hashtable<IRemoteConnectionListener,ConnectionListenerAdapter>();
+ public synchronized void addConnectionListener(IRemoteConnectionListener listener,
+ boolean immediateNotify) {
+ ConnectionListenerAdapter adapter = connectionListenerMap.get(listener);
+ if (adapter != null)
+ throw new IllegalStateException("Cannot add the same listener twice");
+ adapter = new ConnectionListenerAdapter(this, listener);
+ adapter.uid = NetworkTablesJNI.addConnectionListener(adapter, immediateNotify);
+ connectionListenerMap.put(listener, adapter);
+ }
+
+ public synchronized void removeConnectionListener(IRemoteConnectionListener listener) {
+ ConnectionListenerAdapter adapter = connectionListenerMap.get(listener);
+ if (adapter != null) {
+ NetworkTablesJNI.removeConnectionListener(adapter.uid);
+ connectionListenerMap.remove(listener);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void addTableListener(ITableListener listener) {
+ addTableListenerEx(listener, NOTIFY_NEW | NOTIFY_UPDATE);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void addTableListener(ITableListener listener,
+ boolean immediateNotify) {
+ int flags = NOTIFY_NEW | NOTIFY_UPDATE;
+ if (immediateNotify)
+ flags |= NOTIFY_IMMEDIATE;
+ addTableListenerEx(listener, flags);
+ }
+
+ private class TableListenerAdapter extends ListenerBase implements NetworkTablesJNI.EntryListenerFunction {
+ private final int prefixLen;
+ private final ITable targetSource;
+ private final ITableListener targetListener;
+
+ public TableListenerAdapter(int prefixLen, ITable targetSource, ITableListener targetListener) {
+ this.prefixLen = prefixLen;
+ this.targetSource = targetSource;
+ this.targetListener = targetListener;
+ }
+
+ public void apply(int uid, String key, Object value, int flags) {
+ String relativeKey = key.substring(prefixLen);
+ if (relativeKey.indexOf(PATH_SEPARATOR) != -1)
+ return;
+ targetListener.valueChangedEx(targetSource, relativeKey, value, flags);
+ }
+ }
+
+ private final Hashtable<ITableListener,List<ListenerBase>> listenerMap = new Hashtable<ITableListener,List<ListenerBase>>();
+ public synchronized void addTableListenerEx(ITableListener listener,
+ int flags) {
+ List<ListenerBase> adapters = listenerMap.get(listener);
+ if (adapters == null) {
+ adapters = new ArrayList<ListenerBase>();
+ listenerMap.put(listener, adapters);
+ }
+ TableListenerAdapter adapter =
+ new TableListenerAdapter(path.length() + 1, this, listener);
+ adapter.uid = NetworkTablesJNI.addEntryListener(path + PATH_SEPARATOR, adapter, flags);
+ adapters.add(adapter);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void addTableListener(String key, ITableListener listener,
+ boolean immediateNotify) {
+ int flags = NOTIFY_NEW | NOTIFY_UPDATE;
+ if (immediateNotify)
+ flags |= NOTIFY_IMMEDIATE;
+ addTableListenerEx(key, listener, flags);
+ }
+
+ private class KeyListenerAdapter extends ListenerBase implements NetworkTablesJNI.EntryListenerFunction {
+ private final String relativeKey;
+ private final String fullKey;
+ private final ITable targetSource;
+ private final ITableListener targetListener;
+
+ public KeyListenerAdapter(String relativeKey, String fullKey, ITable targetSource, ITableListener targetListener) {
+ this.relativeKey = relativeKey;
+ this.fullKey = fullKey;
+ this.targetSource = targetSource;
+ this.targetListener = targetListener;
+ }
+
+ public void apply(int uid, String key, Object value, int flags) {
+ if (!key.equals(fullKey))
+ return;
+ targetListener.valueChangedEx(targetSource, relativeKey, value, flags);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public synchronized void addTableListenerEx(String key,
+ ITableListener listener,
+ int flags) {
+ List<ListenerBase> adapters = listenerMap.get(listener);
+ if (adapters == null) {
+ adapters = new ArrayList<ListenerBase>();
+ listenerMap.put(listener, adapters);
+ }
+ String fullKey = path + PATH_SEPARATOR + key;
+ KeyListenerAdapter adapter =
+ new KeyListenerAdapter(key, fullKey, this, listener);
+ adapter.uid = NetworkTablesJNI.addEntryListener(fullKey, adapter, flags);
+ adapters.add(adapter);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void addSubTableListener(final ITableListener listener) {
+ addSubTableListener(listener, false);
+ }
+
+ private class SubListenerAdapter extends ListenerBase implements NetworkTablesJNI.EntryListenerFunction {
+ private final int prefixLen;
+ private final ITable targetSource;
+ private final ITableListener targetListener;
+ private final Set<String> notifiedTables = new HashSet<String>();
+
+ public SubListenerAdapter(int prefixLen, ITable targetSource, ITableListener targetListener) {
+ this.prefixLen = prefixLen;
+ this.targetSource = targetSource;
+ this.targetListener = targetListener;
+ }
+
+ public void apply(int uid, String key, Object value, int flags) {
+ String relativeKey = key.substring(prefixLen);
+ int endSubTable = relativeKey.indexOf(PATH_SEPARATOR);
+ if (endSubTable == -1)
+ return;
+ String subTableKey = relativeKey.substring(0, endSubTable);
+ if (notifiedTables.contains(subTableKey))
+ return;
+ notifiedTables.add(subTableKey);
+ targetListener.valueChangedEx(targetSource, subTableKey, targetSource.getSubTable(subTableKey), flags);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public synchronized void addSubTableListener(final ITableListener listener,
+ boolean localNotify) {
+ List<ListenerBase> adapters = listenerMap.get(listener);
+ if (adapters == null) {
+ adapters = new ArrayList<ListenerBase>();
+ listenerMap.put(listener, adapters);
+ }
+ SubListenerAdapter adapter =
+ new SubListenerAdapter(path.length() + 1, this, listener);
+ int flags = NOTIFY_NEW | NOTIFY_IMMEDIATE;
+ if (localNotify)
+ flags |= NOTIFY_LOCAL;
+ adapter.uid = NetworkTablesJNI.addEntryListener(path + PATH_SEPARATOR, adapter, flags);
+ adapters.add(adapter);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public synchronized void removeTableListener(ITableListener listener) {
+ List<ListenerBase> adapters = listenerMap.get(listener);
+ if (adapters != null) {
+ for (int i = 0; i < adapters.size(); ++i)
+ NetworkTablesJNI.removeEntryListener(adapters.get(i).uid);
+ adapters.clear();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ITable getSubTable(String key) {
+ return new NetworkTable(path + PATH_SEPARATOR + key);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean containsKey(String key) {
+ return NetworkTablesJNI.containsKey(path + PATH_SEPARATOR + key);
+ }
+
+ public boolean containsSubTable(String key) {
+ EntryInfo[] entries = NetworkTablesJNI.getEntries(path + PATH_SEPARATOR + key + PATH_SEPARATOR, 0);
+ return entries.length != 0;
+ }
+
+ /**
+ * @param types bitmask of types; 0 is treated as a "don't care".
+ * @return keys currently in the table
+ */
+ public Set<String> getKeys(int types) {
+ Set<String> keys = new HashSet<String>();
+ int prefixLen = path.length() + 1;
+ for (EntryInfo entry : NetworkTablesJNI.getEntries(path + PATH_SEPARATOR, types)) {
+ String relativeKey = entry.name.substring(prefixLen);
+ if (relativeKey.indexOf(PATH_SEPARATOR) != -1)
+ continue;
+ keys.add(relativeKey);
+ }
+ return keys;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Set<String> getKeys() {
+ return getKeys(0);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Set<String> getSubTables() {
+ Set<String> keys = new HashSet<String>();
+ int prefixLen = path.length() + 1;
+ for (EntryInfo entry : NetworkTablesJNI.getEntries(path + PATH_SEPARATOR, 0)) {
+ String relativeKey = entry.name.substring(prefixLen);
+ int endSubTable = relativeKey.indexOf(PATH_SEPARATOR);
+ if (endSubTable == -1)
+ continue;
+ keys.add(relativeKey.substring(0, endSubTable));
+ }
+ return keys;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean putNumber(String key, double value) {
+ return NetworkTablesJNI.putDouble(path + PATH_SEPARATOR + key, value);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @deprecated This exception-raising method has been replaced by the
+ * default-taking method {@link #getNumber(String, double)}.
+ */
+ @Override
+ @Deprecated
+ public double getNumber(String key) throws TableKeyNotDefinedException {
+ return NetworkTablesJNI.getDouble(path + PATH_SEPARATOR + key);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public double getNumber(String key, double defaultValue) {
+ return NetworkTablesJNI.getDouble(path + PATH_SEPARATOR + key, defaultValue);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean putString(String key, String value) {
+ return NetworkTablesJNI.putString(path + PATH_SEPARATOR + key, value);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @deprecated This exception-raising method has been replaced by the
+ * default-taking method {@link #getString(String, String)}.
+ */
+ @Override
+ @Deprecated
+ public String getString(String key) throws TableKeyNotDefinedException {
+ return NetworkTablesJNI.getString(path + PATH_SEPARATOR + key);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getString(String key, String defaultValue) {
+ return NetworkTablesJNI.getString(path + PATH_SEPARATOR + key, defaultValue);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean putBoolean(String key, boolean value) {
+ return NetworkTablesJNI.putBoolean(path + PATH_SEPARATOR + key, value);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @deprecated This exception-raising method has been replaced by the
+ * default-taking method {@link #getBoolean(String, boolean)}.
+ */
+ @Override
+ @Deprecated
+ public boolean getBoolean(String key) throws TableKeyNotDefinedException {
+ return NetworkTablesJNI.getBoolean(path + PATH_SEPARATOR + key);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean getBoolean(String key, boolean defaultValue) {
+ return NetworkTablesJNI.getBoolean(path + PATH_SEPARATOR + key, defaultValue);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean putBooleanArray(String key, boolean[] value) {
+ return NetworkTablesJNI.putBooleanArray(path + PATH_SEPARATOR + key, value);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean putBooleanArray(String key, Boolean[] value) {
+ return putBooleanArray(key, toNative(value));
+ }
+
+ /**
+ * {@inheritDoc}
+ * @deprecated This exception-raising method has been replaced by the
+ * default-taking method {@link #getBooleanArray(String, boolean[])}.
+ */
+ @Override
+ @Deprecated
+ public boolean[] getBooleanArray(String key) throws TableKeyNotDefinedException {
+ return NetworkTablesJNI.getBooleanArray(path + PATH_SEPARATOR + key);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean[] getBooleanArray(String key, boolean[] defaultValue) {
+ return NetworkTablesJNI.getBooleanArray(path + PATH_SEPARATOR + key, defaultValue);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Boolean[] getBooleanArray(String key, Boolean[] defaultValue) {
+ try {
+ return fromNative(getBooleanArray(key));
+ } catch (TableKeyNotDefinedException e) {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean putNumberArray(String key, double[] value) {
+ return NetworkTablesJNI.putDoubleArray(path + PATH_SEPARATOR + key, value);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean putNumberArray(String key, Double[] value) {
+ return putNumberArray(key, toNative(value));
+ }
+
+ /**
+ * {@inheritDoc}
+ * @deprecated This exception-raising method has been replaced by the
+ * default-taking method {@link #getNumberArray(String, double[])}.
+ */
+ @Override
+ @Deprecated
+ public double[] getNumberArray(String key) throws TableKeyNotDefinedException {
+ return NetworkTablesJNI.getDoubleArray(path + PATH_SEPARATOR + key);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public double[] getNumberArray(String key, double[] defaultValue) {
+ return NetworkTablesJNI.getDoubleArray(path + PATH_SEPARATOR + key, defaultValue);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Double[] getNumberArray(String key, Double[] defaultValue) {
+ try {
+ return fromNative(getNumberArray(key));
+ } catch (TableKeyNotDefinedException e) {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean putStringArray(String key, String[] value) {
+ return NetworkTablesJNI.putStringArray(path + PATH_SEPARATOR + key, value);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @deprecated This exception-raising method has been replaced by the
+ * default-taking method {@link #getStringArray(String, String[])}.
+ */
+ @Override
+ @Deprecated
+ public String[] getStringArray(String key) throws TableKeyNotDefinedException {
+ return NetworkTablesJNI.getStringArray(path + PATH_SEPARATOR + key);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String[] getStringArray(String key, String[] defaultValue) {
+ return NetworkTablesJNI.getStringArray(path + PATH_SEPARATOR + key, defaultValue);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean putRaw(String key, byte[] value) {
+ return NetworkTablesJNI.putRaw(path + PATH_SEPARATOR + key, value);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean putRaw(String key, ByteBuffer value, int len) {
+ if (!value.isDirect())
+ throw new IllegalArgumentException("must be a direct buffer");
+ if (value.capacity() < len)
+ throw new IllegalArgumentException("buffer is too small, must be at least " + len);
+ return NetworkTablesJNI.putRaw(path + PATH_SEPARATOR + key, value, len);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @deprecated This exception-raising method has been replaced by the
+ * default-taking method {@link #getRaw(String, byte[])}.
+ */
+ @Override
+ @Deprecated
+ public byte[] getRaw(String key) throws TableKeyNotDefinedException {
+ return NetworkTablesJNI.getRaw(path + PATH_SEPARATOR + key);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public byte[] getRaw(String key, byte[] defaultValue) {
+ return NetworkTablesJNI.getRaw(path + PATH_SEPARATOR + key, defaultValue);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean putValue(String key, Object value) throws IllegalArgumentException {
+ if (value instanceof Boolean)
+ return NetworkTablesJNI.putBoolean(path + PATH_SEPARATOR + key, ((Boolean)value).booleanValue());
+ else if (value instanceof Double)
+ return NetworkTablesJNI.putDouble(path + PATH_SEPARATOR + key, ((Double)value).doubleValue());
+ else if (value instanceof String)
+ return NetworkTablesJNI.putString(path + PATH_SEPARATOR + key, (String)value);
+ else if (value instanceof byte[])
+ return NetworkTablesJNI.putRaw(path + PATH_SEPARATOR + key, (byte[])value);
+ else if (value instanceof boolean[])
+ return NetworkTablesJNI.putBooleanArray(path + PATH_SEPARATOR + key, (boolean[])value);
+ else if (value instanceof double[])
+ return NetworkTablesJNI.putDoubleArray(path + PATH_SEPARATOR + key, (double[])value);
+ else if (value instanceof Boolean[])
+ return NetworkTablesJNI.putBooleanArray(path + PATH_SEPARATOR + key, toNative((Boolean[])value));
+ else if (value instanceof Double[])
+ return NetworkTablesJNI.putDoubleArray(path + PATH_SEPARATOR + key, toNative((Double[])value));
+ else if (value instanceof String[])
+ return NetworkTablesJNI.putStringArray(path + PATH_SEPARATOR + key, (String[])value);
+ else if (value instanceof BooleanArray)
+ return NetworkTablesJNI.putBooleanArray(path + PATH_SEPARATOR + key, toNative((Boolean[])((ArrayData)value).getDataArray()));
+ else if (value instanceof NumberArray)
+ return NetworkTablesJNI.putDoubleArray(path + PATH_SEPARATOR + key, toNative((Double[])((ArrayData)value).getDataArray()));
+ else if (value instanceof StringArray)
+ return NetworkTablesJNI.putStringArray(path + PATH_SEPARATOR + key, (String[])((ArrayData)value).getDataArray());
+ else
+ throw new IllegalArgumentException(key);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @deprecated Use get*Array functions instead.
+ */
+ @Override
+ @Deprecated
+ public void retrieveValue(String key, Object externalData) throws TableKeyNotDefinedException {
+ Object value = getValue(key);
+ if (value instanceof boolean[] && externalData instanceof BooleanArray)
+ ((ArrayData)externalData).setDataArray(fromNative((boolean[])value));
+ else if (value instanceof double[] && externalData instanceof NumberArray)
+ ((ArrayData)externalData).setDataArray(fromNative((double[])value));
+ else if (value instanceof String[] && externalData instanceof StringArray)
+ ((ArrayData)externalData).setDataArray((String[])value);
+ else
+ throw new TableKeyNotDefinedException(key);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @deprecated This exception-raising method has been replaced by the
+ * default-taking method {@link #getValue(String, Object)}.
+ */
+ @Override
+ @Deprecated
+ public Object getValue(String key) throws TableKeyNotDefinedException {
+ return NetworkTablesJNI.getValue(path + PATH_SEPARATOR + key);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Object getValue(String key, Object defaultValue) {
+ return NetworkTablesJNI.getValue(path + PATH_SEPARATOR + key, defaultValue);
+ }
+
+ /** The persistent flag value. */
+ public static final int PERSISTENT = 1;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setPersistent(String key) {
+ setFlags(key, PERSISTENT);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void clearPersistent(String key) {
+ clearFlags(key, PERSISTENT);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isPersistent(String key) {
+ return (getFlags(key) & PERSISTENT) != 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setFlags(String key, int flags) {
+ NetworkTablesJNI.setEntryFlags(path + PATH_SEPARATOR + key, getFlags(key) | flags);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void clearFlags(String key, int flags) {
+ NetworkTablesJNI.setEntryFlags(path + PATH_SEPARATOR + key, getFlags(key) & ~flags);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int getFlags(String key) {
+ return NetworkTablesJNI.getEntryFlags(path + PATH_SEPARATOR + key);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void delete(String key) {
+ NetworkTablesJNI.deleteEntry(path + PATH_SEPARATOR + key);
+ }
+
+ /**
+ * Deletes ALL keys in ALL subtables. Use with caution!
+ */
+ public static void globalDeleteAll() {
+ NetworkTablesJNI.deleteAllEntries();
+ }
+
+ /**
+ * Flushes all updated values immediately to the network.
+ * Note: This is rate-limited to protect the network from flooding.
+ * This is primarily useful for synchronizing network updates with
+ * user code.
+ */
+ public static void flush() {
+ NetworkTablesJNI.flush();
+ }
+
+ /**
+ * Set the periodic update rate.
+ *
+ * @param interval update interval in seconds (range 0.1 to 1.0)
+ */
+ public static void setUpdateRate(double interval) {
+ NetworkTablesJNI.setUpdateRate(interval);
+ }
+
+ /**
+ * Saves persistent keys to a file. The server does this automatically.
+ *
+ * @param filename file name
+ * @throws PersistentException if error saving file
+ */
+ public static void savePersistent(String filename) throws PersistentException {
+ NetworkTablesJNI.savePersistent(filename);
+ }
+
+ /**
+ * Loads persistent keys from a file. The server does this automatically.
+ *
+ * @param filename file name
+ * @return List of warnings (errors result in an exception instead)
+ * @throws PersistentException if error reading file
+ */
+ public static String[] loadPersistent(String filename) throws PersistentException {
+ return NetworkTablesJNI.loadPersistent(filename);
+ }
+
+ /*
+ * Deprecated Methods
+ */
+
+ /**
+ * {@inheritDoc}
+ * @deprecated Use {@link #putNumber(String, double)} instead.
+ */
+ @Override
+ @Deprecated
+ public boolean putInt(String key, int value) {
+ return putNumber(key, value);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @deprecated Use {@link #getNumber(String, double)} instead.
+ */
+ @Override
+ @Deprecated
+ public int getInt(String key) throws TableKeyNotDefinedException {
+ return (int)getNumber(key);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @deprecated Use {@link #getNumber(String, double)} instead.
+ */
+ @Override
+ @Deprecated
+ public int getInt(String key, int defaultValue) throws TableKeyNotDefinedException {
+ try {
+ return (int)getNumber(key);
+ } catch (NoSuchElementException ex) {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ * @deprecated Use {@link #putNumber(String, double)} instead.
+ */
+ @Override
+ @Deprecated
+ public boolean putDouble(String key, double value) {
+ return putNumber(key, value);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @deprecated Use {@link #getNumber(String, double)} instead.
+ */
+ @Override
+ @Deprecated
+ public double getDouble(String key) throws TableKeyNotDefinedException {
+ return getNumber(key);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @deprecated Use {@link #getNumber(String, double)} instead.
+ */
+ @Override
+ @Deprecated
+ public double getDouble(String key, double defaultValue) {
+ return getNumber(key, defaultValue);
+ }
+}
diff --git a/java/src/edu/wpi/first/wpilibj/networktables/NetworkTableKeyNotDefined.java b/java/src/edu/wpi/first/wpilibj/networktables/NetworkTableKeyNotDefined.java
new file mode 100644
index 0000000..d654cfc
--- /dev/null
+++ b/java/src/edu/wpi/first/wpilibj/networktables/NetworkTableKeyNotDefined.java
@@ -0,0 +1,22 @@
+package edu.wpi.first.wpilibj.networktables;
+
+import edu.wpi.first.wpilibj.tables.TableKeyNotDefinedException;
+
+/**
+ * An exception throw when the lookup a a key-value fails in a {@link NetworkTable}
+ *
+ * @deprecated to provide backwards compatability for new api
+ *
+ * @author Mitchell
+ *
+ */
+public class NetworkTableKeyNotDefined extends TableKeyNotDefinedException {
+
+ /**
+ * @param key the key that was not defined in the table
+ */
+ public NetworkTableKeyNotDefined(String key) {
+ super(key);
+ }
+
+}
diff --git a/java/src/edu/wpi/first/wpilibj/networktables/NetworkTablesJNI.java b/java/src/edu/wpi/first/wpilibj/networktables/NetworkTablesJNI.java
new file mode 100644
index 0000000..810d7f8
--- /dev/null
+++ b/java/src/edu/wpi/first/wpilibj/networktables/NetworkTablesJNI.java
@@ -0,0 +1,155 @@
+package edu.wpi.first.wpilibj.networktables;
+
+import edu.wpi.first.wpilibj.tables.*;
+
+import java.io.File;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+public class NetworkTablesJNI {
+ static boolean libraryLoaded = false;
+ static File jniLibrary = null;
+ static {
+ if (!libraryLoaded) {
+ try {
+ String osname = System.getProperty("os.name");
+ String resname;
+ if (osname.startsWith("Windows"))
+ resname = "/Windows/" + System.getProperty("os.arch") + "/";
+ else
+ resname = "/" + osname + "/" + System.getProperty("os.arch") + "/";
+ System.out.println("platform: " + resname);
+ if (osname.startsWith("Windows"))
+ resname += "ntcore.dll";
+ else if (osname.startsWith("Mac"))
+ resname += "libntcore.dylib";
+ else
+ resname += "libntcore.so";
+ InputStream is = NetworkTablesJNI.class.getResourceAsStream(resname);
+ if (is != null) {
+ // create temporary file
+ if (System.getProperty("os.name").startsWith("Windows"))
+ jniLibrary = File.createTempFile("NetworkTablesJNI", ".dll");
+ else if (System.getProperty("os.name").startsWith("Mac"))
+ jniLibrary = File.createTempFile("libNetworkTablesJNI", ".dylib");
+ else
+ jniLibrary = File.createTempFile("libNetworkTablesJNI", ".so");
+ // flag for delete on exit
+ jniLibrary.deleteOnExit();
+ OutputStream os = new FileOutputStream(jniLibrary);
+
+ byte[] buffer = new byte[1024];
+ int readBytes;
+ try {
+ while ((readBytes = is.read(buffer)) != -1) {
+ os.write(buffer, 0, readBytes);
+ }
+ } finally {
+ os.close();
+ is.close();
+ }
+
+ System.load(jniLibrary.getAbsolutePath());
+ } else {
+ System.loadLibrary("ntcore");
+ }
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ System.exit(1);
+ }
+ libraryLoaded = true;
+ }
+ }
+
+ public static native boolean containsKey(String key);
+ public static native int getType(String key);
+
+ public static native boolean putBoolean(String key, boolean value);
+ public static native boolean putDouble(String key, double value);
+ public static native boolean putString(String key, String value);
+ public static native boolean putRaw(String key, byte[] value);
+ public static native boolean putRaw(String key, ByteBuffer value, int len);
+ public static native boolean putBooleanArray(String key, boolean[] value);
+ public static native boolean putDoubleArray(String key, double[] value);
+ public static native boolean putStringArray(String key, String[] value);
+
+ public static native void forcePutBoolean(String key, boolean value);
+ public static native void forcePutDouble(String key, double value);
+ public static native void forcePutString(String key, String value);
+ public static native void forcePutRaw(String key, byte[] value);
+ public static native void forcePutRaw(String key, ByteBuffer value, int len);
+ public static native void forcePutBooleanArray(String key, boolean[] value);
+ public static native void forcePutDoubleArray(String key, double[] value);
+ public static native void forcePutStringArray(String key, String[] value);
+
+ public static native Object getValue(String key) throws TableKeyNotDefinedException;
+ public static native boolean getBoolean(String key) throws TableKeyNotDefinedException;
+ public static native double getDouble(String key) throws TableKeyNotDefinedException;
+ public static native String getString(String key) throws TableKeyNotDefinedException;
+ public static native byte[] getRaw(String key) throws TableKeyNotDefinedException;
+ public static native boolean[] getBooleanArray(String key) throws TableKeyNotDefinedException;
+ public static native double[] getDoubleArray(String key) throws TableKeyNotDefinedException;
+ public static native String[] getStringArray(String key) throws TableKeyNotDefinedException;
+
+ public static native Object getValue(String key, Object defaultValue);
+ public static native boolean getBoolean(String key, boolean defaultValue);
+ public static native double getDouble(String key, double defaultValue);
+ public static native String getString(String key, String defaultValue);
+ public static native byte[] getRaw(String key, byte[] defaultValue);
+ public static native boolean[] getBooleanArray(String key, boolean[] defaultValue);
+ public static native double[] getDoubleArray(String key, double[] defaultValue);
+ public static native String[] getStringArray(String key, String[] defaultValue);
+
+ public static native void setEntryFlags(String key, int flags);
+ public static native int getEntryFlags(String key);
+
+ public static native void deleteEntry(String key);
+ public static native void deleteAllEntries();
+
+ public static native EntryInfo[] getEntries(String prefix, int types);
+
+ public static native void flush();
+
+ public interface EntryListenerFunction {
+ void apply(int uid, String key, Object value, int flags);
+ }
+ public static native int addEntryListener(String prefix, EntryListenerFunction listener, int flags);
+ public static native void removeEntryListener(int entryListenerUid);
+
+ public interface ConnectionListenerFunction {
+ void apply(int uid, boolean connected, ConnectionInfo conn);
+ }
+ public static native int addConnectionListener(ConnectionListenerFunction listener, boolean immediateNotify);
+ public static native void removeConnectionListener(int connListenerUid);
+
+ // public static native void createRpc(String key, byte[] def, IRpc rpc);
+ // public static native void createRpc(String key, ByteBuffer def, int def_len, IRpc rpc);
+ public static native byte[] getRpc(String key) throws TableKeyNotDefinedException;
+ public static native byte[] getRpc(String key, byte[] defaultValue);
+ public static native int callRpc(String key, byte[] params);
+ public static native int callRpc(String key, ByteBuffer params, int params_len);
+ // public static native byte[] getRpcResultBlocking(int callUid);
+ // public static native byte[] getRpcResultNonblocking(int callUid) throws RpcNoResponseException;
+
+ public static native void setNetworkIdentity(String name);
+ public static native void startServer(String persistFilename, String listenAddress, int port);
+ public static native void stopServer();
+ public static native void startClient(String serverName, int port);
+ public static native void stopClient();
+ public static native void setUpdateRate(double interval);
+
+ public static native ConnectionInfo[] getConnections();
+
+ public static native void savePersistent(String filename) throws PersistentException;
+ public static native String[] loadPersistent(String filename) throws PersistentException; // returns warnings
+
+ public static native long now();
+
+ public interface LoggerFunction {
+ void apply(int level, String file, int line, String msg);
+ }
+ public static native void setLogger(LoggerFunction func, int minLevel);
+}
diff --git a/java/src/edu/wpi/first/wpilibj/networktables/PersistentException.java b/java/src/edu/wpi/first/wpilibj/networktables/PersistentException.java
new file mode 100644
index 0000000..8d521fb
--- /dev/null
+++ b/java/src/edu/wpi/first/wpilibj/networktables/PersistentException.java
@@ -0,0 +1,18 @@
+package edu.wpi.first.wpilibj.networktables;
+
+import java.io.IOException;
+
+/**
+ * An exception thrown when persistent load/save fails in a {@link NetworkTable}
+ *
+ */
+public class PersistentException extends IOException {
+
+ /**
+ * @param message The error message
+ */
+ public PersistentException(String message) {
+ super(message);
+ }
+
+}
diff --git a/java/src/edu/wpi/first/wpilibj/networktables2/type/ArrayData.java b/java/src/edu/wpi/first/wpilibj/networktables2/type/ArrayData.java
new file mode 100644
index 0000000..e05f3a0
--- /dev/null
+++ b/java/src/edu/wpi/first/wpilibj/networktables2/type/ArrayData.java
@@ -0,0 +1,49 @@
+package edu.wpi.first.wpilibj.networktables2.type;
+
+/**
+ * @deprecated Use ArrayList instead.
+ */
+public class ArrayData {
+ private Object[] data = new Object[0];
+
+ protected Object getAsObject(int index) {
+ return data[index];
+ }
+ protected void _set(int index, Object value) {
+ data[index] = value;
+ }
+ protected void _add(Object value) {
+ setSize(size() + 1);
+ data[size() - 1] = value;
+ }
+ public void remove(int index) {
+ if (index < 0 || index >= size())
+ throw new IndexOutOfBoundsException();
+ if (index < size() - 1)
+ System.arraycopy(data, index + 1, data, index, size() - index - 1);
+ setSize(size() - 1);
+ }
+ public void setSize(int size) {
+ if (size == data.length)
+ return;
+ Object[] newArray = new Object[size];
+ if (size < data.length)
+ System.arraycopy(data, 0, newArray, 0, size);
+ else {
+ System.arraycopy(data, 0, newArray, 0, data.length);
+ for (int i = data.length; i < newArray.length; ++i)
+ newArray[i] = null;
+ }
+ data = newArray;
+ }
+ public int size() {
+ return data.length;
+ }
+
+ public Object[] getDataArray() {
+ return data;
+ }
+ public void setDataArray(Object[] value) {
+ data = value;
+ }
+}
diff --git a/java/src/edu/wpi/first/wpilibj/networktables2/type/BooleanArray.java b/java/src/edu/wpi/first/wpilibj/networktables2/type/BooleanArray.java
new file mode 100644
index 0000000..f2c78e6
--- /dev/null
+++ b/java/src/edu/wpi/first/wpilibj/networktables2/type/BooleanArray.java
@@ -0,0 +1,16 @@
+package edu.wpi.first.wpilibj.networktables2.type;
+
+/**
+ * @deprecated Use {@literal ArrayList<Boolean>} instead.
+ */
+public class BooleanArray extends ArrayData {
+ public boolean get(int index) {
+ return ((Boolean)getAsObject(index)).booleanValue();
+ }
+ public void set(int index, boolean value) {
+ _set(index, value?Boolean.TRUE:Boolean.FALSE);
+ }
+ public void add(boolean value) {
+ _add(value?Boolean.TRUE:Boolean.FALSE);
+ }
+}
diff --git a/java/src/edu/wpi/first/wpilibj/networktables2/type/NumberArray.java b/java/src/edu/wpi/first/wpilibj/networktables2/type/NumberArray.java
new file mode 100644
index 0000000..1066159
--- /dev/null
+++ b/java/src/edu/wpi/first/wpilibj/networktables2/type/NumberArray.java
@@ -0,0 +1,16 @@
+package edu.wpi.first.wpilibj.networktables2.type;
+
+/**
+ * @deprecated Use {@literal ArrayList<Double>} instead.
+ */
+public class NumberArray extends ArrayData {
+ public double get(int index) {
+ return ((Double)getAsObject(index)).doubleValue();
+ }
+ public void set(int index, double value) {
+ _set(index, new Double(value));
+ }
+ public void add(double value) {
+ _add(new Double(value));
+ }
+}
diff --git a/java/src/edu/wpi/first/wpilibj/networktables2/type/StringArray.java b/java/src/edu/wpi/first/wpilibj/networktables2/type/StringArray.java
new file mode 100644
index 0000000..5eea0d3
--- /dev/null
+++ b/java/src/edu/wpi/first/wpilibj/networktables2/type/StringArray.java
@@ -0,0 +1,16 @@
+package edu.wpi.first.wpilibj.networktables2.type;
+
+/**
+ * @deprecated Use {@literal ArrayList<String>} instead.
+ */
+public class StringArray extends ArrayData {
+ public String get(int index) {
+ return ((String)getAsObject(index));
+ }
+ public void set(int index, String value) {
+ _set(index, value);
+ }
+ public void add(String value) {
+ _add(value);
+ }
+}
diff --git a/java/src/edu/wpi/first/wpilibj/tables/IRemote.java b/java/src/edu/wpi/first/wpilibj/tables/IRemote.java
new file mode 100644
index 0000000..a79f740
--- /dev/null
+++ b/java/src/edu/wpi/first/wpilibj/tables/IRemote.java
@@ -0,0 +1,37 @@
+package edu.wpi.first.wpilibj.tables;
+
+
+/**
+ * Represents an object that has a remote connection
+ *
+ * @author Mitchell
+ *
+ */
+public interface IRemote {
+ /**
+ * Register an object to listen for connection and disconnection events
+ *
+ * @param listener the listener to be register
+ * @param immediateNotify if the listener object should be notified of the current connection state
+ */
+ public void addConnectionListener(IRemoteConnectionListener listener, boolean immediateNotify);
+
+ /**
+ * Unregister a listener from connection events
+ *
+ * @param listener the listener to be unregistered
+ */
+ public void removeConnectionListener(IRemoteConnectionListener listener);
+
+ /**
+ * Get the current state of the objects connection
+ * @return the current connection state
+ */
+ public boolean isConnected();
+
+ /**
+ * If the object is acting as a server
+ * @return if the object is a server
+ */
+ public boolean isServer();
+}
diff --git a/java/src/edu/wpi/first/wpilibj/tables/IRemoteConnectionListener.java b/java/src/edu/wpi/first/wpilibj/tables/IRemoteConnectionListener.java
new file mode 100644
index 0000000..cab9b1c
--- /dev/null
+++ b/java/src/edu/wpi/first/wpilibj/tables/IRemoteConnectionListener.java
@@ -0,0 +1,20 @@
+package edu.wpi.first.wpilibj.tables;
+
+/**
+ * A listener that listens for connection changes in a {@link IRemote} object
+ *
+ * @author Mitchell
+ *
+ */
+public interface IRemoteConnectionListener {
+ /**
+ * Called when an IRemote is connected
+ * @param remote the object that connected
+ */
+ public void connected(IRemote remote);
+ /**
+ * Called when an IRemote is disconnected
+ * @param remote the object that disconnected
+ */
+ public void disconnected(IRemote remote);
+}
diff --git a/java/src/edu/wpi/first/wpilibj/tables/ITable.java b/java/src/edu/wpi/first/wpilibj/tables/ITable.java
new file mode 100644
index 0000000..81d12be
--- /dev/null
+++ b/java/src/edu/wpi/first/wpilibj/tables/ITable.java
@@ -0,0 +1,547 @@
+package edu.wpi.first.wpilibj.tables;
+
+import java.nio.ByteBuffer;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+
+/**
+ * A table whose values can be read and written to
+ */
+public interface ITable {
+
+ /**
+ * Checks the table and tells if it contains the specified key
+ *
+ * @param key the key to search for
+ * @return true if the table as a value assigned to the given key
+ */
+ public boolean containsKey(String key);
+
+ /**
+ * @param key the key to search for
+ * @return true if there is a subtable with the key which contains at least
+ * one key/subtable of its own
+ */
+ public boolean containsSubTable(String key);
+
+ /**
+ * Returns the table at the specified key. If there is no table at the
+ * specified key, it will create a new table
+ *
+ * @param key the name of the table relative to this one
+ * @return a sub table relative to this one
+ */
+ public ITable getSubTable(String key);
+
+ /**
+ * @param types bitmask of types; 0 is treated as a "don't care".
+ * @return keys currently in the table
+ */
+ public Set<String> getKeys(int types);
+
+ /**
+ * @return keys currently in the table
+ */
+ public Set<String> getKeys();
+
+ /**
+ * @return subtables currently in the table
+ */
+ public Set<String> getSubTables();
+
+ /**
+ * Makes a key's value persistent through program restarts.
+ * The key cannot be null.
+ *
+ * @param key the key name
+ */
+ public void setPersistent(String key);
+
+ /**
+ * Stop making a key's value persistent through program restarts.
+ * The key cannot be null.
+ *
+ * @param key the key name
+ */
+ public void clearPersistent(String key);
+
+ /**
+ * Returns whether the value is persistent through program restarts.
+ * The key cannot be null.
+ *
+ * @param key the key name
+ * @return True if the value is persistent.
+ */
+ public boolean isPersistent(String key);
+
+ /**
+ * Sets flags on the specified key in this table. The key can
+ * not be null.
+ *
+ * @param key the key name
+ * @param flags the flags to set (bitmask)
+ */
+ public void setFlags(String key, int flags);
+
+ /**
+ * Clears flags on the specified key in this table. The key can
+ * not be null.
+ *
+ * @param key the key name
+ * @param flags the flags to clear (bitmask)
+ */
+ public void clearFlags(String key, int flags);
+
+ /**
+ * Returns the flags for the specified key.
+ *
+ * @param key the key name
+ * @return the flags, or 0 if the key is not defined
+ */
+ public int getFlags(String key);
+
+ /**
+ * Deletes the specified key in this table. The key can
+ * not be null.
+ *
+ * @param key the key name
+ */
+ public void delete(String key);
+
+ /**
+ * Gets the value associated with a key as an object. If the key does not
+ * exist, it will return the default value
+ * NOTE: If the value is a double, it will return a Double object,
+ * not a primitive. To get the primitive, use
+ * {@link #getDouble(String, double)}.
+ * @param key the key of the value to look up
+ * @return the value associated with the given key
+ * @throws TableKeyNotDefinedException if there is no value associated with
+ * the given key
+ * @deprecated This exception-raising method has been replaced by the
+ * default-taking method {@link #getValue(String, Object)}.
+ */
+ @Deprecated
+ public Object getValue(String key) throws TableKeyNotDefinedException;
+
+ /**
+ * Gets the value associated with a key as an object.
+ * NOTE: If the value is a double, it will return a Double object,
+ * not a primitive. To get the primitive, use
+ * {@link #getDouble(String, double)}.
+ * @param key the key of the value to look up
+ * @param defaultValue the default value if the key is null
+ * @return the value associated with the given key
+ */
+ public Object getValue(String key, Object defaultValue);
+
+ /**
+ * Put a value in the table
+ * @param key the key to be assigned to
+ * @param value the value that will be assigned
+ * @return False if the table key already exists with a different type
+ * @throws IllegalArgumentException when the value is not supported by the
+ * table
+ */
+ public boolean putValue(String key, Object value)
+ throws IllegalArgumentException;
+
+ /**
+ * Retrieve an array data type from the table.
+ * @param key the key to be assigned to
+ * @param externalValue the array data type to retreive into
+ * @throws TableKeyNotDefinedException if there is no value associated with
+ * the given key
+ * @deprecated Use get*Array functions instead.
+ */
+ @Deprecated
+ public void retrieveValue(String key, Object externalValue) throws TableKeyNotDefinedException;
+
+ /**
+ * Put a number in the table
+ * @param key the key to be assigned to
+ * @param value the value that will be assigned
+ * @return False if the table key already exists with a different type
+ */
+ public boolean putNumber(String key, double value);
+ /**
+ * Returns the number the key maps to.
+ * @param key the key to look up
+ * @return the value associated with the given key
+ * @throws TableKeyNotDefinedException if there is no value associated with
+ * the given key
+ * @deprecated This exception-raising method has been replaced by the
+ * default-taking method {@link #getNumber(String, double)}.
+ */
+ @Deprecated
+ public double getNumber(String key) throws TableKeyNotDefinedException;
+ /**
+ * Returns the number the key maps to. If the key does not exist or is of
+ * different type, it will return the default value.
+ * @param key the key to look up
+ * @param defaultValue the value to be returned if no value is found
+ * @return the value associated with the given key or the given default value
+ * if there is no value associated with the key
+ */
+ public double getNumber(String key, double defaultValue);
+
+ /**
+ * Put a string in the table
+ * @param key the key to be assigned to
+ * @param value the value that will be assigned
+ * @return False if the table key already exists with a different type
+ */
+ public boolean putString(String key, String value);
+ /**
+ * Returns the string the key maps to.
+ * @param key the key to look up
+ * @return the value associated with the given key
+ * @throws TableKeyNotDefinedException if there is no value associated with
+ * the given key
+ * @deprecated This exception-raising method has been replaced by the
+ * default-taking method {@link #getString(String, String)}.
+ */
+ @Deprecated
+ public String getString(String key) throws TableKeyNotDefinedException;
+ /**
+ * Returns the string the key maps to. If the key does not exist or is of
+ * different type, it will return the default value.
+ * @param key the key to look up
+ * @param defaultValue the value to be returned if no value is found
+ * @return the value associated with the given key or the given default value
+ * if there is no value associated with the key
+ */
+ public String getString(String key, String defaultValue);
+
+ /**
+ * Put a boolean in the table
+ * @param key the key to be assigned to
+ * @param value the value that will be assigned
+ * @return False if the table key already exists with a different type
+ */
+ public boolean putBoolean(String key, boolean value);
+ /**
+ * Returns the boolean the key maps to.
+ * @param key the key to look up
+ * @return the value associated with the given key
+ * @throws TableKeyNotDefinedException if there is no value associated with
+ * the given key
+ * @deprecated This exception-raising method has been replaced by the
+ * default-taking method {@link #getBoolean(String, boolean)}.
+ */
+ @Deprecated
+ public boolean getBoolean(String key) throws TableKeyNotDefinedException;
+ /**
+ * Returns the boolean the key maps to. If the key does not exist or is of
+ * different type, it will return the default value.
+ * @param key the key to look up
+ * @param defaultValue the value to be returned if no value is found
+ * @return the value associated with the given key or the given default value
+ * if there is no value associated with the key
+ */
+ public boolean getBoolean(String key, boolean defaultValue);
+
+ /**
+ * Put a boolean array in the table
+ * @param key the key to be assigned to
+ * @param value the value that will be assigned
+ * @return False if the table key already exists with a different type
+ */
+ public boolean putBooleanArray(String key, boolean[] value);
+ /**
+ * Put a boolean array in the table
+ * @param key the key to be assigned to
+ * @param value the value that will be assigned
+ * @return False if the table key already exists with a different type
+ */
+ public boolean putBooleanArray(String key, Boolean[] value);
+ /**
+ * Returns the boolean array the key maps to.
+ * @param key the key to look up
+ * @return the value associated with the given key
+ * @throws TableKeyNotDefinedException if there is no value associated with
+ * the given key
+ * @deprecated This exception-raising method has been replaced by the
+ * default-taking method {@link #getBooleanArray(String, boolean[])}.
+ */
+ @Deprecated
+ public boolean[] getBooleanArray(String key) throws TableKeyNotDefinedException;
+ /**
+ * Returns the boolean array the key maps to. If the key does not exist or is
+ * of different type, it will return the default value.
+ * @param key the key to look up
+ * @param defaultValue the value to be returned if no value is found
+ * @return the value associated with the given key or the given default value
+ * if there is no value associated with the key
+ */
+ public boolean[] getBooleanArray(String key, boolean[] defaultValue);
+ /**
+ * Returns the boolean array the key maps to. If the key does not exist or is
+ * of different type, it will return the default value.
+ * @param key the key to look up
+ * @param defaultValue the value to be returned if no value is found
+ * @return the value associated with the given key or the given default value
+ * if there is no value associated with the key
+ */
+ public Boolean[] getBooleanArray(String key, Boolean[] defaultValue);
+
+ /**
+ * Put a number array in the table
+ * @param key the key to be assigned to
+ * @param value the value that will be assigned
+ * @return False if the table key already exists with a different type
+ */
+ public boolean putNumberArray(String key, double[] value);
+ /**
+ * Put a number array in the table
+ * @param key the key to be assigned to
+ * @param value the value that will be assigned
+ * @return False if the table key already exists with a different type
+ */
+ public boolean putNumberArray(String key, Double[] value);
+ /**
+ * Returns the number array the key maps to.
+ * @param key the key to look up
+ * @return the value associated with the given key
+ * @throws TableKeyNotDefinedException if there is no value associated with
+ * the given key
+ * @deprecated This exception-raising method has been replaced by the
+ * default-taking method {@link #getNumberArray(String, double[])}.
+ */
+ @Deprecated
+ public double[] getNumberArray(String key) throws TableKeyNotDefinedException;
+ /**
+ * Returns the number array the key maps to. If the key does not exist or is
+ * of different type, it will return the default value.
+ * @param key the key to look up
+ * @param defaultValue the value to be returned if no value is found
+ * @return the value associated with the given key or the given default value
+ * if there is no value associated with the key
+ */
+ public double[] getNumberArray(String key, double[] defaultValue);
+ /**
+ * Returns the number array the key maps to. If the key does not exist or is
+ * of different type, it will return the default value.
+ * @param key the key to look up
+ * @param defaultValue the value to be returned if no value is found
+ * @return the value associated with the given key or the given default value
+ * if there is no value associated with the key
+ */
+ public Double[] getNumberArray(String key, Double[] defaultValue);
+
+ /**
+ * Put a string array in the table
+ * @param key the key to be assigned to
+ * @param value the value that will be assigned
+ * @return False if the table key already exists with a different type
+ */
+ public boolean putStringArray(String key, String[] value);
+ /**
+ * Returns the string array the key maps to.
+ * @param key the key to look up
+ * @return the value associated with the given key
+ * @throws TableKeyNotDefinedException if there is no value associated with
+ * the given key
+ * @deprecated This exception-raising method has been replaced by the
+ * default-taking method {@link #getStringArray(String, String[])}.
+ */
+ @Deprecated
+ public String[] getStringArray(String key) throws TableKeyNotDefinedException;
+ /**
+ * Returns the string array the key maps to. If the key does not exist or is
+ * of different type, it will return the default value.
+ * @param key the key to look up
+ * @param defaultValue the value to be returned if no value is found
+ * @return the value associated with the given key or the given default value
+ * if there is no value associated with the key
+ */
+ public String[] getStringArray(String key, String[] defaultValue);
+
+ /**
+ * Put a raw value (byte array) in the table
+ * @param key the key to be assigned to
+ * @param value the value that will be assigned
+ * @return False if the table key already exists with a different type
+ */
+ public boolean putRaw(String key, byte[] value);
+ /**
+ * Put a raw value (bytes from a byte buffer) in the table
+ * @param key the key to be assigned to
+ * @param value the value that will be assigned
+ * @param len the length of the value
+ * @return False if the table key already exists with a different type
+ */
+ public boolean putRaw(String key, ByteBuffer value, int len);
+ /**
+ * Returns the raw value (byte array) the key maps to.
+ * @param key the key to look up
+ * @return the value associated with the given key
+ * @throws TableKeyNotDefinedException if there is no value associated with
+ * the given key
+ * @deprecated This exception-raising method has been replaced by the
+ * default-taking method {@link #getRaw(String, byte[])}.
+ */
+ @Deprecated
+ public byte[] getRaw(String key) throws TableKeyNotDefinedException;
+ /**
+ * Returns the raw value (byte array) the key maps to. If the key does not
+ * exist or is of different type, it will return the default value.
+ * @param key the key to look up
+ * @param defaultValue the value to be returned if no value is found
+ * @return the value associated with the given key or the given default value
+ * if there is no value associated with the key
+ */
+ public byte[] getRaw(String key, byte[] defaultValue);
+
+ /** Notifier flag values. */
+ public static final int NOTIFY_IMMEDIATE = 0x01;
+ public static final int NOTIFY_LOCAL = 0x02;
+ public static final int NOTIFY_NEW = 0x04;
+ public static final int NOTIFY_DELETE = 0x08;
+ public static final int NOTIFY_UPDATE = 0x10;
+ public static final int NOTIFY_FLAGS = 0x20;
+
+ /**
+ * Add a listener for changes to the table
+ * @param listener the listener to add
+ */
+ public void addTableListener(ITableListener listener);
+ /**
+ * Add a listener for changes to the table
+ * @param listener the listener to add
+ * @param immediateNotify if true then this listener will be notified of all
+ * current entries (marked as new)
+ */
+ public void addTableListener(ITableListener listener,
+ boolean immediateNotify);
+ /**
+ * Add a listener for changes to the table
+ * @param listener the listener to add
+ * @param flags bitmask specifying desired notifications
+ */
+ public void addTableListenerEx(ITableListener listener, int flags);
+
+ /**
+ * Add a listener for changes to a specific key the table
+ * @param key the key to listen for
+ * @param listener the listener to add
+ * @param immediateNotify if true then this listener will be notified of all
+ * current entries (marked as new)
+ */
+ public void addTableListener(String key, ITableListener listener,
+ boolean immediateNotify);
+ /**
+ * Add a listener for changes to a specific key the table
+ * @param key the key to listen for
+ * @param listener the listener to add
+ * @param flags bitmask specifying desired notifications
+ */
+ public void addTableListenerEx(String key, ITableListener listener,
+ int flags);
+ /**
+ * This will immediately notify the listener of all current sub tables
+ * @param listener the listener to notify
+ */
+ public void addSubTableListener(final ITableListener listener);
+ /**
+ * This will immediately notify the listener of all current sub tables
+ * @param listener the listener to notify
+ * @param localNotify if true then this listener will be notified of all
+ * local changes in addition to all remote changes
+ */
+ public void addSubTableListener(final ITableListener listener,
+ boolean localNotify);
+ /**
+ * Remove a listener from receiving table events
+ * @param listener the listener to be removed
+ */
+ public void removeTableListener(ITableListener listener);
+
+ /*
+ * Deprecated Methods
+ */
+
+ /**
+ * Maps the specified key to the specified value in this table.
+ * The key can not be null.
+ * The value can be retrieved by calling the get method with a key that is
+ * equal to the original key.
+ * @param key the key
+ * @param value the value
+ * @return False if the table key already exists with a different type
+ * @throws IllegalArgumentException if key is null
+ * @deprecated Use {@link #putNumber(String, double)} instead.
+ */
+ @Deprecated
+ public boolean putInt(String key, int value);
+
+ /**
+ * Returns the value at the specified key.
+ * @param key the key
+ * @return the value
+ * @throws TableKeyNotDefinedException if there is no value mapped to by the
+ * key
+ * @throws IllegalArgumentException if the value mapped to by the key is not
+ * an int
+ * @throws IllegalArgumentException if the key is null
+ * @deprecated Use {@link #getNumber(String, double)} instead.
+ */
+ @Deprecated
+ public int getInt(String key) throws TableKeyNotDefinedException;
+
+ /**
+ * Returns the value at the specified key.
+ * @param key the key
+ * @param defaultValue the value returned if the key is undefined
+ * @return the value
+ * @throws IllegalArgumentException if the value mapped to by the key is not
+ * an int
+ * @throws IllegalArgumentException if the key is null
+ * @deprecated Use {@link #getNumber(String, double)} instead.
+ */
+ @Deprecated
+ public int getInt(String key, int defaultValue)
+ throws TableKeyNotDefinedException;
+
+ /**
+ * Maps the specified key to the specified value in this table.
+ * The key can not be null.
+ * The value can be retrieved by calling the get method with a key that is
+ * equal to the original key.
+ * @param key the key
+ * @param value the value
+ * @return False if the table key already exists with a different type
+ * @throws IllegalArgumentException if key is null
+ * @deprecated Use {@link #putNumber(String, double)} instead.
+ */
+ @Deprecated
+ public boolean putDouble(String key, double value);
+
+ /**
+ * Returns the value at the specified key.
+ * @param key the key
+ * @return the value
+ * @throws TableKeyNotDefinedException if there is no
+ * value mapped to by the key
+ * @throws IllegalArgumentException if the value mapped to by the key is not a
+ * double
+ * @throws IllegalArgumentException if the key is null
+ * @deprecated Use {@link #getNumber(String, double)} instead.
+ */
+ @Deprecated
+ public double getDouble(String key) throws TableKeyNotDefinedException;
+
+ /**
+ * Returns the value at the specified key.
+ * @param key the key
+ * @param defaultValue the value returned if the key is undefined
+ * @return the value
+ * @throws IllegalArgumentException if the value mapped to by the key is not a
+ * double
+ * @throws IllegalArgumentException if the key is null
+ * @deprecated Use {@link #getNumber(String, double)} instead.
+ */
+ @Deprecated
+ public double getDouble(String key, double defaultValue);
+}
diff --git a/java/src/edu/wpi/first/wpilibj/tables/ITableListener.java b/java/src/edu/wpi/first/wpilibj/tables/ITableListener.java
new file mode 100644
index 0000000..e1d9259
--- /dev/null
+++ b/java/src/edu/wpi/first/wpilibj/tables/ITableListener.java
@@ -0,0 +1,35 @@
+package edu.wpi.first.wpilibj.tables;
+
+/**
+ * A listener that listens to changes in values in a {@link ITable}
+ *
+ * @author Mitchell
+ *
+ */
+@FunctionalInterface
+public interface ITableListener {
+ /**
+ * Called when a key-value pair is changed in a {@link ITable}
+ * @param source the table the key-value pair exists in
+ * @param key the key associated with the value that changed
+ * @param value the new value
+ * @param isNew true if the key did not previously exist in the table, otherwise it is false
+ */
+ public void valueChanged(ITable source, String key, Object value, boolean isNew);
+
+ /**
+ * Extended version of valueChanged. Called when a key-value pair is
+ * changed in a {@link ITable}. The default implementation simply calls
+ * valueChanged(). If this is overridden, valueChanged() will not be
+ * called.
+ * @param source the table the key-value pair exists in
+ * @param key the key associated with the value that changed
+ * @param value the new value
+ * @param flags update flags; for example, NOTIFY_NEW if the key did not
+ * previously exist in the table
+ */
+ default public void valueChangedEx(ITable source, String key, Object value, int flags) {
+ // NOTIFY_NEW = 0x04
+ valueChanged(source, key, value, (flags & 0x04) != 0);
+ }
+}
diff --git a/java/src/edu/wpi/first/wpilibj/tables/TableKeyNotDefinedException.java b/java/src/edu/wpi/first/wpilibj/tables/TableKeyNotDefinedException.java
new file mode 100644
index 0000000..4ca3a54
--- /dev/null
+++ b/java/src/edu/wpi/first/wpilibj/tables/TableKeyNotDefinedException.java
@@ -0,0 +1,20 @@
+package edu.wpi.first.wpilibj.tables;
+
+import java.util.NoSuchElementException;
+
+/**
+ * An exception throw when the lookup a a key-value fails in a {@link ITable}
+ *
+ * @author Mitchell
+ *
+ */
+public class TableKeyNotDefinedException extends NoSuchElementException {
+
+ /**
+ * @param key the key that was not defined in the table
+ */
+ public TableKeyNotDefinedException(String key) {
+ super("Unknown Table Key: "+key);
+ }
+
+}
diff --git a/java/test/Client.java b/java/test/Client.java
new file mode 100644
index 0000000..7f18690
--- /dev/null
+++ b/java/test/Client.java
@@ -0,0 +1,39 @@
+import edu.wpi.first.wpilibj.networktables.*;
+import edu.wpi.first.wpilibj.tables.*;
+
+public class Client {
+ private static class MyLogger implements NetworkTablesJNI.LoggerFunction {
+ public void apply(int level, String file, int line, String msg) {
+ System.err.println(msg);
+ }
+ }
+
+ public static void main(String[] args) {
+ NetworkTablesJNI.setLogger(new MyLogger(), 0);
+ NetworkTable.setIPAddress("127.0.0.1");
+ NetworkTable.setPort(10000);
+ NetworkTable.setClientMode();
+ NetworkTable nt = NetworkTable.getTable("");
+ try { Thread.sleep(2000); } catch (InterruptedException e) {}
+ try {
+ System.out.println("Got foo: " + nt.getNumber("foo"));
+ } catch(TableKeyNotDefinedException ex) {
+ }
+ nt.putBoolean("bar", false);
+ nt.setFlags("bar", NetworkTable.PERSISTENT);
+ nt.putBoolean("bar2", true);
+ nt.putBoolean("bar2", false);
+ nt.putBoolean("bar2", true);
+ nt.putString("str", "hello world");
+ double[] nums = new double[3];
+ nums[0] = 0.5;
+ nums[1] = 1.2;
+ nums[2] = 3.0;
+ nt.putNumberArray("numarray", nums);
+ String[] strs = new String[2];
+ strs[0] = "Hello";
+ strs[1] = "World";
+ nt.putStringArray("strarray", strs);
+ try { Thread.sleep(10000); } catch (InterruptedException e) {}
+ }
+}
diff --git a/java/test/Server.java b/java/test/Server.java
new file mode 100644
index 0000000..33844fb
--- /dev/null
+++ b/java/test/Server.java
@@ -0,0 +1,26 @@
+import edu.wpi.first.wpilibj.networktables.*;
+import edu.wpi.first.wpilibj.tables.*;
+
+public class Server {
+ private static class MyLogger implements NetworkTablesJNI.LoggerFunction {
+ public void apply(int level, String file, int line, String msg) {
+ System.err.println(msg);
+ }
+ }
+
+ public static void main(String[] args) {
+ NetworkTablesJNI.setLogger(new MyLogger(), 0);
+ NetworkTable.setIPAddress("127.0.0.1");
+ NetworkTable.setPort(10000);
+ NetworkTable.setServerMode();
+ NetworkTable nt = NetworkTable.getTable("");
+ try { Thread.sleep(1000); } catch (InterruptedException e) {}
+ nt.putNumber("foo", 0.5);
+ nt.setFlags("foo", NetworkTable.PERSISTENT);
+ nt.putNumber("foo2", 0.5);
+ nt.putNumber("foo2", 0.7);
+ nt.putNumber("foo2", 0.6);
+ nt.putNumber("foo2", 0.5);
+ try { Thread.sleep(10000); } catch (InterruptedException e) {}
+ }
+}