from __future__ import print_function import sys import os import re try: import configparser except ImportError: import ConfigParser as configparser from nivision_parse import * # base, cast-out-pre, cast-out-post, cast-in-pre, cast-in-post java_accessor_map = { "B": ("", "", "", "", ""), "C": ("Char", "", "", "", ""), "S": ("Short", "", "", "", ""), "I": ("Int", "", "", "", ""), "J": ("Long", "", "", "", ""), "F": ("Float", "", "", "", ""), "D": ("Double", "", "", "", ""), "Z": ("Boolean", "", "", "", ""), "X": ("", "(short)(", " & 0xff)", "(byte)(", " & 0xff)"), "Y": ("Short", "(int)(", " & 0xffff)", "(short)(", " & 0xffff)"), } java_size_map = { "B": 1, "C": 2, "S": 2, "I": 4, "J": 8, "F": 4, "D": 8, "Z": 1, } class JavaType: def __init__(self, j_type, jn_type, jni_type, jni_sig, is_enum=False, is_struct=False, is_opaque=False, string_array=False, array_size=None): self.j_type = j_type self.jn_type = jn_type self.jni_type = jni_type self.jni_sig = jni_sig self.is_enum = is_enum self.is_struct = is_struct self.is_opaque = is_opaque self.string_array = string_array self.array_size = array_size def copy(self): return JavaType(self.j_type, self.jn_type, self.jni_type, self.jni_sig, is_enum=self.is_enum, is_struct=self.is_struct, is_opaque=self.is_opaque, string_array=self.string_array, array_size=self.array_size) def __repr__(self): return "JavaType(%s, %s, %s, %s, is_enum=%s, is_struct=%s, is_opaque=%s, string_array=%s, array_size=%s)" % ( self.j_type, self.jn_type, self.jni_type, self.jni_sig, self.is_enum, self.is_struct, self.is_opaque, self.string_array, self.array_size) java_types_map = { ("void", None): JavaType("void", "void", "void", None), ("env", None): JavaType("", "", "JNIEnv*", None), ("cls", None): JavaType("", "", "jclass", None), ("int", None): JavaType("int", "int", "jint", "I"), ("char", None): JavaType("byte", "byte", "jbyte", "B"), ("wchar_t", None): JavaType("char", "char", "jchar", "C"), ("unsigned char", None): JavaType("short", "short", "jshort", "X"), ("short", None): JavaType("short", "short", "jshort", "S"), ("unsigned short", None): JavaType("int", "int", "jint", "Y"), ("unsigned", None): JavaType("int", "int", "jint", "I"), ("unsigned int", None): JavaType("int", "int", "jint", "I"), ("uInt32", None): JavaType("int", "int", "jint", "I"), ("IMAQdxSession", None): JavaType("int", "int", "jint", "I"), ("bool32", None): JavaType("int", "int", "jint", "I"), ("long", None): JavaType("long", "long", "jlong", "J"), ("unsigned long", None): JavaType("long", "long", "jlong", "J"), ("__int64", None): JavaType("long", "long", "jlong", "J"), ("long long", None): JavaType("long", "long", "jlong", "J"), ("unsigned __int64", None): JavaType("long", "long", "jlong", "J"), ("__uint64", None): JavaType("long", "long", "jlong", "J"), ("unsigned long long", None): JavaType("long", "long", "jlong", "J"), ("float", None): JavaType("float", "float", "jfloat", "F"), ("double", None): JavaType("double", "double", "jdouble", "D"), ("long double", None): JavaType("double", "double", "jdouble", "D"), ("unsigned char*", None): JavaType("String", "String", "jstring", "Ljava/lang/String;"), ("char*", None): JavaType("String", "String", "jstring", "Ljava/lang/String;"), ("void*", None): JavaType("RawData", "long", "jlong", "J", is_opaque=True), #("size_t", None): JavaType("long", "long", "jlong", "J"), ("String255", None): JavaType("String", "String", "jstring", "Ljava/lang/String;", string_array=True, array_size="256"), ("String255", ""): JavaType("String[]", "String[]", "jstringArray", "[Ljava/lang/String;", string_array=True, array_size="256"), ("char*", ""): JavaType("String[]", "String[]", "jstringArray", "[Ljava/lang/String;"), ("char", ""): JavaType("String", "String", "jstring", "Ljava/lang/String;", string_array=True, array_size=""), ("unsigned char", ""): JavaType("byte[]", "byte[]", "jbyteArray", "[B"), ("short", ""): JavaType("short[]", "short[]", "jshortArray", "[S"), ("int", ""): JavaType("int[]", "int[]", "jintArray", "[I"), ("unsigned int", ""): JavaType("int[]", "int[]", "jintArray", "[I"), ("uInt32", ""): JavaType("int[]", "int[]", "jintArray", "[I"), ("long", ""): JavaType("long[]", "long[]", "jlongArray", "[J"), ("float", ""): JavaType("float[]", "float[]", "jfloatArray", "[F"), ("double", ""): JavaType("double[]", "double[]", "jdoubleArray", "[D"), } def c_to_jtype(name, arr): jtype = java_types_map.get((name, arr), None) if jtype is not None: return jtype # sized array is treated the same as unsized if arr is not None and arr != "": jtype = c_to_jtype(name, "").copy() jtype.array_size = arr java_types_map[(name, arr)] = jtype # cache return jtype # Opaque structures if name in opaque_structs: if arr is None: jtype = JavaType(name, "long", "jlong", "J", is_opaque=True) else: # FIXME jtype = JavaType(name+"[]", "long[]", "jlongArray", "[J", is_opaque=True) java_types_map[(name, arr)] = jtype # cache return jtype # Enums if name in enums: if arr is None: jtype = JavaType(name, "int", "jint", "I", is_enum=True) else: # FIXME jtype = JavaType(name+"[]", "int[]", "jintArray", "[I", is_enum=True) java_types_map[(name, arr)] = jtype # cache return jtype # handle pointers as void* (FIXME) if name[-1] == '*': if name[:-1] not in structs and name[:-1] not in defined: return java_types_map[("void*", None)] return c_to_jtype(name[:-1], arr) # Otherwise it's a normal structure object if arr is None: jtype = JavaType(name, "long", "jlong", "J", is_struct=True) else: # FIXME jtype = JavaType(name+"[]", "long[]", "jlongArray", "[J", is_struct=True) java_types_map[(name, arr)] = jtype return jtype class JavaEmitData: def __init__(self): self.construct = [] self.backingRead = [] self.read = [] self.writeBufs = [] self.write = [] self.backingWrite = [] self.toArg = "" def addConstruct(self, s): self.construct.extend(s.split('\n')[1 if s[0]=='\n' else 0:]) def addBackingRead(self, s): self.backingRead.extend(s.split('\n')[1 if s[0]=='\n' else 0:]) def addRead(self, s): self.read.extend(s.split('\n')[1 if s[0]=='\n' else 0:]) def addWriteBuf(self, s): self.writeBufs.append(s) def addWrite(self, s): self.write.extend(s.split('\n')[1 if s[0]=='\n' else 0:]) def addBackingWrite(self, s): self.backingWrite.extend(s.split('\n')[1 if s[0]=='\n' else 0:]) class JavaEmitArrayData(JavaEmitData): def __init__(self): JavaEmitData.__init__(self) self.addConstruct("{fname} = new {ftype_one}[0];") self.addBackingRead("int {size_fname} = {backing}.get{jaccessor}({size_foffset});") self.addBackingWrite("{backing}.put{jaccessor}({size_foffset}, {fname}.length);") # sized array of null-terminated strings strzArrayEmitSized = JavaEmitArrayData() strzArrayEmitSized.addBackingRead("long {fname}_addr = getPointer({backing}, {foffset});") strzArrayEmitSized.addRead(""" {fname} = new String[{size_fname}]; if ({size_fname} > 0 && {fname}_addr != 0) {{ ByteBuffer bb = newDirectByteBuffer({fname}_addr, {size_fname}*{pointer_sz}); for (int i=0, off=0; i<{size_fname}; i++, off += {pointer_sz}) {{ long addr = getPointer(bb, off); if (addr == 0) {fname}[i] = null; else {{ ByteBuffer bb2 = newDirectByteBuffer(addr, 1000); // FIXME while (bb2.get() != 0) {{}} byte[] bytes = new byte[bb2.position()-1]; bb2.rewind(); getBytes(bb2, bytes, 0, bytes.length); try {{ {fname}[i] = new String(bytes, "UTF-8"); }} catch (UnsupportedEncodingException e) {{ {fname}[i] = ""; }} }} }} }}""") strzArrayEmitSized.addWriteBuf("{buftype} {fname}_buf") strzArrayEmitSized.addWriteBuf("{buftype}[] {fname}_bufs") strzArrayEmitSized.addWrite(""" {fname}_buf = ByteBuffer.allocateDirect({fname}.length*{pointer_sz}).order(ByteOrder.nativeOrder()); for (int i=0, off=0; i<{fname}.length; i++, off += {pointer_sz}) {{ if ({fname}[i] == null) putPointer({fname}_buf, off, 0); else {{ byte[] bytes; try {{ bytes = {fname}[i].getBytes("UTF-8"); }} catch (UnsupportedEncodingException e) {{ bytes = new byte[0]; }} {fname}_bufs[i] = ByteBuffer.allocateDirect(bytes.length+1); putBytes({fname}_bufs[i], bytes, 0, bytes.length).put(bytes.length, (byte)0); putPointer({fname}_buf, off, getByteBufferAddress({fname}_bufs[i])); }} }}""") strzArrayEmitSized.addBackingWrite("putPointer({backing}, {foffset}, {fname}_buf);") # unsized array; final terminating zero determines the length strzArrayEmitUnsized = JavaEmitData() strzArrayEmitUnsized.addConstruct("{fname} = new {ftype_one}[0];") strzArrayEmitUnsized.addBackingRead("long {fname}_addr = getPointer({backing}, {foffset});") strzArrayEmitUnsized.addRead(""" {{ if ({fname}_addr == 0) {fname} = new {ftype_one}[0]; else {{ // prescan to find length ByteBuffer bb = newDirectByteBuffer({fname}_addr, 1000*{pointer_sz}); // FIXME int size = 0; for (int off=0; getPointer(bb, off) != 0; size++, off += {pointer_sz}) {{ }} {fname} = new String[size]; for (int i=0, off=0; i 0 && {fname}_addr != 0) {{ ByteBuffer bb = newDirectByteBuffer({fname}_addr, {size_fname}*%d); for (int i=0, off=0; i<{size_fname}; i++, off += %d) {{ {fname}[i] = {ftype_one}.fromValue(bb.getInt(off)); }} }}""" % (4, 4)) enumArrayEmit.addWriteBuf("{buftype} {fname}_buf") enumArrayEmit.addWrite(""" {fname}_buf = ByteBuffer.allocateDirect({fname}.length*%d).order(ByteOrder.nativeOrder()); for (int i=0, off=0; i<{fname}.length; i++, off += %d) {{ if ({fname} != null) {fname}_buf.putInt(off, {fname}[i].getValue()); }}""" % (4, 4)) enumArrayEmit.addBackingWrite("putPointer({backing}, {foffset}, {fname}_buf);") enumArrayEmit.toArg = "getByteBufferAddress({fname}_buf)" # array of opaque structures opaqueArrayEmit = JavaEmitArrayData() opaqueArrayEmit.addBackingRead("long {fname}_addr = getPointer({backing}, {foffset});") opaqueArrayEmit.addRead(""" {fname} = new {ftype_one}[{size_fname}]; if ({size_fname} > 0 && {fname}_addr != 0) {{ ByteBuffer bb = newDirectByteBuffer({fname}_addr, {size_fname}*{pointer_sz}); for (int i=0, off=0; i<{size_fname}; i++, off += {pointer_sz}) {{ {fname}[i] = new {ftype_one}(getPointer(bb, off), false); }} }}""") opaqueArrayEmit.addWriteBuf("{buftype} {fname}_buf") opaqueArrayEmit.addWrite(""" {fname}_buf = ByteBuffer.allocateDirect({fname}.length*{pointer_sz}).order(ByteOrder.nativeOrder()); for (int i=0, off=0; i<{fname}.length; i++, off += {pointer_sz}) {{ putPointer({fname}_buf, off, {fname}[i]); }}""") opaqueArrayEmit.addBackingWrite("putPointer({backing}, {foffset}, {fname}_buf);") opaqueArrayEmit.toArg = "getByteBufferAddress({fname}_buf)" # array of String255 string255ArrayEmit = JavaEmitArrayData() string255ArrayEmit.addBackingRead(""" {fname} = new String[{size_fname}]; if ({size_fname} > 0) {{ byte[] bytes = new byte[%d]; int len; for (int i=0, off={foffset}; i<{size_fname}; i++, off += %d) {{ getBytes({backing}, bytes, off, %d); for (len=0; len 0 && {fname}_addr != 0) {{ ByteBuffer bb = newDirectByteBuffer({fname}_addr, {size_fname}*{struct_sz}); for (int i=0, off=0; i<{size_fname}; i++, off += {struct_sz}) {{ {fname}[i] = new {ftype_one}(bb, off); {fname}[i].read(); }} }}""") structArrayEmit.addWriteBuf("{buftype} {fname}_buf") # FIXME: This can be optimized for the read->write case. structArrayEmit.addWrite(""" {fname}_buf = ByteBuffer.allocateDirect({fname}.length*{struct_sz}).order(ByteOrder.nativeOrder()); for (int i=0, off=0; i<{fname}.length; i++, off += {struct_sz}) {{ {fname}[i].setBuffer({fname}_buf, off); {fname}[i].write(); }}""") structArrayEmit.addBackingWrite("putPointer({backing}, {foffset}, {fname}_buf);") structArrayEmit.toArg = "getByteBufferAddress({fname}_buf)" # array of bytes byteArrayEmit = JavaEmitArrayData() byteArrayEmit.addBackingRead("long {fname}_addr = getPointer({backing}, {foffset});") byteArrayEmit.addRead(""" {fname} = new {ftype_one}[{size_fname}]; if ({size_fname} > 0 && {fname}_addr != 0) {{ getBytes(newDirectByteBuffer({fname}_addr, {size_fname}), {fname}, 0, {size_fname}); }}""") byteArrayEmit.addWriteBuf("{buftype} {fname}_buf") byteArrayEmit.addWrite(""" {fname}_buf = ByteBuffer.allocateDirect({fname}.length); putBytes({fname}_buf, {fname}, 0, {fname}.length);""") byteArrayEmit.addBackingWrite("putPointer({backing}, {foffset}, {fname}_buf);") byteArrayEmit.toArg = "getByteBufferAddress({fname}_buf)" # array of java types jtypeArrayEmit = JavaEmitArrayData() jtypeArrayEmit.addBackingRead("long {fname}_addr = getPointer({backing}, {foffset});") jtypeArrayEmit.addRead("""{fname} = new {ftype_one}[{size_fname}]; if ({size_fname} > 0 && {fname}_addr != 0) {{ newDirectByteBuffer({fname}_addr, {size_fname}*{struct_sz}).as{buftype}().get({fname}); }}""") jtypeArrayEmit.addWriteBuf("ByteBuffer {fname}_buf") jtypeArrayEmit.addWrite(""" {fname}_buf = ByteBuffer.allocateDirect({fname}.length*{struct_sz}).order(ByteOrder.nativeOrder()); {fname}_buf.as{buftype}().put({fname}).rewind();""") jtypeArrayEmit.addBackingWrite("putPointer({backing}, {foffset}, {fname}_buf);") jtypeArrayEmit.toArg = "getByteBufferAddress({fname}_buf)" # enum enumEmit = JavaEmitData() enumEmit.addBackingRead("{fname} = {ftype}.fromValue({backing}.getInt({foffset}));") enumEmit.addBackingWrite("""if ({fname} != null) {backing}.putInt({foffset}, {fname}.getValue());""") enumEmit.toArg = "{fname}.getValue()" # opaque structure opaqueEmit = JavaEmitData() opaqueEmit.addBackingRead("long {fname}_addr = getPointer({backing}, {foffset});") opaqueEmit.addRead("""if ({fname}_addr == 0) {fname} = null; else {fname} = new {ftype}({fname}_addr, false);""") opaqueEmit.addBackingWrite("putPointer({backing}, {foffset}, {fname});") opaqueEmit.toArg = "{fname}.getAddress()" # inline normal structure structEmit = JavaEmitData() structEmit.addConstruct("{fname} = new {ftype}({backing}, {foffset});") structEmit.addRead("{fname}.read();") structEmit.addWrite("{fname}.write();") structEmit.toArg = "{fname}.getAddress()" # java type jtypeEmit = JavaEmitData() jtypeEmit.addBackingRead("{fname} = {jaccessor_cast_out_pre}{backing}.get{jaccessor}({foffset}){jaccessor_cast_out_post};") jtypeEmit.addBackingWrite("{backing}.put{jaccessor}({foffset}, {jaccessor_cast_in_pre}{fname}{jaccessor_cast_in_post});") # string - array of characters strSizedEmit = JavaEmitData() strSizedEmit.addBackingRead("""{{ byte[] bytes = new byte[{array_size}]; getBytes({backing}, bytes, {foffset}, {array_size}); int len; for (len=0; len 0 and read[0][0] == '{': read[0] = ifcheck + read[0] else: read = (" " + "\n ".join(read)).split('\n') read.insert(0, ifcheck + "{") read.append("}") if len(write[0]) > 0 and write[0][0] == '{': write[0] = ifcheck + write[0] else: write = (" " + "\n ".join(write)).split('\n') write.insert(0, ifcheck + "{") write.append("}") jread.extend(read) jwrite.extend(write) jfielddefs.extend(jfielddefs_private) # Java definition p1 = """ public static class {name} extends DisposedStruct {{ {jfielddefs} private void init() {{ {jconstruct} }} public {name}() {{ super({size}); init(); }}""" if jcargs: p2 = """ public {name}({jcargs}) {{ super({size}); {jcinit} }}""" else: p2 = "" p3 = """ protected {name}(ByteBuffer backing, int offset) {{ super(backing, offset, {size}); init(); }} protected {name}(long nativeObj, boolean owned) {{ super(nativeObj, owned, {size}); init(); }} protected void setBuffer(ByteBuffer backing, int offset) {{ super.setBuffer(backing, offset, {size}); }} public void read() {{ {jread} }} public void write() {{ {jwrite} }} public int size() {{ return {size}; }} }}""" return "".join([p1,p2,p3]).format( name=self.name, jfielddefs="\n ".join(jfielddefs), jread="\n ".join(jread), jwrite="\n ".join(jwrite), jconstruct="\n ".join(jconstruct), jcargs=", ".join(jcargs), jcinit="\n ".join(jcinit), size=self.config_struct_get("_SIZE_")) class JavaEmitter: def __init__(self, outdir, config, config_struct, library_funcs): self.outdir = outdir self.config = config self.config_struct = config_struct self.library_funcs = library_funcs self.package = "com.ni.vision" self.classname = "NIVision" self.classpath = self.package.replace(".", "/") + "/" + self.classname self.unions = {} self.errors = {} with open(os.path.join(outdir, "VisionException.java"), "wt") as f: print("""// // This file is auto-generated by wpilibj/wpilibJavaJNI/nivision/gen_java.py // Please do not edit! // package {package}; public class VisionException extends RuntimeException {{ private static final long serialVersionUID = 1L; public VisionException(String msg) {{ super(msg); }} @Override public String toString() {{ return "VisionException [" + super.toString() + "]"; }} }}""".format(package=self.package), file=f) self.out = open(os.path.join(outdir, "NIVision.java"), "wt") print("""// // This file is auto-generated by wpilibj/wpilibJavaJNI/nivision/gen_java.py // Please do not edit! // package {package}; import java.lang.reflect.*; import java.io.UnsupportedEncodingException; import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.ByteOrder; public class {classname} {{ private {classname}() {{}} private static native void imaqDispose(long addr); private static Constructor constructDirectByteBuffer; private static Field bufferAddressField; static {{ try {{ Class[] cArg = new Class[2]; cArg[0] = long.class; cArg[1] = int.class; constructDirectByteBuffer = Class.forName("java.nio.DirectByteBuffer").getDeclaredConstructor(cArg); constructDirectByteBuffer.setAccessible(true); bufferAddressField = Buffer.class.getDeclaredField("address"); bufferAddressField.setAccessible(true); }} catch (ReflectiveOperationException e) {{ throw new ExceptionInInitializerError(e); }} }} private static ByteBuffer newDirectByteBuffer(long addr, int cap) {{ try {{ return ((ByteBuffer)(constructDirectByteBuffer.newInstance(addr, cap))).order(ByteOrder.nativeOrder()); }} catch (ReflectiveOperationException e) {{ throw new ExceptionInInitializerError(e); }} }} private static long getByteBufferAddress(ByteBuffer bb) {{ try {{ return bufferAddressField.getLong(bb); }} catch (IllegalAccessException e) {{ return 0; }} }} public static ByteBuffer sliceByteBuffer(ByteBuffer bb, int offset, int size) {{ int pos = bb.position(); int lim = bb.limit(); bb.position(offset); bb.limit(offset+size); ByteBuffer new_bb = bb.slice().order(ByteOrder.nativeOrder()); bb.position(pos); bb.limit(lim); return new_bb; }} public static ByteBuffer getBytes(ByteBuffer bb, byte[] dst, int offset, int size) {{ int pos = bb.position(); bb.position(offset); bb.get(dst, 0, size); bb.position(pos); return bb; }} public static ByteBuffer putBytes(ByteBuffer bb, byte[] src, int offset, int size) {{ int pos = bb.position(); bb.position(offset); bb.put(src, 0, size); bb.position(pos); return bb; }} private static abstract class DisposedStruct {{ protected ByteBuffer backing; private boolean owned; protected DisposedStruct(int size) {{ backing = ByteBuffer.allocateDirect(size); backing.order(ByteOrder.nativeOrder()); owned = false; }} protected DisposedStruct(ByteBuffer backing, int offset, int size) {{ this.backing = sliceByteBuffer(backing, offset, size); owned = false; }} private DisposedStruct(long nativeObj, boolean owned, int size) {{ backing = newDirectByteBuffer(nativeObj, size); this.owned = owned; }} public void free() {{ if (owned) {{ imaqDispose(getByteBufferAddress(backing)); owned = false; backing = null; }} }} @Override protected void finalize() throws Throwable {{ if (owned) imaqDispose(getByteBufferAddress(backing)); super.finalize(); }} public long getAddress() {{ if (backing == null) return 0; write(); return getByteBufferAddress(backing); }} protected void setBuffer(ByteBuffer backing, int offset, int size) {{ this.backing = sliceByteBuffer(backing, offset, size); }} abstract public void read(); abstract public void write(); abstract public int size(); }} private static abstract class OpaqueStruct {{ private long nativeObj; private boolean owned; protected OpaqueStruct() {{ nativeObj = 0; owned = false; }} protected OpaqueStruct(long nativeObj, boolean owned) {{ this.nativeObj = nativeObj; this.owned = owned; }} public void free() {{ if (owned && nativeObj != 0) {{ imaqDispose(nativeObj); owned = false; nativeObj = 0; }} }} @Override protected void finalize() throws Throwable {{ if (owned && nativeObj != 0) imaqDispose(nativeObj); super.finalize(); }} public long getAddress() {{ return nativeObj; }} }} public static class RawData {{ private ByteBuffer buf; private boolean owned; public RawData() {{ owned = false; }} public RawData(ByteBuffer buf) {{ this.buf = buf; owned = false; }} private RawData(long nativeObj, boolean owned, int size) {{ buf = newDirectByteBuffer(nativeObj, size); this.owned = owned; }} public void free() {{ if (owned) {{ imaqDispose(getByteBufferAddress(buf)); owned = false; buf = null; }} }} @Override protected void finalize() throws Throwable {{ if (owned) imaqDispose(getByteBufferAddress(buf)); super.finalize(); }} public long getAddress() {{ if (buf == null) return 0; return getByteBufferAddress(buf); }} public ByteBuffer getBuffer() {{ return buf; }} public void setBuffer(ByteBuffer buf) {{ if (owned) free(); this.buf = buf; }} }}""".format(package=self.package, classname=self.classname), file=self.out) if int(self.config_struct.get("_platform_", "pointer")) == 4: # 32-bit addressing java_types_map[("size_t", None)] = JavaType("int", "int", "jint", "I") print(""" private static long getPointer(ByteBuffer bb, int offset) { return (long)bb.getInt(offset); } private static void putPointer(ByteBuffer bb, int offset, long address) { bb.putInt(offset, (int)address); } private static void putPointer(ByteBuffer bb, int offset, ByteBuffer buf) { if (buf == null) bb.putInt(offset, 0); else bb.putInt(offset, (int)getByteBufferAddress(buf)); } private static void putPointer(ByteBuffer bb, int offset, DisposedStruct struct) { if (struct == null) bb.putInt(offset, 0); else bb.putInt(offset, (int)struct.getAddress()); } private static void putPointer(ByteBuffer bb, int offset, OpaqueStruct struct) { if (struct == null) bb.putInt(offset, 0); else bb.putInt(offset, (int)struct.getAddress()); }""", file=self.out) else: # 64-bit addressing java_types_map[("size_t", None)] = JavaType("long", "long", "jlong", "J") print(""" private static long getPointer(ByteBuffer bb, int offset) { return bb.getLong(offset); } private static void putPointer(ByteBuffer bb, int offset, long address) { bb.putLong(offset, address); } private static void putPointer(ByteBuffer bb, int offset, ByteBuffer buf) { if (buf == null) bb.putLong(offset, 0); else bb.putLong(offset, getByteBufferAddress(buf)); } private static void putPointer(ByteBuffer bb, int offset, OpaqueStruct struct) { if (struct == null) bb.putLong(offset, 0); else bb.putLong(offset, struct.getAddress()); } private static void putPointer(ByteBuffer bb, int offset, DisposedStruct struct) { if (struct == null) bb.putLong(offset, 0); else bb.putLong(offset, struct.getAddress()); }""", file=self.out) self.outc = open(os.path.join(outdir, "NIVision.cpp"), "wt") print("""// // This file is auto-generated by wpilibj/wpilibJavaJNI/nivision/gen_java.py // Please do not edit! // #include #include #include #include #include #include static const char* getErrorText(int err); // throw java exception static void throwJavaException(JNIEnv *env) {{ jclass je = env->FindClass("{packagepath}/VisionException"); int err = imaqGetLastError(); const char* err_text = getErrorText(err); char* full_err_msg = (char*)malloc(30+strlen(err_text)); sprintf(full_err_msg, "imaqError: %d: %s", err, err_text); env->ThrowNew(je, full_err_msg); free(full_err_msg); }} // throw IMAQdx java exception static void dxthrowJavaException(JNIEnv *env, IMAQdxError err) {{ jclass je = env->FindClass("{packagepath}/VisionException"); const char* err_text = getErrorText(err); char* full_err_msg = (char*)malloc(30+strlen(err_text)); sprintf(full_err_msg, "IMAQdxError: %d: %s", err, err_text); env->ThrowNew(je, full_err_msg); free(full_err_msg); }} extern "C" {{ JNIEXPORT void JNICALL Java_{package}_{classname}_imaqDispose(JNIEnv* , jclass , jlong addr) {{ imaqDispose((void*)addr); }} static inline IMAQdxError NI_FUNC IMAQdxGetAttributeU32(IMAQdxSession id, const char* name, uInt32* value) {{ return IMAQdxGetAttribute(id, name, IMAQdxValueTypeU32, (void*)value); }} static inline IMAQdxError NI_FUNC IMAQdxGetAttributeI64(IMAQdxSession id, const char* name, Int64* value) {{ return IMAQdxGetAttribute(id, name, IMAQdxValueTypeI64, (void*)value); }} static inline IMAQdxError NI_FUNC IMAQdxGetAttributeF64(IMAQdxSession id, const char* name, float64* value) {{ return IMAQdxGetAttribute(id, name, IMAQdxValueTypeF64, (void*)value); }} static inline IMAQdxError NI_FUNC IMAQdxGetAttributeString(IMAQdxSession id, const char* name, char value[IMAQDX_MAX_API_STRING_LENGTH]) {{ return IMAQdxGetAttribute(id, name, IMAQdxValueTypeString, (void*)value); }} static inline IMAQdxError NI_FUNC IMAQdxGetAttributeEnum(IMAQdxSession id, const char* name, IMAQdxEnumItem* value) {{ return IMAQdxGetAttribute(id, name, IMAQdxValueTypeEnumItem, (void*)value); }} static inline IMAQdxError NI_FUNC IMAQdxGetAttributeBool(IMAQdxSession id, const char* name, bool32* value) {{ return IMAQdxGetAttribute(id, name, IMAQdxValueTypeBool, (void*)value); }} static inline IMAQdxError NI_FUNC IMAQdxGetAttributeMinimumU32(IMAQdxSession id, const char* name, uInt32* value) {{ return IMAQdxGetAttributeMinimum(id, name, IMAQdxValueTypeU32, (void*)value); }} static inline IMAQdxError NI_FUNC IMAQdxGetAttributeMinimumI64(IMAQdxSession id, const char* name, Int64* value) {{ return IMAQdxGetAttributeMinimum(id, name, IMAQdxValueTypeI64, (void*)value); }} static inline IMAQdxError NI_FUNC IMAQdxGetAttributeMinimumF64(IMAQdxSession id, const char* name, float64* value) {{ return IMAQdxGetAttributeMinimum(id, name, IMAQdxValueTypeF64, (void*)value); }} static inline IMAQdxError NI_FUNC IMAQdxGetAttributeMaximumU32(IMAQdxSession id, const char* name, uInt32* value) {{ return IMAQdxGetAttributeMaximum(id, name, IMAQdxValueTypeU32, (void*)value); }} static inline IMAQdxError NI_FUNC IMAQdxGetAttributeMaximumI64(IMAQdxSession id, const char* name, Int64* value) {{ return IMAQdxGetAttributeMaximum(id, name, IMAQdxValueTypeI64, (void*)value); }} static inline IMAQdxError NI_FUNC IMAQdxGetAttributeMaximumF64(IMAQdxSession id, const char* name, float64* value) {{ return IMAQdxGetAttributeMaximum(id, name, IMAQdxValueTypeF64, (void*)value); }} static inline IMAQdxError NI_FUNC IMAQdxGetAttributeIncrementU32(IMAQdxSession id, const char* name, uInt32* value) {{ return IMAQdxGetAttributeIncrement(id, name, IMAQdxValueTypeU32, (void*)value); }} static inline IMAQdxError NI_FUNC IMAQdxGetAttributeIncrementI64(IMAQdxSession id, const char* name, Int64* value) {{ return IMAQdxGetAttributeIncrement(id, name, IMAQdxValueTypeI64, (void*)value); }} static inline IMAQdxError NI_FUNC IMAQdxGetAttributeIncrementF64(IMAQdxSession id, const char* name, float64* value) {{ return IMAQdxGetAttributeIncrement(id, name, IMAQdxValueTypeF64, (void*)value); }} static inline IMAQdxError NI_FUNC IMAQdxSetAttributeU32(IMAQdxSession id, const char* name, uInt32 value) {{ return IMAQdxSetAttribute(id, name, IMAQdxValueTypeU32, value); }} static inline IMAQdxError NI_FUNC IMAQdxSetAttributeI64(IMAQdxSession id, const char* name, Int64 value) {{ return IMAQdxSetAttribute(id, name, IMAQdxValueTypeI64, value); }} static inline IMAQdxError NI_FUNC IMAQdxSetAttributeF64(IMAQdxSession id, const char* name, float64 value) {{ return IMAQdxSetAttribute(id, name, IMAQdxValueTypeF64, value); }} static inline IMAQdxError NI_FUNC IMAQdxSetAttributeString(IMAQdxSession id, const char* name, const char* value) {{ return IMAQdxSetAttribute(id, name, IMAQdxValueTypeString, value); }} static inline IMAQdxError NI_FUNC IMAQdxSetAttributeEnum(IMAQdxSession id, const char* name, const IMAQdxEnumItem* value) {{ return IMAQdxSetAttribute(id, name, IMAQdxValueTypeU32, value->Value); }} static inline IMAQdxError NI_FUNC IMAQdxSetAttributeBool(IMAQdxSession id, const char* name, bool32 value) {{ return IMAQdxSetAttribute(id, name, IMAQdxValueTypeBool, value); }} """.format(packagepath=self.package.replace(".", "/"), package=self.package.replace(".", "_"), classname=self.classname), file=self.outc) self.block_comment("Opaque Structures") for name in sorted(opaque_structs): self.opaque_struct(name) def finish(self): print("}", file=self.out) print("""}} static const char* getErrorText(int err) {{ switch (err) {{ {errs} default: return "Unknown error"; }} }}""".format(errs="\n ".join('case %s: return "%s";' % (x, self.errors[x]) for x in sorted(self.errors))), file=self.outc) def config_get(self, section, option, fallback): try: return self.config.get(section, option) except (ValueError, configparser.NoSectionError, configparser.NoOptionError): return fallback def config_getboolean(self, section, option, fallback): try: return self.config.getboolean(section, option) except (ValueError, configparser.NoSectionError, configparser.NoOptionError): return fallback def block_comment(self, comment): print(""" /** * {comment} */""".format(comment=comment), file=self.out) print(""" /* * {comment} */""".format(comment=comment), file=self.outc) def opaque_struct(self, name): print(""" public static class {name} extends OpaqueStruct {{ private {name}() {{}} private {name}(long nativeObj, boolean owned) {{ super(nativeObj, owned); }} }}""".format(name=name), file=self.out) def define(self, name, value, comment): if self.config_getboolean(name, "exclude", fallback=False): return if name in opaque_structs: return clean = None type = None after_struct = False if value == "TRUE": clean = "true" type = "boolean" elif value == "FALSE": clean = "false" type = "boolean" elif name.startswith("IMAQ_INIT_RGB") and value[0] == '{' and value[-1] == '}': return elif value.startswith("imaqMake"): clean = "new " + value[8:] type = value.split("(")[0][8:] after_struct = True elif value[0] == '"': if len(value) == 2: clean = "{ 0 }" else: clean = "{ %s,0 }" % ",".join("0x%x" % ord(c) for c in value[1:-1]) type = "byte[]" elif number_re.match(value): clean = value type = "int" elif constant_re.match(value): clean = value after_struct = value not in defined if clean is None: print("Invalid #define: %s" % name) return if name.startswith("ERR_"): self.errors[name] = comment return # strip IMAQ_ prefix if name.startswith("IMAQ_"): name = name[5:] code = " public static final {type} {name} = {value};" \ .format(type=type, name=name, value=clean) if after_struct: define_after_struct.append((name, code)) return print(code, file=self.out) defined.add(name) def text(self, text): print(text, file=self.out) def static_const(self, name, ctype, value): # strip IMAQ_ prefix if name.startswith("IMAQ_"): name = name[5:] if hasattr(value, "__iter__"): code = " public static final {ctype} {name} = new {ctype}({value});" value = ", ".join(value) else: code = "{name} = {value};" print(code.format(name=name, value=value, ctype=ctype), file=self.out) defined.add(name) def enum(self, name, values): if self.config_getboolean(name, "exclude", fallback=False): return if name in opaque_structs: return valuestrs = [] need_search = False prev_value = -1 for vname, value, comment in values: if vname.endswith("SIZE_GUARD"): continue if value is None: # auto-increment value = "%d" % (prev_value + 1) value_i = int(value, 0) if value_i < 0 or value_i != (prev_value + 1): # need to do search instead of index for fromValue() need_search = True prev_value = value_i if vname == "IMAQdxErrorSuccess": continue if vname.startswith("IMAQdxError"): self.errors[vname] = comment continue if vname.startswith("IMAQ_"): vname = vname[5:] if vname.startswith("IMAQdx"): vname = vname[6:] if vname[0] in "0123456789": vname = "C" + vname valuestrs.append("%s(%s),%s" % (vname, value, " // %s" % comment if comment else "")) defined.add(vname) if not valuestrs: return print(""" public static enum {name} {{ {values} ; private final int value; private {name}(int value) {{ this.value = value; }} public static {name} fromValue(int val) {{""".format(name=name, values="\n ".join(valuestrs)), file=self.out) if need_search: print(""" for ({name} v : values()) {{ if (v.value == val) return v; }} return null;""".format(name=name), file=self.out) else: print(""" try {{ return values()[val]; }} catch (ArrayIndexOutOfBoundsException e) {{ return null; }}""".format(), file=self.out) print(""" }} public int getValue() {{ return value; }} }}""".format(), file=self.out) defined.add(name) enums.add(name) def typedef(self, name, typedef, arr): if self.config_getboolean(name, "exclude", fallback=False): return if name in opaque_structs: return if typedef.startswith("struct"): return elif typedef.startswith("union"): return elif (name, arr) not in java_types_map: java_types_map[(name, arr)] = c_to_jtype(typedef, arr).copy() if arr is None: java_types_map[(name, "")] = c_to_jtype(typedef, "").copy() defined.add(name) def typedef_function(self, name, restype, params): if self.config_getboolean(name, "exclude", fallback=False): return if name in opaque_structs: return raise NotImplementedError("typedef function not implemented") def function(self, name, restype, params): if name not in self.library_funcs: return if name == "IMAQdxEnumerateVideoModes": # full custom code print(""" public static class dxEnumerateVideoModesResult {{ public IMAQdxEnumItem[] videoModeArray; public int currentMode; private ByteBuffer videoModeArray_buf; private dxEnumerateVideoModesResult(ByteBuffer rv_buf, ByteBuffer videoModeArray_buf) {{ this.videoModeArray_buf = videoModeArray_buf; int count = rv_buf.getInt(0); videoModeArray = new IMAQdxEnumItem[count]; for (int i=0, off=0; i...") exit(0) inputs = [] for i in range(1, len(sys.argv), 4): fname = sys.argv[i] config_struct_name = sys.argv[i+1] configname = sys.argv[i+2] funcs_name = sys.argv[i+3] inputs.append((fname, config_struct_name, configname, funcs_name)) generate("", "", inputs)