/** * @(#) CFuncDeclaration.java */ import java.lang.System; import java.lang.String; import java.util.Vector; /** * The function-declaration holder ! * * @see CFuncVariable * @version 1.00, 12. Novemeber 1999 * @author Sven Goethel * */ public class CFuncDeclaration implements Cloneable { public boolean isValid; public CFuncVariable funcSpec; public Vector argList; public static final String jniFuncPrefixStd= "Java_" ; public static final String jniFuncArgPrefix="JNIEnv *env, jobject obj"; public static final int FUNC_ERROR = 0; public static final int FUNC_OK = 1; public static final int FUNC_TYPE_MISSING = 2; public static final int FUNC_NAME_MISSING = 3; public static final int FUNC_LASTARG_INCOMPLETE = 4; public CFuncDeclaration() { isValid = true; funcSpec = null; argList = new Vector(); } protected Object clone() throws CloneNotSupportedException { int i; CFuncDeclaration nobj = new CFuncDeclaration(); nobj.isValid=isValid; try { nobj.funcSpec=(CFuncVariable)funcSpec.clone(); } catch (Exception ex) {} for(i=0; i0) { if(which==n || which<0) { // Can only support single-dimensional arrays with direct buffers if (directBuffers) { if (cfvar.arrayNumber != 1) return null; // Bailout cfvar.typeJava = customType; cfvar.isDirectBuffer = true; cfvar.arrayNumber = 0; cfvar.isVoid = false; } else { cfvar.typeJava=customType; cfvar.isVoid=isNewTypeVoid; } } if(which==n) break; /* job done - leave loop */ n++; } } return tmp; } protected String args2JNIStrList() { String res = new String(); CFuncVariable cfvar; int i,j; for (i=0; i0) n++; } return n; } protected String getFuncArgsSignature() { String res = new String(); CFuncVariable cfvar; int i,j; res += "__"; for (i=0; i type[] */ if(cfvar.typeJava.equals("boolean")) res+="Z"; else if(cfvar.typeJava.equals("byte")) res+="B"; else if(cfvar.typeJava.equals("char")) res+="C"; else if(cfvar.typeJava.equals("short")) res+="S"; else if(cfvar.typeJava.equals("int")) res+="I"; else if(cfvar.typeJava.equals("long")) res+="J"; else if(cfvar.typeJava.equals("float")) res+="F"; else if(cfvar.typeJava.equals("double")) res+="D"; else if(cfvar.typeJava.equals("String")) res+="Ljava_lang_String_2"; else if(cfvar.isDirectBuffer) res+="Ljava_nio_Buffer_2"; } return res; } protected String __toJniJavaCode(boolean isFinal) { String res = new String(); if(funcSpec.arrayNumber>0) { System.err.println("ERROR: Pointer As Function-ReturnType is not supported yet !"); System.err.println("Function: "+funcSpec); return ""; } if(isFinal) res += "\tpublic final native "; else res += "\tpublic native "; res += funcSpec.getJavaTypeString() + " " + funcSpec.identifier + " (\n"; res += args2JavaStrList(); res += "\t) ;\n"; return res; } public String toJniJavaCode(boolean isFinal, int modifier) { int numberOfVoidPointerArgs = getNumberOfVoidPointerArgs(); if(numberOfVoidPointerArgs==0) { return __toJniJavaCode(isFinal); } CFuncDeclaration tmp = null; String res = new String(); tmp=getChangedVoidPtr2CustomPtrClone("byte", -1, false); if(tmp!=null) res+=tmp.__toJniJavaCode(isFinal); tmp=getChangedVoidPtr2CustomPtrClone("short", -1, false); if(tmp!=null) res+=tmp.__toJniJavaCode(isFinal); tmp=getChangedVoidPtr2CustomPtrClone("int", -1, false); if(tmp!=null) res+=tmp.__toJniJavaCode(isFinal); tmp=getChangedVoidPtr2CustomPtrClone("float", -1, false); if(tmp!=null) res+=tmp.__toJniJavaCode(isFinal); tmp=getChangedVoidPtr2CustomPtrClone("double", -1, false); if(tmp!=null) res+=tmp.__toJniJavaCode(isFinal); tmp=getChangedVoidPtr2CustomPtrClone("boolean", -1, false); if(tmp!=null) res+=tmp.__toJniJavaCode(isFinal); tmp=getChangedVoidPtr2CustomPtrClone("long", -1, false); if(tmp!=null) res+=tmp.__toJniJavaCode(isFinal); if ((modifier & C2J.MODIFIER_JNI_DIRECT_BUFFERS) != 0) { tmp=getChangedVoidPtr2CustomPtrClone("object", -1, true); if(tmp!=null) res+=tmp.__toJniJavaCode(isFinal); } return res; } protected String __toJniCCode(String clazzName, int exportMode, int modifier, boolean overloaded) { String res = new String(); CFuncVariable cfvar; int i; if(funcSpec.arrayNumber>0) { System.err.println("ERROR: Pointer As Function-ReturnType is not supported yet !"); System.err.println("Function: "+funcSpec); return ""; } res += "\tJNIEXPORT " + funcSpec.getJNITypeString() + " JNICALL\n" ; res += "\t" + jniFuncPrefixStd+clazzName+"_"+funcSpec.identifier; if(overloaded) res += getFuncArgsSignature(); res += " (\n"; res += "\t\t"+jniFuncArgPrefix; res += args2JNIStrList(); res += ")\n"; res += "\t{\n"; // // Add the return variable // if(funcSpec.typeJava.equals("void")==false) { res += "\t\t"+funcSpec.getJNITypeString()+" ret;\n\n"; } String jniCMethodBaseType; // // Adding the JNI access Methods // for Arrays and Direct Buffers ... // THE VARABLE DEFINITIONS // for (i=0; i0 ) { jniCMethodBaseType = cfvar.getJniCMethodBaseType(); if( !cfvar.isConst || (modifier&C2J.MODIFIER_JNI_COPY_CHECK)>0 ) res += "\t\tjboolean isCopiedArray" +i+ " = JNI_FALSE;\n"; res += "\t\t" + "j" + cfvar.typeJava + " *ptr" + i + " = NULL;\n"; if( (modifier&C2J.MODIFIER_JNI_COPY_CHECK )>0 ) { // // JAU COPY Warning, if copy is used !!! // res += "\t\tstatic int isWarned"+i+" = 0;\n"; } } else if( cfvar.isDirectBuffer ) { res += "\t\t" + "void *ptr" + i + " = NULL;\n"; } } res += "\n" ; if(exportMode==C2J.EXPORT_JNI_C_DYN) { // // Add the query if the dynamic native function pointer is != NULL // res += "\t\tif ( disp__"+funcSpec.identifier+" == NULL ) return"; if(funcSpec.typeJava.equals("void")==false) res += " 0"; res += ";\n\n"; } // // Adding the JNI access Methods // for Direct Buffers ... // THE ARGUMENT ACCESS // NOTE: this is done before any of the array setup so // we can throw IllegalArgumentException and return if // the passed object is not a direct buffer, without // having to perform any ReleasePrimitiveArrayCritical // (or similar) calls. // for (i=0; iGetDirectBufferAddress" + "(env, " + cfvar.identifier + ");\n"; res += "\t\t\t" + "if (ptr" + i + " == NULL) {\n" + "\t\t\t\t" + "(*env)->ThrowNew(env, (*env)->FindClass(env, \"java/lang/IllegalArgumentException\"),\n" + "\t\t\t\t\t\"Argument " + i + " was not a direct buffer\");\n" + "\t\t\t\t" + "return "; if (!funcSpec.typeJava.equals("void")) { res += "0"; } res += ";\n"; res += "\t\t\t}\n"; res += "\t\t}\n"; } } // // Adding the JNI access Methods // for Arrays ... // THE ARGUMENT ACCESS // for (i=0; i0 ) { jniCMethodBaseType = cfvar.getJniCMethodBaseType(); res += "\t\tif("+cfvar.identifier+"!=NULL)\n"; res += "\t\t{\n"; if ( (modifier&C2J.MODIFIER_JNI_CRITICAL_ARRAY)>0 ) { if( !cfvar.isConst || (modifier&C2J.MODIFIER_JNI_COPY_CHECK)>0 ) { res += "\t\t\t" + "ptr" + i + " = " + "(j" + cfvar.typeJava + " *) " + "(*env)->GetPrimitiveArrayCritical" + "(env, " + cfvar.identifier + ", " + "&isCopiedArray"+i+");\n"; } else { res += "\t\t\t" + "ptr" + i + " = " + "(j" + cfvar.typeJava + " *) " + "(*env)->GetPrimitiveArrayCritical" + "(env, " + cfvar.identifier + ", 0);\n"; } } else { if( !cfvar.isConst || (modifier&C2J.MODIFIER_JNI_COPY_CHECK)>0 ) { res += "\t\t\t" + "ptr" + i + " = " + "(*env)->Get" + jniCMethodBaseType + "ArrayElements(env, " + cfvar.identifier + ", " + "&isCopiedArray"+i+");\n"; } else { res += "\t\t\t" + "ptr" + i + " = " + "(*env)->Get" + jniCMethodBaseType + "ArrayElements(env, " + cfvar.identifier + ", 0);\n"; } } if( (modifier&C2J.MODIFIER_JNI_COPY_CHECK)>0 ) { // // JAU COPY Warning, if copy is used !!! // res += "\t\t\tif( isCopiedArray"+i+" == JNI_TRUE && isWarned"+i+"==0 ) {\n"; res += "\t\t\t\tisWarned"+i+"=1;\n"; res += "\t\t\t\tprintf(\"COPY by "+funcSpec.identifier+" arg: "+cfvar.identifier+"\");\n"; res += "\t\t\t}\n"; } res += "\t\t}\n"; } } // // Add the return variable assignment, incl. casting ! // if(funcSpec.typeC.equals("void")==false) { res += "\t\tret = ("+funcSpec.getJNITypeString()+") "; } else res += "\t\t"; // // Add the native function call ! // if(exportMode==C2J.EXPORT_JNI_C) res += funcSpec.identifier + " (\n"; else res += "disp__"+funcSpec.identifier + " (\n"; for (i=0; i0 || cfvar.isDirectBuffer ) res += "ptr"+i; else res += cfvar.identifier; if(i0 ) { jniCMethodBaseType = cfvar.getJniCMethodBaseType(); res += "\t\tif("+cfvar.identifier+"!=NULL)\n"; res += "\t\t{\n"; if ( (modifier&C2J.MODIFIER_JNI_CRITICAL_ARRAY)>0 ) { if( !cfvar.isConst ) { // // Free the memory, or the pinning lock. // A copy is needed, // if the Get*Array method used // the copy method ! // res += "\t\t\t(*env)->ReleasePrimitiveArrayCritical" + "(env, "+ cfvar.identifier + ", ptr" + i + ", " +"(isCopiedArray"+i+" == JNI_TRUE)?0:JNI_ABORT" +");\n"; } else { // // Just free the memory, or the pinning lock. // No copy needed, // because of the const data type ! // res += "\t\t\t(*env)->ReleasePrimitiveArrayCritical" + "(env, "+ cfvar.identifier + ", ptr" + i + ", JNI_ABORT);\n"; } } else { if( !cfvar.isConst ) { // // Free the memory, or the pinning lock. // A copy is needed, // if the Get*Array method used // the copy method ! // res += "\t\t\t(*env)->Release" + jniCMethodBaseType+ "ArrayElements(env, "+ cfvar.identifier + ", ptr" + i + ", " +"(isCopiedArray"+i+" == JNI_TRUE)?0:JNI_ABORT" +");\n"; } else { // // Just free the memory, or the pinning lock. // No copy needed, // because of the const data type ! // res += "\t\t\t(*env)->Release" + jniCMethodBaseType+ "ArrayElements(env, "+ cfvar.identifier + ", ptr" + i + ", JNI_ABORT);\n"; } } res += "\t\t}\n"; } } // // Let's give the baby to the caller ... // if(funcSpec.typeJava.equals("void")==false) res += "\t\treturn ret;\n"; res += "\t}\n"; return res; } public String toJniCCode(String clazzName, int exportMode, int modifier) { int numberOfVoidPointerArgs = getNumberOfVoidPointerArgs(); if(numberOfVoidPointerArgs==0) { return __toJniCCode(clazzName, exportMode, modifier, false); } CFuncDeclaration tmp = null; String res = new String(); tmp=getChangedVoidPtr2CustomPtrClone("byte", -1, false); if(tmp!=null) res+=tmp.__toJniCCode(clazzName, exportMode, modifier, true); tmp=getChangedVoidPtr2CustomPtrClone("short", -1, false); if(tmp!=null) res+=tmp.__toJniCCode(clazzName, exportMode, modifier, true); tmp=getChangedVoidPtr2CustomPtrClone("int", -1, false); if(tmp!=null) res+=tmp.__toJniCCode(clazzName, exportMode, modifier, true); tmp=getChangedVoidPtr2CustomPtrClone("float", -1, false); if(tmp!=null) res+=tmp.__toJniCCode(clazzName, exportMode, modifier, true); tmp=getChangedVoidPtr2CustomPtrClone("double", -1, false); if(tmp!=null) res+=tmp.__toJniCCode(clazzName, exportMode, modifier, true); tmp=getChangedVoidPtr2CustomPtrClone("boolean", -1, false); if(tmp!=null) res+=tmp.__toJniCCode(clazzName, exportMode, modifier, true); tmp=getChangedVoidPtr2CustomPtrClone("long", -1, false); if(tmp!=null) res+=tmp.__toJniCCode(clazzName, exportMode, modifier, true); if ((modifier & C2J.MODIFIER_JNI_DIRECT_BUFFERS) != 0) { tmp=getChangedVoidPtr2CustomPtrClone("object", -1, true); if(tmp!=null) res+=tmp.__toJniCCode(clazzName, exportMode, modifier, true); } return res; } protected String __toMsJDirectCode(String dllname) { String res = new String(); CFuncVariable cfvar; int i; if(funcSpec.arrayNumber>0) { System.err.println("ERROR: Pointer As Function-ReturnType is not supported yet !"); System.err.println("Function: "+funcSpec); return ""; } // // Use The JDirect security tag to make security calls easy ! // This one grants access to all MSJVM's >= // "Microsoft (R) VM for Java, 5.0 Release 5.0.0.3186" // without signing the applet !!! // // Making the mapping from the "static native" wrapper function // to the corresponding native function // res += "\t/**\n"; res += "\t * @dll.import(\""+dllname+"\",entrypoint=\""+ funcSpec.identifier+"\")\n"; res += "\t */\n"; // // adding the "static native" wrapper function // res += "\tprivate static native "; res += funcSpec.getJavaTypeString() + " __" + funcSpec.identifier + " (\n"; res += args2JavaStrList(); res += "\t) ;\n"; // // adding our GL4Java glue to the // "static native" wrapper function // res += "\tpublic final "; res += funcSpec.getJavaTypeString() + " " + funcSpec.identifier + " (\n"; res += args2JavaStrList(); res += "\t)\n"; res += "\t{\n"; res += "\t\t"; if(funcSpec.typeJava.equals("void")==false) res += "return "; res += "disp__"+funcSpec.identifier+"(\n"; for (i=0; i