diff options
Diffstat (limited to 'src/java/com/jogamp/gluegen')
9 files changed, 678 insertions, 640 deletions
diff --git a/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java b/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java index 7c88c37..caeede8 100644 --- a/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java +++ b/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2010-2023 JogAmp Community. All rights reserved. * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without @@ -39,15 +40,18 @@ package com.jogamp.gluegen; -import java.util.*; -import java.io.*; +import java.io.PrintWriter; import java.text.MessageFormat; +import java.util.List; import com.jogamp.common.os.MachineDataInfo; import com.jogamp.gluegen.Logging.LoggerIf; -import com.jogamp.gluegen.cgram.types.*; +import com.jogamp.gluegen.cgram.types.ArrayType; +import com.jogamp.gluegen.cgram.types.FunctionSymbol; +import com.jogamp.gluegen.cgram.types.PointerType; +import com.jogamp.gluegen.cgram.types.Type; -/** Emits the C-side component of the Java<->C JNI binding. */ +/** Emits the C-side component of the Java<->C JNI binding to its {@link CodeUnit}, see {@link FunctionEmitter}. */ public class CMethodBindingEmitter extends FunctionEmitter { protected static final CommentEmitter defaultCommentEmitter = new DefaultCommentEmitter(); @@ -58,8 +62,6 @@ public class CMethodBindingEmitter extends FunctionEmitter { protected final LoggerIf LOG; - protected MethodBinding binding; - /** Name of the package in which the corresponding Java method resides.*/ private final String packageName; @@ -117,7 +119,7 @@ public class CMethodBindingEmitter extends FunctionEmitter { * being bound. */ public CMethodBindingEmitter(final MethodBinding binding, - final PrintWriter output, + final CodeUnit unit, final String javaPackageName, final String javaClassName, final boolean isOverloadedBinding, @@ -127,14 +129,13 @@ public class CMethodBindingEmitter extends FunctionEmitter { final MachineDataInfo machDesc, final JavaConfiguration configuration) { - super(output, false, configuration); + super(binding, unit, false, configuration); LOG = Logging.getLogger(CMethodBindingEmitter.class.getPackage().getName(), CMethodBindingEmitter.class.getSimpleName()); assert(binding != null); assert(javaClassName != null); assert(javaPackageName != null); - this.binding = binding; this.packageName = javaPackageName; this.className = javaClassName; this.isOverloadedBinding = isOverloadedBinding; @@ -147,8 +148,6 @@ public class CMethodBindingEmitter extends FunctionEmitter { setCommentEmitter(defaultCommentEmitter); } - public final MethodBinding getBinding() { return binding; } - @Override public String getInterfaceName() { return binding.getInterfaceName(); @@ -308,21 +307,21 @@ public class CMethodBindingEmitter extends FunctionEmitter { @Override - protected void emitReturnType(final PrintWriter writer) { - writer.print("JNIEXPORT "); - writer.print(binding.getJavaReturnType().jniTypeName()); - writer.print(" JNICALL"); + protected void emitReturnType() { + unit.emit("JNIEXPORT "); + unit.emit(binding.getJavaReturnType().jniTypeName()); + unit.emit(" JNICALL"); } @Override - protected void emitName(final PrintWriter writer) { - writer.println(); // start name on new line - writer.print(JavaEmitter.getJNIMethodNamePrefix(getJavaPackageName(), getJavaClassName())); - writer.print("_"); + protected void emitName() { + unit.emitln(); // start name on new line + unit.emit(JavaEmitter.getJNIMethodNamePrefix(getJavaPackageName(), getJavaClassName())); + unit.emit("_"); if (isOverloadedBinding) { - writer.print(jniMangle(binding)); + unit.emit(jniMangle(binding)); } else { - writer.print(JavaEmitter.jniMangle(getImplName())); + unit.emit(JavaEmitter.jniMangle(getImplName())); } } @@ -338,20 +337,24 @@ public class CMethodBindingEmitter extends FunctionEmitter { } @Override - protected int emitArguments(final PrintWriter writer) { - writer.print("JNIEnv *env, "); + protected int emitArguments() { + unit.emit("JNIEnv *env, "); int numEmitted = 1; // initially just the JNIEnv if (isJavaMethodStatic && !binding.hasContainingType()) { - writer.print("jclass"); + unit.emit("jclass"); } else { - writer.print("jobject"); + unit.emit("jobject"); } - writer.print(" _unused"); + unit.emit(" _unused"); ++numEmitted; + if( binding.isReturnCompoundByValue() ) { + unit.emit(", jclass _clazzBuffers"); + ++numEmitted; + } if (binding.hasContainingType()) { // "this" argument always comes down in argument 0 as direct buffer - writer.print(", jobject " + JavaMethodBindingEmitter.javaThisArgumentName()); + unit.emit(", jobject " + JavaMethodBindingEmitter.javaThisArgumentName()); } for (int i = 0; i < binding.getNumArguments(); i++) { final JavaType javaArgType = binding.getJavaArgumentType(i); @@ -365,20 +368,20 @@ public class CMethodBindingEmitter extends FunctionEmitter { if (javaArgType.isJNIEnv() || binding.isArgumentThisPointer(i)) { continue; } - writer.print(", "); - writer.print(javaArgType.jniTypeName()); - writer.print(" "); - writer.print(binding.getArgumentName(i)); + unit.emit(", "); + unit.emit(javaArgType.jniTypeName()); + unit.emit(" "); + unit.emit(binding.getArgumentName(i)); ++numEmitted; if (javaArgType.isPrimitiveArray() || javaArgType.isNIOBuffer()) { - writer.print(", jint " + byteOffsetArgName(i)); + unit.emit(", jint " + byteOffsetArgName(i)); if(forIndirectBufferAndArrayImplementation) { - writer.print(", jboolean " + isNIOArgName(i)); + unit.emit(", jboolean " + isNIOArgName(i)); } } else if (javaArgType.isNIOBufferArray()) { - writer.print(", jintArray " + + unit.emit(", jintArray " + byteOffsetArrayArgName(i)); } } @@ -387,25 +390,24 @@ public class CMethodBindingEmitter extends FunctionEmitter { @Override - protected void emitBody(final PrintWriter writer) { - writer.println(" {"); -// writer.println("printf(\" - - - - "+ getName() + getImplSuffix() +" - - - -\\n\");"); - emitBodyVariableDeclarations(writer); - emitBodyUserVariableDeclarations(writer); - emitBodyVariablePreCallSetup(writer); - emitBodyCallCFunction(writer); - emitBodyUserVariableAssignments(writer); - emitBodyVariablePostCallCleanup(writer); - emitBodyReturnResult(writer); - writer.println("}"); - writer.println(); + protected void emitBody() { + unit.emitln(" {"); +// unit().emitln("printf(\" - - - - "+ getName() + getImplSuffix() +" - - - -\\n\");"); + emitBodyVariableDeclarations(); + emitBodyUserVariableDeclarations(); + emitBodyVariablePreCallSetup(); + emitBodyCallCFunction(); + emitBodyUserVariableAssignments(); + emitBodyVariablePostCallCleanup(); + emitBodyReturnResult(); + unit.emitln("}"); + unit.emitln(); } - protected void emitBodyVariableDeclarations(final PrintWriter writer) { + protected void emitBodyVariableDeclarations() { // Emit declarations for all pointer and String conversion variables if (binding.hasContainingType()) { - emitPointerDeclaration(writer, - binding.getContainingType(), + emitPointerDeclaration(binding.getContainingType(), binding.getContainingCType(), CMethodBindingEmitter.cThisArgumentName(), null); @@ -423,20 +425,19 @@ public class CMethodBindingEmitter extends FunctionEmitter { final String convName = pointerConversionArgumentName(javaArgName); // handle array/buffer argument types final boolean needsDataCopy = - emitPointerDeclaration(writer, - type, + emitPointerDeclaration(type, binding.getCArgumentType(i), convName, javaArgName); if (needsDataCopy && !emittedDataCopyTemps) { // emit loop counter and array length variables used during data // copy - writer.println(" jobject _tmpObj;"); - writer.println(" int _copyIndex;"); - writer.println(" jsize _tmpArrayLen;"); + unit.emitln(" jobject _tmpObj;"); + unit.emitln(" int _copyIndex;"); + unit.emitln(" jsize _tmpArrayLen;"); // Pointer to the data in the Buffer, taking the offset into account if(type.isNIOBufferArray()) { - writer.println(" int * _offsetHandle = NULL;"); + unit.emitln(" int * _offsetHandle = NULL;"); } emittedDataCopyTemps = true; @@ -444,13 +445,13 @@ public class CMethodBindingEmitter extends FunctionEmitter { } else if (type.isString()) { final Type cType = binding.getCArgumentType(i); if (isUTF8Type(cType)) { - writer.print(" const char* "); + unit.emit(" const char* "); } else { - writer.print(" jchar* "); + unit.emit(" jchar* "); } - writer.print(STRING_CHARS_PREFIX); - writer.print(binding.getArgumentName(i)); - writer.println(" = NULL;"); + unit.emit(STRING_CHARS_PREFIX); + unit.emit(binding.getArgumentName(i)); + unit.emitln(" = NULL;"); } } @@ -460,27 +461,27 @@ public class CMethodBindingEmitter extends FunctionEmitter { final JavaType javaReturnType = binding.getJavaReturnType(); if (!cReturnType.isVoid()) { - writer.print(" "); + unit.emit(" "); // Note we respect const/volatile in the function return type. // However, we cannot have it 'const' for our local variable. // See cast in emitBodyCallCFunction(..)! - writer.print(binding.getCSymbol().getReturnType().getCName(false)); - writer.println(" _res;"); + unit.emit(binding.getCSymbol().getReturnType().getCName(false)); + unit.emitln(" _res;"); if (javaReturnType.isNIOByteBufferArray() || javaReturnType.isArrayOfCompoundTypeWrappers()) { - writer.print(" int "); - writer.print(arrayResLength); - writer.println(";"); - writer.print(" int "); - writer.print(arrayIdx); - writer.println(";"); - writer.print(" jobjectArray "); - writer.print(arrayRes); - writer.println(";"); + unit.emit(" int "); + unit.emit(arrayResLength); + unit.emitln(";"); + unit.emit(" int "); + unit.emit(arrayIdx); + unit.emitln(";"); + unit.emit(" jobjectArray "); + unit.emit(arrayRes); + unit.emitln(";"); } else if (javaReturnType.isArray()) { - writer.print(" int "); - writer.print(arrayResLength); - writer.println(";"); + unit.emit(" int "); + unit.emit(arrayResLength); + unit.emitln(";"); final Class<?> componentType = javaReturnType.getJavaClass().getComponentType(); if (componentType.isArray()) { @@ -489,22 +490,22 @@ public class CMethodBindingEmitter extends FunctionEmitter { final String javaTypeName = componentType.getName(); final String javaArrayTypeName = "j" + javaTypeName + "Array"; - writer.print(" "); - writer.print(javaArrayTypeName); - writer.print(" "); - writer.print(arrayRes); - writer.println(";"); + unit.emit(" "); + unit.emit(javaArrayTypeName); + unit.emit(" "); + unit.emit(arrayRes); + unit.emitln(";"); } } } /** Emits the user-defined C variable declarations from the TemporaryCVariableDeclarations directive in the .cfg file. */ - protected void emitBodyUserVariableDeclarations(final PrintWriter writer) { + protected void emitBodyUserVariableDeclarations() { if (temporaryCVariableDeclarations != null) { for (final String val : temporaryCVariableDeclarations) { - writer.print(" "); - writer.println(val); + unit.emit(" "); + unit.emitln(val); } } } @@ -545,13 +546,13 @@ public class CMethodBindingEmitter extends FunctionEmitter { * emitBodyVariableDeclarations(), PRIOR TO calling the actual C * function. */ - protected void emitBodyVariablePreCallSetup(final PrintWriter writer) { + protected void emitBodyVariablePreCallSetup() { // Convert all Buffers to pointers first so we don't have to // call ReleasePrimitiveArrayCritical for any arrays if any // incoming buffers aren't direct if (binding.hasContainingType()) { - emitPointerConversion(writer, binding, + emitPointerConversion(binding, binding.getContainingType(), binding.getContainingCType(), JavaMethodBindingEmitter.javaThisArgumentName(), @@ -570,7 +571,7 @@ public class CMethodBindingEmitter extends FunctionEmitter { if (javaArgType.isCompoundTypeWrapper() || (javaArgType.isNIOBuffer() && !forIndirectBufferAndArrayImplementation ) ) { - emitPointerConversion(writer, binding, javaArgType, + emitPointerConversion(binding, javaArgType, binding.getCArgumentType(i), javaArgName, pointerConversionArgumentName(javaArgName), byteOffsetArgName(i)); @@ -579,7 +580,7 @@ public class CMethodBindingEmitter extends FunctionEmitter { ( javaArgType.isNIOBuffer() && forIndirectBufferAndArrayImplementation ) ) { final boolean needsDataCopy = javaArgTypeNeedsDataCopy(javaArgType); - writer.println(" if ( NULL != " + javaArgName + " ) {"); + unit.emitln(" if ( NULL != " + javaArgName + " ) {"); final Type cArgType = binding.getCArgumentType(i); String cArgTypeName = cArgType.getCName(); @@ -587,17 +588,17 @@ public class CMethodBindingEmitter extends FunctionEmitter { final String convName = pointerConversionArgumentName(javaArgName); if (!needsDataCopy) { - writer.print(" "); - writer.print(convName); - writer.print(" = ("); + unit.emit(" "); + unit.emit(convName); + unit.emit(" = ("); if (javaArgType.isStringArray()) { // java-side type is String[] cArgTypeName = "jstring *"; } - writer.print(cArgTypeName); - writer.print(") ( JNI_TRUE == " + isNIOArgName(i) + " ? "); - writer.print(" (*env)->GetDirectBufferAddress(env, " + javaArgName + ") : "); - writer.print(" (*env)->GetPrimitiveArrayCritical(env, " + javaArgName + ", NULL) );"); + unit.emit(cArgTypeName); + unit.emit(") ( JNI_TRUE == " + isNIOArgName(i) + " ? "); + unit.emit(" (*env)->GetDirectBufferAddress(env, " + javaArgName + ") : "); + unit.emit(" (*env)->GetPrimitiveArrayCritical(env, " + javaArgName + ", NULL) );"); } else { // Handle the case where the array elements are of a type that needs a // data copy operation to convert from the java memory model to the C @@ -618,16 +619,16 @@ public class CMethodBindingEmitter extends FunctionEmitter { "\": support for non-const ptr-to-ptr types not implemented: "+binding, binding.getCSymbol().getASTLocusTag()); } - writer.println(); - writer.println(" /* Copy contents of " + javaArgName + " into " + convName + "_copy */"); + unit.emitln(); + unit.emitln(" /* Copy contents of " + javaArgName + " into " + convName + "_copy */"); // get length of array being copied final String arrayLenName = "_tmpArrayLen"; - writer.print(" "); - writer.print(arrayLenName); - writer.print(" = (*env)->GetArrayLength(env, "); - writer.print(javaArgName); - writer.println(");"); + unit.emit(" "); + unit.emit(arrayLenName); + unit.emit(" = (*env)->GetArrayLength(env, "); + unit.emit(javaArgName); + unit.emitln(");"); // allocate an array to hold each element final Type cArgElementType, cArgElementType2; @@ -666,7 +667,6 @@ public class CMethodBindingEmitter extends FunctionEmitter { } } emitMalloc( - writer, convName+"_copy", cArgElementType.getCName(), cArgType.isBaseTypeConst(), @@ -679,33 +679,31 @@ public class CMethodBindingEmitter extends FunctionEmitter { // GetObjectArrayElement while in a critical section. May // need to do another loop and add in the offsets. if (javaArgType.isNIOBufferArray()) { - writer.println + unit.emitln (" _offsetHandle = (int *) (*env)->GetPrimitiveArrayCritical(env, " + byteOffsetArrayArgName(i) + ", NULL);"); } // process each element in the array - writer.println(" for (_copyIndex = 0; _copyIndex < "+arrayLenName+"; ++_copyIndex) {"); + unit.emitln(" for (_copyIndex = 0; _copyIndex < "+arrayLenName+"; ++_copyIndex) {"); // get each array element - writer.println(" /* get each element of the array argument \"" + javaArgName + "\" */"); - writer.print(" _tmpObj = (*env)->GetObjectArrayElement(env, "); - writer.print(javaArgName); - writer.println(", _copyIndex);"); + unit.emitln(" /* get each element of the array argument \"" + javaArgName + "\" */"); + unit.emit(" _tmpObj = (*env)->GetObjectArrayElement(env, "); + unit.emit(javaArgName); + unit.emitln(", _copyIndex);"); if (javaArgType.isStringArray()) { - writer.print(" "); - emitGetStringChars(writer, - "(jstring) _tmpObj", + unit.emit(" "); + emitGetStringChars("(jstring) _tmpObj", convName+"_copy[_copyIndex]", isUTF8Type(cArgType), true); } else if (javaArgType.isNIOBufferArray()) { /* We always assume an integer "byte offset" argument follows any Buffer in the method binding. */ - emitGetDirectBufferAddress(writer, - "_tmpObj", + emitGetDirectBufferAddress("_tmpObj", cArgElementType.getCName(), convName + "_copy[_copyIndex]", true, @@ -714,8 +712,7 @@ public class CMethodBindingEmitter extends FunctionEmitter { // These come down in similar fashion to an array of NIO // Buffers only we do not pass down any integer byte // offset argument - emitGetDirectBufferAddress(writer, - "_tmpObj", + emitGetDirectBufferAddress("_tmpObj", cArgElementType.getCName(), "("+convName + "_copy + _copyIndex)", false /* !receivingIsPtrPtr -> linear layout -> use memcpy */, @@ -730,10 +727,8 @@ public class CMethodBindingEmitter extends FunctionEmitter { // assign it to the appropriate elements at pointer depth 1? // Probably depends on const-ness of the argument. // Malloc enough space to hold a copy of each sub-array - writer.print(" "); - emitMalloc( - writer, - convName+"_copy[_copyIndex]", + unit.emit(" "); + emitMalloc(convName+"_copy[_copyIndex]", cArgElementType2.getCName(), // assumes cArgPtrType is ptr-to-ptr-to-primitive !! cArgType.isBaseTypeConst(), "(*env)->GetArrayLength(env, _tmpObj)", @@ -746,22 +741,22 @@ public class CMethodBindingEmitter extends FunctionEmitter { } } - writer.println(" }"); + unit.emitln(" }"); if (javaArgType.isNIOBufferArray()) { - writer.println + unit.emitln (" (*env)->ReleasePrimitiveArrayCritical(env, " + byteOffsetArrayArgName(i) + ", _offsetHandle, JNI_ABORT);"); } - writer.println(); + unit.emitln(); } // end of data copy - writer.println(" }"); + unit.emitln(" }"); } else if (javaArgType.isString()) { - emitGetStringChars(writer, javaArgName, + emitGetStringChars(javaArgName, STRING_CHARS_PREFIX + javaArgName, isUTF8Type(binding.getCArgumentType(i)), false); @@ -774,7 +769,7 @@ public class CMethodBindingEmitter extends FunctionEmitter { * Code to clean up any variables that were declared in * emitBodyVariableDeclarations(), AFTER calling the actual C function. */ - protected void emitBodyVariablePostCallCleanup(final PrintWriter writer) { + protected void emitBodyVariablePostCallCleanup() { // Release primitive arrays and temporary UTF8 strings if necessary for (int i = 0; i < binding.getNumArguments(); i++) { @@ -794,13 +789,13 @@ public class CMethodBindingEmitter extends FunctionEmitter { final String convName = pointerConversionArgumentName(javaArgName); if (!needsDataCopy) { - writer.println(" if ( JNI_FALSE == " + isNIOArgName(i) + " && NULL != " + javaArgName + " ) {"); + unit.emitln(" if ( JNI_FALSE == " + isNIOArgName(i) + " && NULL != " + javaArgName + " ) {"); // Release array final String modeFlag = cArgType.isBaseTypeConst() ? "JNI_ABORT" : "0" ; - writer.print(" (*env)->ReleasePrimitiveArrayCritical(env, " + javaArgName + ", " + convName + ", "+modeFlag+");"); + unit.emit(" (*env)->ReleasePrimitiveArrayCritical(env, " + javaArgName + ", " + convName + ", "+modeFlag+");"); } else { - writer.println(" if ( NULL != " + javaArgName + " ) {"); + unit.emitln(" if ( NULL != " + javaArgName + " ) {"); // clean up the case where the array elements are of a type that needed // a data copy operation to convert from the java memory model to the @@ -815,16 +810,15 @@ public class CMethodBindingEmitter extends FunctionEmitter { // method for details). if (javaArgType.isArrayOfCompoundTypeWrappers()) { // This is the only form of cleanup we handle right now - writer.println(" _tmpArrayLen = (*env)->GetArrayLength(env, " + javaArgName + ");"); - writer.println(" for (_copyIndex = 0; _copyIndex < _tmpArrayLen; ++_copyIndex) {"); - writer.println(" _tmpObj = (*env)->GetObjectArrayElement(env, " + javaArgName + ", _copyIndex);"); - emitReturnDirectBufferAddress(writer, - "_tmpObj", - cArgType.asArray().getBaseElementType().getCName(), - "("+convName + "_copy + _copyIndex)", - false /* receivingIsPtrPtr */, - null); - writer.println(" }"); + unit.emitln(" _tmpArrayLen = (*env)->GetArrayLength(env, " + javaArgName + ");"); + unit.emitln(" for (_copyIndex = 0; _copyIndex < _tmpArrayLen; ++_copyIndex) {"); + unit.emitln(" _tmpObj = (*env)->GetObjectArrayElement(env, " + javaArgName + ", _copyIndex);"); + emitReturnDirectBufferAddress("_tmpObj", + cArgType.asArray().getBaseElementType().getCName(), + "("+convName + "_copy + _copyIndex)", + false /* receivingIsPtrPtr */, + null); + unit.emitln(" }"); } else { throw new GlueGenException( "Cannot clean up copied data for ptr-to-ptr arg type \"" + cArgType.getDebugString() + @@ -833,7 +827,7 @@ public class CMethodBindingEmitter extends FunctionEmitter { } } - writer.println(" /* Clean up " + convName + "_copy */"); + unit.emitln(" /* Clean up " + convName + "_copy */"); // Only need to perform cleanup for individual array // elements if they are not direct buffers @@ -841,11 +835,11 @@ public class CMethodBindingEmitter extends FunctionEmitter { !javaArgType.isArrayOfCompoundTypeWrappers()) { // Re-fetch length of array that was copied final String arrayLenName = "_tmpArrayLen"; - writer.print(" "); - writer.print(arrayLenName); - writer.print(" = (*env)->GetArrayLength(env, "); - writer.print(javaArgName); - writer.println(");"); + unit.emit(" "); + unit.emit(arrayLenName); + unit.emit(" = (*env)->GetArrayLength(env, "); + unit.emit(javaArgName); + unit.emitln(");"); // free each element final PointerType cArgPtrType = cArgType.asPointer(); @@ -857,61 +851,61 @@ public class CMethodBindingEmitter extends FunctionEmitter { } // process each element in the array - writer.println(" for (_copyIndex = 0; _copyIndex < " + arrayLenName +"; ++_copyIndex) {"); + unit.emitln(" for (_copyIndex = 0; _copyIndex < " + arrayLenName +"; ++_copyIndex) {"); // get each array element - writer.println(" /* free each element of " +convName +"_copy */"); - writer.print(" _tmpObj = (*env)->GetObjectArrayElement(env, "); - writer.print(javaArgName); - writer.println(", _copyIndex);"); + unit.emitln(" /* free each element of " +convName +"_copy */"); + unit.emit(" _tmpObj = (*env)->GetObjectArrayElement(env, "); + unit.emit(javaArgName); + unit.emitln(", _copyIndex);"); if (javaArgType.isStringArray()) { - writer.print(" (*env)->ReleaseStringUTFChars(env, "); - writer.print("(jstring) _tmpObj"); - writer.print(", "); - writer.print(convName+"_copy[_copyIndex]"); - writer.println(");"); + unit.emit(" (*env)->ReleaseStringUTFChars(env, "); + unit.emit("(jstring) _tmpObj"); + unit.emit(", "); + unit.emit(convName+"_copy[_copyIndex]"); + unit.emitln(");"); } else { throw new GlueGenException( "Cannot yet handle type \"" + cArgType.getDebugString() + "\"; need to add support for cleaning up copied ptr-to-ptr-to-primitiveType subarrays", binding.getCSymbol().getASTLocusTag()); } - writer.println(" }"); + unit.emitln(" }"); } // free the main array - writer.print(" free((void*) "); - writer.print(convName+"_copy"); - writer.println(");"); + unit.emit(" free((void*) "); + unit.emit(convName+"_copy"); + unit.emitln(");"); } // end of cleaning up copied data - writer.println(" }"); + unit.emitln(" }"); } else if (javaArgType.isString()) { - writer.println(" if ( NULL != " + javaArgName + " ) {"); + unit.emitln(" if ( NULL != " + javaArgName + " ) {"); if (isUTF8Type(cArgType)) { - writer.print(" (*env)->ReleaseStringUTFChars(env, "); - writer.print(javaArgName); - writer.print(", " + STRING_CHARS_PREFIX); - writer.print(javaArgName); - writer.println(");"); + unit.emit(" (*env)->ReleaseStringUTFChars(env, "); + unit.emit(javaArgName); + unit.emit(", " + STRING_CHARS_PREFIX); + unit.emit(javaArgName); + unit.emitln(");"); } else { - writer.println(" free((void*) " + STRING_CHARS_PREFIX + javaArgName + ");"); + unit.emitln(" free((void*) " + STRING_CHARS_PREFIX + javaArgName + ");"); } - writer.println(" }"); + unit.emitln(" }"); } } } /** Returns the number of arguments passed so calling code knows whether to print a comma */ - protected int emitBodyPassCArguments(final PrintWriter writer) { + protected int emitBodyPassCArguments() { for (int i = 0; i < binding.getNumArguments(); i++) { if (i != 0) { - writer.print(", "); + unit.emit(", "); } final JavaType javaArgType = binding.getJavaArgumentType(i); // Handle case where only param is void. @@ -923,40 +917,40 @@ public class CMethodBindingEmitter extends FunctionEmitter { } if (javaArgType.isJNIEnv()) { - writer.print("env"); + unit.emit("env"); } else if (binding.isArgumentThisPointer(i)) { - writer.print(CMethodBindingEmitter.cThisArgumentName()); + unit.emit(CMethodBindingEmitter.cThisArgumentName()); } else { - writer.print("("); + unit.emit("("); final Type cArgType = binding.getCArgumentType(i); final boolean needsDataCopy = javaArgTypeNeedsDataCopy(javaArgType); final boolean needsArrayOffset = !needsDataCopy && ( javaArgType.isArray() || javaArgType.isArrayOfCompoundTypeWrappers() || ( javaArgType.isNIOBuffer() && forIndirectBufferAndArrayImplementation ) ); - writer.print(cArgType.getCName(true)); - writer.print(") "); + unit.emit(cArgType.getCName(true)); + unit.emit(") "); if (cArgType.isPointer() && javaArgType.isPrimitive()) { - writer.print("(intptr_t) "); + unit.emit("(intptr_t) "); } if (javaArgType.isArray() || javaArgType.isNIOBuffer() || javaArgType.isCompoundTypeWrapper() || javaArgType.isArrayOfCompoundTypeWrappers()) { if( needsArrayOffset ) { - writer.print("(((char *) "); + unit.emit("(((char *) "); } else if( !cArgType.isPointer() && javaArgType.isCompoundTypeWrapper() ) { // FIXME: Compound call-by-value - writer.print("*"); + unit.emit("*"); } - writer.print(pointerConversionArgumentName(binding.getArgumentName(i))); + unit.emit(pointerConversionArgumentName(binding.getArgumentName(i))); if ( needsDataCopy ) { - writer.print("_copy"); + unit.emit("_copy"); } if( needsArrayOffset ) { - writer.print(") + " + byteOffsetArgName(i) + ")"); + unit.emit(") + " + byteOffsetArgName(i) + ")"); } } else { - if (javaArgType.isString()) { writer.print(STRING_CHARS_PREFIX); } - writer.print(binding.getArgumentName(i)); + if (javaArgType.isString()) { unit.emit(STRING_CHARS_PREFIX); } + unit.emit(binding.getArgumentName(i)); } } } @@ -974,9 +968,9 @@ public class CMethodBindingEmitter extends FunctionEmitter { isCStructFunctionPointer = v; } - protected void emitBodyCallCFunction(final PrintWriter writer) { + protected void emitBodyCallCFunction() { // Make the call to the actual C function - writer.print(" "); + unit.emit(" "); // WARNING: this code assumes that the return type has already been // typedef-resolved. @@ -986,32 +980,32 @@ public class CMethodBindingEmitter extends FunctionEmitter { // Note we respect const/volatile in the function return type. // However, we cannot have it 'const' for our local variable. // See return type in emitBodyVariableDeclarations(..)! - writer.print("_res = ("); - writer.print(cReturnType.getCName(false)); - writer.print(") "); + unit.emit("_res = ("); + unit.emit(cReturnType.getCName(false)); + unit.emit(") "); } if ( isCStructFunctionPointer && binding.hasContainingType() ) { // Call through function pointer - writer.print(CMethodBindingEmitter.cThisArgumentName() + "->"); + unit.emit(CMethodBindingEmitter.cThisArgumentName() + "->"); } - writer.print(getNativeName()); - writer.print("("); - emitBodyPassCArguments(writer); - writer.println(");"); + unit.emit(getNativeName()); + unit.emit("("); + emitBodyPassCArguments(); + unit.emitln(");"); } /** Emits the user-defined C variable assignments from the TemporaryCVariableAssignments directive in the .cfg file. */ - protected void emitBodyUserVariableAssignments(final PrintWriter writer) { + protected void emitBodyUserVariableAssignments() { if (temporaryCVariableAssignments != null) { for (final String val : temporaryCVariableAssignments) { - writer.print(" "); - writer.println(val); + unit.emit(" "); + unit.emitln(val); } } } - protected void emitBodyReturnResult(final PrintWriter writer) + protected void emitBodyReturnResult() { // WARNING: this code assumes that the return type has already been // typedef-resolved. @@ -1021,28 +1015,29 @@ public class CMethodBindingEmitter extends FunctionEmitter { if (!cReturnType.isVoid()) { final JavaType javaReturnType = binding.getJavaReturnType(); if (javaReturnType.isPrimitive()) { - writer.print(" return "); + unit.emit(" return "); if (cReturnType.isPointer()) { // Pointer being converted to int or long: cast this result // (through intptr_t to avoid compiler warnings with gcc) - writer.print("(" + javaReturnType.jniTypeName() + ") (intptr_t) "); + unit.emit("(" + javaReturnType.jniTypeName() + ") (intptr_t) "); } - writer.println("_res;"); - } else if ( !cReturnType.isPointer() && javaReturnType.isCompoundTypeWrapper() ) { // FIXME: Compound call-by-value + unit.emitln("_res;"); + } else if ( !cReturnType.isPointer() && javaReturnType.isCompoundTypeWrapper() ) { // isReturnCompoundByValue() final String returnSizeOf; if (returnValueCapacityExpression != null) { returnSizeOf = returnValueCapacityExpression.format(argumentNameArray()); } else { returnSizeOf = "sizeof(" + cReturnType.getCName() + ")"; } - writer.println(" return JVMUtil_NewDirectByteBufferCopy(env, &_res, "+returnSizeOf+");"); + unit.emitln(" return JVMUtil_NewDirectByteBufferCopy(env, _clazzBuffers, &_res, "+returnSizeOf+");"); + unit.addTailCode(CCodeUnit.NewDirectByteBufferCopyUnitCode); } else if (javaReturnType.isNIOBuffer() || javaReturnType.isCompoundTypeWrapper()) { - writer.println(" if (NULL == _res) return NULL;"); - writer.print(" return (*env)->NewDirectByteBuffer(env, (void *)_res, "); + unit.emitln(" if (NULL == _res) return NULL;"); + unit.emit(" return (*env)->NewDirectByteBuffer(env, (void *)_res, "); // See whether capacity has been specified if (returnValueCapacityExpression != null) { - writer.println( returnValueCapacityExpression.format( argumentNameArray() ) + ");"); + unit.emitln( returnValueCapacityExpression.format( argumentNameArray() ) + ");"); } else { final Type cReturnTargetType = cReturnType.isPointer() ? cReturnType.getTargetType() : null; int mode = 0; @@ -1062,22 +1057,22 @@ public class CMethodBindingEmitter extends FunctionEmitter { binding.getCSymbol().getASTLocusTag() ); } - writer.println("sizeof(" + cReturnTargetType.getCName() + ") );"); + unit.emitln("sizeof(" + cReturnTargetType.getCName() + ") );"); mode = 10; } else if( cReturnTargetType.asCompound().getNumFields() == 0 ) { // anonymous struct pointer: pass pointer - writer.println("sizeof(" + cReturnType.getCName() + ") );"); + unit.emitln("sizeof(" + cReturnType.getCName() + ") );"); mode = 11; } } if( 0 == mode ) { if( cReturnTargetType.isPrimitive() ) { // primitive pointer: pass primitive - writer.println("sizeof(" + cReturnTargetType.getCName() + ") );"); + unit.emitln("sizeof(" + cReturnTargetType.getCName() + ") );"); mode = 20; } else if( cReturnTargetType.isVoid() ) { // void pointer: pass pointer - writer.println("sizeof(" + cReturnType.getCName() + ") );"); + unit.emitln("sizeof(" + cReturnType.getCName() + ") );"); mode = 21; } } @@ -1085,37 +1080,37 @@ public class CMethodBindingEmitter extends FunctionEmitter { if( 0 == mode ) { if( null != cfg.typeInfo(cReturnType) ) { // javaReturnType.isOpaqued() covered above via isPrimitive() // Opaque - writer.println("sizeof(" + cReturnType.getCName() + ") );"); + unit.emitln("sizeof(" + cReturnType.getCName() + ") );"); mode = 88; } else { final String wmsg = "Assumed return size of equivalent C return type"; - writer.println("sizeof(" + cReturnType.getCName() + ") ); // WARNING: "+wmsg); + unit.emitln("sizeof(" + cReturnType.getCName() + ") ); // WARNING: "+wmsg); mode = 99; LOG.warning(binding.getCSymbol().getASTLocusTag(), "No capacity specified for java.nio.Buffer return " + "value for function \"" + binding.getName() + "\". " + wmsg + " (sizeof(" + cReturnType.getCName() + ")): " + binding); } } - writer.println(" /** "); - writer.println(" * mode: "+mode); - writer.println(" * cReturnType: "+cReturnType.getDebugString()); - writer.println(" * cReturnTargetType: "+cReturnTargetType.getDebugString()); - writer.println(" * javaReturnType: "+javaReturnType.getDebugString()); - writer.println(" */"); + unit.emitln(" /** "); + unit.emitln(" * mode: "+mode); + unit.emitln(" * cReturnType: "+cReturnType.getDebugString()); + unit.emitln(" * cReturnTargetType: "+cReturnTargetType.getDebugString()); + unit.emitln(" * javaReturnType: "+javaReturnType.getDebugString()); + unit.emitln(" */"); } } else if (javaReturnType.isString()) { - writer.println(" if (NULL == _res) return NULL;"); - writer.println(" return (*env)->NewStringUTF(env, (const char *)_res);"); + unit.emitln(" if (NULL == _res) return NULL;"); + unit.emitln(" return (*env)->NewStringUTF(env, (const char *)_res);"); } else if (javaReturnType.isArrayOfCompoundTypeWrappers() || (javaReturnType.isArray() && javaReturnType.isNIOByteBufferArray())) { - writer.println(" if (NULL == _res) return NULL;"); + unit.emitln(" if (NULL == _res) return NULL;"); if (returnValueLengthExpression == null) { throw new GlueGenException("Error while generating C code: no length specified for array returned from function " + binding, binding.getCSymbol().getASTLocusTag()); } - writer.println(" " + arrayResLength + " = " + returnValueLengthExpression.format(argumentNameArray()) + ";"); - writer.println(" " + arrayRes + " = (*env)->NewObjectArray(env, " + arrayResLength + ", (*env)->FindClass(env, \"java/nio/ByteBuffer\"), NULL);"); - writer.println(" for (" + arrayIdx + " = 0; " + arrayIdx + " < " + arrayResLength + "; " + arrayIdx + "++) {"); + unit.emitln(" " + arrayResLength + " = " + returnValueLengthExpression.format(argumentNameArray()) + ";"); + unit.emitln(" " + arrayRes + " = (*env)->NewObjectArray(env, " + arrayResLength + ", (*env)->FindClass(env, \"java/nio/ByteBuffer\"), NULL);"); + unit.emitln(" for (" + arrayIdx + " = 0; " + arrayIdx + " < " + arrayResLength + "; " + arrayIdx + "++) {"); final Type retType = binding.getCSymbol().getReturnType(); Type pointerType; if (retType.isPointer()) { @@ -1123,10 +1118,10 @@ public class CMethodBindingEmitter extends FunctionEmitter { } else { pointerType = retType.asArray().getBaseElementType(); } - writer.println(" (*env)->SetObjectArrayElement(env, " + arrayRes + ", " + arrayIdx + + unit.emitln(" (*env)->SetObjectArrayElement(env, " + arrayRes + ", " + arrayIdx + ", (*env)->NewDirectByteBuffer(env, (void *)_res[" + arrayIdx + "], sizeof(" + pointerType.getCName() + ")));"); - writer.println(" }"); - writer.println(" return " + arrayRes + ";"); + unit.emitln(" }"); + unit.emitln(" return " + arrayRes + ";"); } else if (javaReturnType.isArray()) { // FIXME: must have user provide length of array in .cfg file // by providing a constant value, input parameter, or @@ -1140,23 +1135,23 @@ public class CMethodBindingEmitter extends FunctionEmitter { // FIXME: This is approximately what will be required here // - //writer.print(" "); - //writer.print(arrayRes); - //writer.print(" = (*env)->New"); - //writer.print(capitalizedComponentType); - //writer.print("Array(env, "); - //writer.print(arrayResLength); - //writer.println(");"); - //writer.print(" (*env)->Set"); - //writer.print(capitalizedComponentType); - //writer.print("ArrayRegion(env, "); - //writer.print(arrayRes); - //writer.print(", 0, "); - //writer.print(arrayResLength); - //writer.println(", _res);"); - //writer.print(" return "); - //writer.print(arrayRes); - //writer.println(";"); + //unit().emit(" "); + //unit().emit(arrayRes); + //unit().emit(" = (*env)->New"); + //unit().emit(capitalizedComponentType); + //unit().emit("Array(env, "); + //unit().emit(arrayResLength); + //unit().emitln(");"); + //unit().emit(" (*env)->Set"); + //unit().emit(capitalizedComponentType); + //unit().emit("ArrayRegion(env, "); + //unit().emit(arrayRes); + //unit().emit(", 0, "); + //unit().emit(arrayResLength); + //unit().emitln(", _res);"); + //unit().emit(" return "); + //unit().emit(arrayRes); + //unit().emitln(";"); } else { throw new GlueGenException("Unhandled return type: "+javaReturnType.getDebugString()+" for "+binding, binding.getCSymbol().getReturnType().getASTLocusTag()); @@ -1173,6 +1168,9 @@ public class CMethodBindingEmitter extends FunctionEmitter { buf.append(JavaEmitter.jniMangle(getImplName())); buf.append(getImplSuffix()); buf.append("__"); + if (binding.isReturnCompoundByValue()) { + jniMangle(Class.class, buf, true); + } if (binding.hasContainingType()) { // "this" argument always comes down in argument 0 as direct buffer jniMangle(java.nio.ByteBuffer.class, buf, true); @@ -1276,77 +1274,74 @@ public class CMethodBindingEmitter extends FunctionEmitter { } } - private void emitOutOfMemoryCheck(final PrintWriter writer, final String varName, final String errorMessage) { - writer.println(" if ( NULL == " + varName + " ) {"); - writer.println(" (*env)->ThrowNew(env, (*env)->FindClass(env, \"java/lang/OutOfMemoryError\"),"); - writer.print(" \"" + errorMessage); - writer.print(" in native dispatcher for \\\""); - writer.print(getInterfaceName()); - writer.println("\\\"\");"); - writer.print(" return"); + private void emitOutOfMemoryCheck(final String varName, final String errorMessage) { + unit.emitln(" if ( NULL == " + varName + " ) {"); + unit.emitln(" (*env)->ThrowNew(env, (*env)->FindClass(env, \"java/lang/OutOfMemoryError\"),"); + unit.emit(" \"" + errorMessage); + unit.emit(" in native dispatcher for \\\""); + unit.emit(getInterfaceName()); + unit.emitln("\\\"\");"); + unit.emit(" return"); if (!binding.getJavaReturnType().isVoid()) { - writer.print(" 0"); + unit.emit(" 0"); } - writer.println(";"); - writer.println(" }"); + unit.emitln(";"); + unit.emitln(" }"); } - private void emitMalloc(final PrintWriter writer, - final String targetVarName, + private void emitMalloc(final String targetVarName, final String elementTypeString, final boolean elementTypeIsConst, final String numElementsExpression, final String mallocFailureErrorString) { - writer.print(" "); - writer.print(targetVarName); - writer.print(" = ("); + unit.emit(" "); + unit.emit(targetVarName); + unit.emit(" = ("); if(elementTypeIsConst) { - writer.print("const "); + unit.emit("const "); } - writer.print(elementTypeString); - writer.print(" *) malloc("); - writer.print(numElementsExpression); - writer.print(" * sizeof("); - writer.print(elementTypeString); - writer.println("));"); + unit.emit(elementTypeString); + unit.emit(" *) malloc("); + unit.emit(numElementsExpression); + unit.emit(" * sizeof("); + unit.emit(elementTypeString); + unit.emitln("));"); // Catch memory allocation failure - emitOutOfMemoryCheck( writer, targetVarName, mallocFailureErrorString); + emitOutOfMemoryCheck( targetVarName, mallocFailureErrorString); } - private void emitCalloc(final PrintWriter writer, - final String targetVarName, + private void emitCalloc(final String targetVarName, final String elementTypeString, final String numElementsExpression, final String mallocFailureErrorString) { - writer.print(" "); - writer.print(targetVarName); - writer.print(" = ("); - writer.print(elementTypeString); - writer.print(" *) calloc("); - writer.print(numElementsExpression); - writer.print(", sizeof("); - writer.print(elementTypeString); - writer.println("));"); + unit.emit(" "); + unit.emit(targetVarName); + unit.emit(" = ("); + unit.emit(elementTypeString); + unit.emit(" *) calloc("); + unit.emit(numElementsExpression); + unit.emit(", sizeof("); + unit.emit(elementTypeString); + unit.emitln("));"); // Catch memory allocation failure - emitOutOfMemoryCheck( writer, targetVarName, mallocFailureErrorString); + emitOutOfMemoryCheck( targetVarName, mallocFailureErrorString); } - private void emitGetStringChars(final PrintWriter writer, - final String sourceVarName, + private void emitGetStringChars(final String sourceVarName, final String receivingVarName, final boolean isUTF8, final boolean emitElseClause) { - writer.println(" if ( NULL != " + sourceVarName + " ) {"); + unit.emitln(" if ( NULL != " + sourceVarName + " ) {"); if (isUTF8) { - writer.print(" "); - writer.print(receivingVarName); - writer.print(" = (*env)->GetStringUTFChars(env, "); - writer.print(sourceVarName); - writer.println(", (jboolean*)NULL);"); + unit.emit(" "); + unit.emit(receivingVarName); + unit.emit(" = (*env)->GetStringUTFChars(env, "); + unit.emit(sourceVarName); + unit.emitln(", (jboolean*)NULL);"); // Catch memory allocation failure in the event that the VM didn't pin // the String and failed to allocate a copy - emitOutOfMemoryCheck( writer, receivingVarName, "Failed to get UTF-8 chars for argument \\\""+sourceVarName+"\\\""); + emitOutOfMemoryCheck( receivingVarName, "Failed to get UTF-8 chars for argument \\\""+sourceVarName+"\\\""); } else { // The UTF-16 case is basically Windows specific. Unix platforms // tend to use only the UTF-8 encoding. On Windows the problem @@ -1355,82 +1350,78 @@ public class CMethodBindingEmitter extends FunctionEmitter { // null-terminated Unicode string. For this reason we explicitly // calloc our buffer, including the null terminator, and use // GetStringRegion to fetch the string's characters. - emitCalloc(writer, - receivingVarName, + emitCalloc(receivingVarName, "jchar", "(*env)->GetStringLength(env, " + sourceVarName + ") + 1", "Could not allocate temporary buffer for copying string argument \\\""+sourceVarName+"\\\""); - writer.println(" (*env)->GetStringRegion(env, " + sourceVarName + ", 0, (*env)->GetStringLength(env, " + sourceVarName + "), " + receivingVarName + ");"); + unit.emitln(" (*env)->GetStringRegion(env, " + sourceVarName + ", 0, (*env)->GetStringLength(env, " + sourceVarName + "), " + receivingVarName + ");"); } - writer.print(" }"); + unit.emit(" }"); if (emitElseClause) { - writer.print(" else {"); - writer.print(" "); - writer.print(receivingVarName); - writer.println(" = NULL;"); - writer.println(" }"); + unit.emit(" else {"); + unit.emit(" "); + unit.emit(receivingVarName); + unit.emitln(" = NULL;"); + unit.emitln(" }"); } else { - writer.println(); + unit.emitln(); } } - private void emitGetDirectBufferAddress(final PrintWriter writer, - final String sourceVarName, + private void emitGetDirectBufferAddress(final String sourceVarName, final String receivingVarTypeString, final String receivingVarName, final boolean receivingIsPtrPtr, final String byteOffsetVarName, final boolean emitElseClause) { - writer.println(" if ( NULL != " + sourceVarName + " ) {"); - writer.print(" "); - writer.print(" "); + unit.emitln(" if ( NULL != " + sourceVarName + " ) {"); + unit.emit(" "); + unit.emit(" "); if( receivingIsPtrPtr ) { - writer.print(receivingVarName+" = ("+receivingVarTypeString+") (((char*) (*env)->GetDirectBufferAddress(env, "+sourceVarName+"))"); - writer.println(" + " + ((byteOffsetVarName != null) ? byteOffsetVarName : "0") + ");"); + unit.emit(receivingVarName+" = ("+receivingVarTypeString+") (((char*) (*env)->GetDirectBufferAddress(env, "+sourceVarName+"))"); + unit.emitln(" + " + ((byteOffsetVarName != null) ? byteOffsetVarName : "0") + ");"); } else { // linear layout -> use memcpy - writer.println("memcpy((void *)"+receivingVarName+", (*env)->GetDirectBufferAddress(env, "+sourceVarName+"), sizeof("+receivingVarTypeString+"));"); + unit.emitln("memcpy((void *)"+receivingVarName+", (*env)->GetDirectBufferAddress(env, "+sourceVarName+"), sizeof("+receivingVarTypeString+"));"); } if (emitElseClause) { - writer.println(" } else {"); - writer.print(" "); - writer.print(" "); + unit.emitln(" } else {"); + unit.emit(" "); + unit.emit(" "); if( receivingIsPtrPtr ) { - writer.print(receivingVarName); - writer.println(" = NULL;"); + unit.emit(receivingVarName); + unit.emitln(" = NULL;"); } else { - writer.println("memset((void *)"+receivingVarName+", 0, sizeof("+receivingVarTypeString+"));"); + unit.emitln("memset((void *)"+receivingVarName+", 0, sizeof("+receivingVarTypeString+"));"); } } - writer.println(" }"); - writer.println(); + unit.emitln(" }"); + unit.emitln(); } - private void emitReturnDirectBufferAddress(final PrintWriter writer, - final String sourceVarName, - final String receivingVarTypeString, - final String receivingVarName, - final boolean receivingIsPtrPtr, - final String byteOffsetVarName) { - writer.print(" "); - writer.print(" "); + private void emitReturnDirectBufferAddress(final String sourceVarName, + final String receivingVarTypeString, + final String receivingVarName, + final boolean receivingIsPtrPtr, + final String byteOffsetVarName) { + unit.emit(" "); + unit.emit(" "); if( receivingIsPtrPtr ) { - writer.print("(((char*) (*env)->GetDirectBufferAddress(env, "+sourceVarName+"))"); - writer.println(" + " + ((byteOffsetVarName != null) ? byteOffsetVarName : "0") + ") = "+receivingVarName+";"); + unit.emit("(((char*) (*env)->GetDirectBufferAddress(env, "+sourceVarName+"))"); + unit.emitln(" + " + ((byteOffsetVarName != null) ? byteOffsetVarName : "0") + ") = "+receivingVarName+";"); throw new RuntimeException("incomplete implementation"); // FIXME doesn't work, currently unused } else { // linear layout -> use memcpy - writer.println("memcpy((*env)->GetDirectBufferAddress(env, "+sourceVarName+"), "+receivingVarName+", sizeof("+receivingVarTypeString+"));"); + unit.emitln("memcpy((*env)->GetDirectBufferAddress(env, "+sourceVarName+"), "+receivingVarName+", sizeof("+receivingVarTypeString+"));"); } - writer.println(); + unit.emitln(); } // Note: if the data in the Type needs to be converted from the Java memory // model to the C memory model prior to calling any C-side functions, then // an extra variable named XXX_copy (where XXX is the value of the // cVariableName argument) will be emitted and TRUE will be returned. - private boolean emitPointerDeclaration(final PrintWriter writer, - final JavaType javaType, + private boolean emitPointerDeclaration(final JavaType javaType, final Type cType, final String cVariableName, final String javaArgumentName) { @@ -1472,17 +1463,17 @@ public class CMethodBindingEmitter extends FunctionEmitter { ptrTypeString = cType.getCName(); } - writer.print(" "); + unit.emit(" "); if (!needsDataCopy) { // declare the pointer variable - writer.print(ptrTypeString); + unit.emit(ptrTypeString); if( !cType.isPointer() && javaType.isCompoundTypeWrapper() ) { // FIXME: Compound call-by-value - writer.print(" * "); + unit.emit(" * "); } else { - writer.print(" "); + unit.emit(" "); } - writer.print(cVariableName); - writer.println(" = NULL;"); + unit.emit(cVariableName); + unit.emitln(" = NULL;"); } else { // Declare a variable to hold a copy of the argument data in which the // incoming data has been properly laid out in memory to match the C @@ -1494,27 +1485,26 @@ public class CMethodBindingEmitter extends FunctionEmitter { cElementTypeName = cPtrType.getTargetType().asPointer().getCName(); } if (cType.isBaseTypeConst()) { - writer.print("const "); + unit.emit("const "); } - writer.print(cElementTypeName+" *"); + unit.emit(cElementTypeName+" *"); } else { if (cType.isBaseTypeConst()) { - writer.print("const "); + unit.emit("const "); } - writer.print(ptrTypeString); + unit.emit(ptrTypeString); } - writer.print(" "); - writer.print(cVariableName); - writer.print("_copy = NULL; /* copy of data in "); - writer.print(javaArgumentName); - writer.println(", laid out according to C memory model */"); + unit.emit(" "); + unit.emit(cVariableName); + unit.emit("_copy = NULL; /* copy of data in "); + unit.emit(javaArgumentName); + unit.emitln(", laid out according to C memory model */"); } return needsDataCopy; } - private void emitPointerConversion(final PrintWriter writer, - final MethodBinding binding, + private void emitPointerConversion(final MethodBinding binding, final JavaType type, final Type cType, final String incomingArgumentName, @@ -1531,8 +1521,7 @@ public class CMethodBindingEmitter extends FunctionEmitter { } else { cVariableType = cType.getCName(); } - emitGetDirectBufferAddress(writer, - incomingArgumentName, + emitGetDirectBufferAddress(incomingArgumentName, cVariableType, cVariableName, true, diff --git a/src/java/com/jogamp/gluegen/FunctionEmitter.java b/src/java/com/jogamp/gluegen/FunctionEmitter.java index bfbb73b..a089a41 100644 --- a/src/java/com/jogamp/gluegen/FunctionEmitter.java +++ b/src/java/com/jogamp/gluegen/FunctionEmitter.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2010-2023 JogAmp Community. All rights reserved. * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without @@ -39,12 +40,14 @@ package com.jogamp.gluegen; -import java.util.*; -import java.io.*; +import java.util.ArrayList; +import java.util.Iterator; import com.jogamp.gluegen.cgram.types.FunctionSymbol; -import com.jogamp.gluegen.cgram.types.Type; +/** + * Generic function emitter to produce C (JNI) or Java code stubs to its {@link CodeUnit}, invoking a native function as described via {@link MethodBinding}. + */ public abstract class FunctionEmitter { public static final EmissionModifier STATIC = new EmissionModifier("static"); @@ -52,18 +55,20 @@ public abstract class FunctionEmitter { private final boolean isInterface; private final ArrayList<EmissionModifier> modifiers; private CommentEmitter commentEmitter = null; - private final PrintWriter defaultOutput; + protected final MethodBinding binding; + protected final CodeUnit unit; // Only present to provide more clear comments protected final JavaConfiguration cfg; /** * Constructs the FunctionEmitter with a CommentEmitter that emits nothing. */ - public FunctionEmitter(final PrintWriter defaultOutput, final boolean isInterface, final JavaConfiguration configuration) { - assert(defaultOutput != null); + public FunctionEmitter(final MethodBinding binding, final CodeUnit unit, final boolean isInterface, final JavaConfiguration configuration) { + assert(unit != null); this.isInterface = isInterface; this.modifiers = new ArrayList<EmissionModifier>(); - this.defaultOutput = defaultOutput; + this.binding = binding; + this.unit = unit; this.cfg = configuration; } @@ -74,13 +79,15 @@ public abstract class FunctionEmitter { isInterface = arg.isInterface; modifiers = new ArrayList<EmissionModifier>(arg.modifiers); commentEmitter = arg.commentEmitter; - defaultOutput = arg.defaultOutput; + binding = arg.binding; + unit = arg.unit; cfg = arg.cfg; } - public boolean isInterface() { return isInterface; } + public final boolean isInterface() { return isInterface; } - public PrintWriter getDefaultOutput() { return defaultOutput; } + public final MethodBinding getBinding() { return binding; } + public final CodeUnit getUnit() { return unit; } public void addModifiers(final Iterator<EmissionModifier> mi) { while (mi.hasNext()) { @@ -104,31 +111,18 @@ public abstract class FunctionEmitter { public abstract FunctionSymbol getCSymbol(); /** - * Emit the function to the specified output (instead of the default - * output). - */ - public void emit(final PrintWriter output) { - emitDocComment(output); - //output.println(" // Emitter: " + getClass().getName()); - emitSignature(output); - emitBody(output); - } - - /** - * Emit the function to the default output (the output that was passed to - * the constructor) + * Emit the function to the {@link #getUnit()} */ public final void emit() { - emit(getDefaultOutput()); + emitDocComment(); + //output.println(" // Emitter: " + getClass().getName()); + emitSignature(); + emitBody(); } - /** Returns, as a String, whatever {@link #emit} would output. */ @Override public String toString() { - final StringWriter sw = new StringWriter(500); - final PrintWriter w = new PrintWriter(sw); - emit(w); - return sw.toString(); + return getClass().getSimpleName()+"["+binding.toString()+"]"; } /** @@ -145,47 +139,47 @@ public abstract class FunctionEmitter { */ public CommentEmitter getCommentEmitter() { return commentEmitter; } - protected void emitDocComment(final PrintWriter writer) { + protected void emitDocComment() { if (commentEmitter != null) { - writer.print(getBaseIndentString()); //indent + unit.emit(getBaseIndentString()); //indent - writer.print(getCommentStartString()); + unit.emit(getCommentStartString()); - commentEmitter.emit(this, writer); + commentEmitter.emit(this, unit.output); - writer.print(getBaseIndentString()); //indent + unit.emit(getBaseIndentString()); //indent - writer.println(getCommentEndString()); + unit.emitln(getCommentEndString()); } } - protected void emitSignature(final PrintWriter writer) { + protected void emitSignature() { - writer.print(getBaseIndentString()); // indent method + unit.emit(getBaseIndentString()); // indent method - final int numEmitted = emitModifiers(writer); + final int numEmitted = emitModifiers(); if (numEmitted > 0) { - writer.print(" "); + unit.emit(" "); } - emitReturnType(writer); - writer.print(" "); + emitReturnType(); + unit.emit(" "); - emitName(writer); - writer.print("("); + emitName(); + unit.emit("("); - emitArguments(writer); - writer.print(")"); + emitArguments(); + unit.emit(")"); } - protected int emitModifiers(final PrintWriter writer) { + protected int emitModifiers() { int numEmitted = 0; for (final Iterator<EmissionModifier> it = getModifiers(); it.hasNext(); ) { - writer.print(it.next()); + unit.emit(it.next().toString()); ++numEmitted; if (it.hasNext()) { - writer.print(" "); + unit.emit(" "); } } return numEmitted; @@ -196,11 +190,11 @@ public abstract class FunctionEmitter { protected String getCommentStartString() { return "/* "; } protected String getCommentEndString() { return " */"; } - protected abstract void emitReturnType(PrintWriter writer); - protected abstract void emitName(PrintWriter writer); + protected abstract void emitReturnType(); + protected abstract void emitName(); /** Returns the number of arguments emitted. */ - protected abstract int emitArguments(PrintWriter writer); - protected abstract void emitBody(PrintWriter writer); + protected abstract int emitArguments(); + protected abstract void emitBody(); public static class EmissionModifier { diff --git a/src/java/com/jogamp/gluegen/JavaMethodBindingEmitter.java b/src/java/com/jogamp/gluegen/JavaMethodBindingEmitter.java index d3fca14..e7903fe 100644 --- a/src/java/com/jogamp/gluegen/JavaMethodBindingEmitter.java +++ b/src/java/com/jogamp/gluegen/JavaMethodBindingEmitter.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2010-2023 JogAmp Community. All rights reserved. * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without @@ -52,9 +53,7 @@ import java.util.Iterator; import java.util.List; import java.util.Set; -/** - * An emitter that emits only the interface for a Java<->C JNI binding. - */ +/** Emits the Java-side component (interface and.or implementation) of the Java<->C JNI binding to its {@link CodeUnit}, see {@link FunctionEmitter}. */ public class JavaMethodBindingEmitter extends FunctionEmitter { public static final EmissionModifier PUBLIC = new EmissionModifier("public"); @@ -69,7 +68,6 @@ public class JavaMethodBindingEmitter extends FunctionEmitter { protected final CommentEmitter defaultInterfaceCommentEmitter = new InterfaceCommentEmitter(); protected final boolean tagNativeBinding; protected final boolean useNIODirectOnly; - protected final MethodBinding binding; // Exception type raised in the generated code if runtime checks fail private final String runtimeExceptionType; @@ -101,7 +99,7 @@ public class JavaMethodBindingEmitter extends FunctionEmitter { private static final String COMPOUND_ARRAY_SUFFIX = "_buf_array_copy"; public JavaMethodBindingEmitter(final MethodBinding binding, - final PrintWriter output, + final CodeUnit unit, final String runtimeExceptionType, final String unsupportedExceptionType, final boolean emitBody, @@ -115,8 +113,7 @@ public class JavaMethodBindingEmitter extends FunctionEmitter { final boolean isInterface, final boolean isNativeMethod, final boolean isPrivateNativeMethod, final JavaConfiguration configuration) { - super(output, isInterface, configuration); - this.binding = binding; + super(binding, unit, isInterface, configuration); this.runtimeExceptionType = runtimeExceptionType; this.unsupportedExceptionType = unsupportedExceptionType; this.emitBody = emitBody; @@ -139,7 +136,6 @@ public class JavaMethodBindingEmitter extends FunctionEmitter { public JavaMethodBindingEmitter(final JavaMethodBindingEmitter arg) { super(arg); - binding = arg.binding; runtimeExceptionType = arg.runtimeExceptionType; unsupportedExceptionType = arg.unsupportedExceptionType; emitBody = arg.emitBody; @@ -158,8 +154,6 @@ public class JavaMethodBindingEmitter extends FunctionEmitter { returnedArrayLengthExpressionOnlyForComments = arg.returnedArrayLengthExpressionOnlyForComments; } - public final MethodBinding getBinding() { return binding; } - public boolean isNativeMethod() { return isNativeMethod; } public boolean isPrivateNativeMethod() { return isPrivateNativeMethod; } public boolean isForDirectBufferImplementation() { return forDirectBufferImplementation; } @@ -263,8 +257,8 @@ public class JavaMethodBindingEmitter extends FunctionEmitter { } @Override - protected void emitReturnType(final PrintWriter writer) { - writer.print(getReturnTypeString(false)); + protected void emitReturnType() { + unit.emit(getReturnTypeString(false)); } protected String erasedTypeString(final JavaType type, final boolean skipBuffers) { @@ -336,25 +330,33 @@ public class JavaMethodBindingEmitter extends FunctionEmitter { } @Override - protected void emitName(final PrintWriter writer) { + protected void emitName() { if (isPrivateNativeMethod) { - writer.print(getNativeImplMethodName()); + unit.emit(getNativeImplMethodName()); } else if( isInterface()) { - writer.print(getInterfaceName()); + unit.emit(getInterfaceName()); } else { - writer.print(getImplName()); + unit.emit(getImplName()); } } @Override - protected int emitArguments(final PrintWriter writer) { + protected int emitArguments() { boolean needComma = false; int numEmitted = 0; + if( hasModifier(JavaMethodBindingEmitter.NATIVE) && binding.isReturnCompoundByValue() ) { + unit.emit("final Class<?> _clazzBuffers"); + ++numEmitted; + needComma = true; + } if (isPrivateNativeMethod && binding.hasContainingType()) { // Always emit outgoing "this" argument - writer.print("ByteBuffer "); - writer.print(javaThisArgumentName()); + if (needComma) { + unit.emit(", "); + } + unit.emit("ByteBuffer "); + unit.emit(javaThisArgumentName()); ++numEmitted; needComma = true; } @@ -378,12 +380,12 @@ public class JavaMethodBindingEmitter extends FunctionEmitter { } if (needComma) { - writer.print(", "); + unit.emit(", "); } - writer.print(erasedTypeString(type, false)); - writer.print(" "); - writer.print(getArgumentName(i)); + unit.emit(erasedTypeString(type, false)); + unit.emit(" "); + unit.emit(getArgumentName(i)); ++numEmitted; needComma = true; @@ -391,12 +393,12 @@ public class JavaMethodBindingEmitter extends FunctionEmitter { // Add Buffer and array index offset arguments after each associated argument if (forDirectBufferImplementation || forIndirectBufferAndArrayImplementation) { if (type.isNIOBuffer()) { - writer.print(", int " + byteOffsetArgName(i)); + unit.emit(", int " + byteOffsetArgName(i)); if(!useNIODirectOnly) { - writer.print(", boolean " + isNIOArgName(i)); + unit.emit(", boolean " + isNIOArgName(i)); } } else if (type.isNIOBufferArray()) { - writer.print(", int[] " + byteOffsetArrayArgName(i)); + unit.emit(", int[] " + byteOffsetArrayArgName(i)); } } @@ -405,7 +407,7 @@ public class JavaMethodBindingEmitter extends FunctionEmitter { if(useNIOOnly) { throw new RuntimeException("NIO[Direct]Only "+binding+" is set, but "+getArgumentName(i)+" is a primitive array"); } - writer.print(", int " + offsetArgName(i)); + unit.emit(", int " + offsetArgName(i)); } } return numEmitted; @@ -441,46 +443,46 @@ public class JavaMethodBindingEmitter extends FunctionEmitter { } @Override - protected void emitBody(final PrintWriter writer) { + protected void emitBody() { if (!emitBody) { - writer.println(';'); + unit.emitln(";"); } else { final MethodBinding mBinding = getBinding(); - writer.println(" {"); - writer.println(); + unit.emitln(" {"); + unit.emitln(); if (isUnimplemented) { - writer.println(" throw new " + getUnsupportedExceptionType() + "(\"Unimplemented\");"); + unit.emitln(" throw new " + getUnsupportedExceptionType() + "(\"Unimplemented\");"); } else { - emitPrologueOrEpilogue(prologue, writer); - emitPreCallSetup(mBinding, writer); + emitPrologueOrEpilogue(prologue); + emitPreCallSetup(mBinding); //emitReturnVariableSetup(binding, writer); - emitReturnVariableSetupAndCall(mBinding, writer); + emitReturnVariableSetupAndCall(mBinding); } - writer.println(" }"); + unit.emitln(" }"); } } - protected void emitPrologueOrEpilogue(final List<String> code, final PrintWriter writer) { + protected void emitPrologueOrEpilogue(final List<String> code) { if (code != null) { final String[] argumentNames = argumentNameArray(); for (final String str : code) { try { final MessageFormat fmt = new MessageFormat(str); - writer.println(" " + fmt.format(argumentNames)); + unit.emitln(" " + fmt.format(argumentNames)); } catch (final IllegalArgumentException e) { // (Poorly) handle case where prologue / epilogue contains blocks of code with braces - writer.println(" " + str); + unit.emitln(" " + str); } } } } - protected void emitPreCallSetup(final MethodBinding binding, final PrintWriter writer) { - emitArrayLengthAndNIOBufferChecks(binding, writer); - emitCompoundArrayCopies(binding, writer); + protected void emitPreCallSetup(final MethodBinding binding) { + emitArrayLengthAndNIOBufferChecks(binding); + emitCompoundArrayCopies(binding); } - protected void emitArrayLengthAndNIOBufferChecks(final MethodBinding binding, final PrintWriter writer) { + protected void emitArrayLengthAndNIOBufferChecks(final MethodBinding binding) { // Check lengths of any incoming arrays if necessary for (int i = 0; i < binding.getNumArguments(); i++) { final Type type = binding.getCArgumentType(i); @@ -489,58 +491,58 @@ public class JavaMethodBindingEmitter extends FunctionEmitter { // Simply add a range check upfront final ArrayType arrayType = type.asArray(); if (javaType.isNIOBuffer()) { - writer.println(" if ( Buffers.remainingElem("+getArgumentName(i)+") < " + arrayType.getLength() + ")"); + unit.emitln(" if ( Buffers.remainingElem("+getArgumentName(i)+") < " + arrayType.getLength() + ")"); } else { - writer.println(" if ( "+getArgumentName(i)+".length < " + arrayType.getLength() + ")"); + unit.emitln(" if ( "+getArgumentName(i)+".length < " + arrayType.getLength() + ")"); } - writer.print(" throw new " + getRuntimeExceptionType() + + unit.emit(" throw new " + getRuntimeExceptionType() + "(\"Array \\\"" + getArgumentName(i) + "\\\" length (\" + "); if (javaType.isNIOBuffer()) { - writer.print("Buffers.remainingElem("+getArgumentName(i)+")"); + unit.emit("Buffers.remainingElem("+getArgumentName(i)+")"); } else { - writer.print(getArgumentName(i)+".length"); + unit.emit(getArgumentName(i)+".length"); } - writer.println("+ \") was less than the required (" + arrayType.getLength() + ")\");"); + unit.emitln("+ \") was less than the required (" + arrayType.getLength() + ")\");"); } if (javaType.isNIOBuffer()) { if (useNIODirectOnly) { - writer.println(" if (!Buffers.isDirect(" + getArgumentName(i) + "))"); - writer.println(" throw new " + getRuntimeExceptionType() + "(\"Argument \\\"" + + unit.emitln(" if (!Buffers.isDirect(" + getArgumentName(i) + "))"); + unit.emitln(" throw new " + getRuntimeExceptionType() + "(\"Argument \\\"" + getArgumentName(i) + "\\\" is not a direct buffer\");"); } else { - writer.println(" final boolean " + isNIOArgName(i) + " = Buffers.isDirect(" + getArgumentName(i) + ");"); + unit.emitln(" final boolean " + isNIOArgName(i) + " = Buffers.isDirect(" + getArgumentName(i) + ");"); } } else if (javaType.isNIOBufferArray()) { // All buffers passed down in an array of NIO buffers must be direct final String argName = getArgumentName(i); final String arrayName = byteOffsetArrayArgName(i); - writer.println(" final int[] " + arrayName + " = new int[" + argName + ".length];"); + unit.emitln(" final int[] " + arrayName + " = new int[" + argName + ".length];"); // Check direct buffer properties of all buffers within - writer.println(" if (" + argName + " != null) {"); - writer.println(" for (int _ctr = 0; _ctr < " + argName + ".length; _ctr++) {"); - writer.println(" if (!Buffers.isDirect(" + argName + "[_ctr])) {"); - writer.println(" throw new " + getRuntimeExceptionType() + + unit.emitln(" if (" + argName + " != null) {"); + unit.emitln(" for (int _ctr = 0; _ctr < " + argName + ".length; _ctr++) {"); + unit.emitln(" if (!Buffers.isDirect(" + argName + "[_ctr])) {"); + unit.emitln(" throw new " + getRuntimeExceptionType() + "(\"Element \" + _ctr + \" of argument \\\"" + getArgumentName(i) + "\\\" was not a direct buffer\");"); - writer.println(" }"); + unit.emitln(" }"); // get the Buffer Array offset values and save them into another array to send down to JNI - writer.print (" " + arrayName + "[_ctr] = Buffers.getDirectBufferByteOffset("); - writer.println(argName + "[_ctr]);"); - writer.println(" }"); - writer.println(" }"); + unit.emit (" " + arrayName + "[_ctr] = Buffers.getDirectBufferByteOffset("); + unit.emitln(argName + "[_ctr]);"); + unit.emitln(" }"); + unit.emitln(" }"); } else if (javaType.isPrimitiveArray()) { final String argName = getArgumentName(i); final String offsetArg = offsetArgName(i); - writer.println(" if(" + argName + " != null && " + argName + ".length <= " + offsetArg + ")"); - writer.print (" throw new " + getRuntimeExceptionType()); - writer.println("(\"array offset argument \\\"" + offsetArg + "\\\" (\" + " + offsetArg + + unit.emitln(" if(" + argName + " != null && " + argName + ".length <= " + offsetArg + ")"); + unit.emit (" throw new " + getRuntimeExceptionType()); + unit.emitln("(\"array offset argument \\\"" + offsetArg + "\\\" (\" + " + offsetArg + " + \") equals or exceeds array length (\" + " + argName + ".length + \")\");"); } } } - protected void emitCompoundArrayCopies(final MethodBinding binding, final PrintWriter writer) { + protected void emitCompoundArrayCopies(final MethodBinding binding) { // If the method binding uses outgoing arrays of compound type // wrappers, we need to generate a temporary copy of this array // into a ByteBuffer[] for processing by the native code @@ -550,73 +552,81 @@ public class JavaMethodBindingEmitter extends FunctionEmitter { if (javaType.isArrayOfCompoundTypeWrappers()) { final String argName = getArgumentName(i); final String tempArrayName = argName + COMPOUND_ARRAY_SUFFIX; - writer.println(" final ByteBuffer[] " + tempArrayName + " = new ByteBuffer[" + argName + ".length];"); - writer.println(" for (int _ctr = 0; _ctr < + " + argName + ".length; _ctr++) {"); - writer.println(" " + javaType.getName() + " _tmp = " + argName + "[_ctr];"); - writer.println(" " + tempArrayName + "[_ctr] = ((_tmp == null) ? null : _tmp.getBuffer());"); - writer.println(" }"); + unit.emitln(" final ByteBuffer[] " + tempArrayName + " = new ByteBuffer[" + argName + ".length];"); + unit.emitln(" for (int _ctr = 0; _ctr < + " + argName + ".length; _ctr++) {"); + unit.emitln(" " + javaType.getName() + " _tmp = " + argName + "[_ctr];"); + unit.emitln(" " + tempArrayName + "[_ctr] = ((_tmp == null) ? null : _tmp.getBuffer());"); + unit.emitln(" }"); } } } } - protected void emitCall(final MethodBinding binding, final PrintWriter writer) { - writer.print(getNativeImplMethodName()); - writer.print("("); - emitCallArguments(binding, writer); - writer.print(");"); + protected void emitCall(final MethodBinding binding) { + unit.emit(getNativeImplMethodName()); + unit.emit("("); + emitCallArguments(binding); + unit.emit(");"); } - protected void emitReturnVariableSetupAndCall(final MethodBinding binding, final PrintWriter writer) { - writer.print(" "); + protected void emitReturnVariableSetupAndCall(final MethodBinding binding) { + unit.emit(" "); final JavaType returnType = binding.getJavaReturnType(); boolean needsResultAssignment = false; if (!returnType.isVoid()) { if (returnType.isCompoundTypeWrapper() || returnType.isNIOBuffer()) { - writer.println("final ByteBuffer _res;"); + unit.emitln("final ByteBuffer _res;"); needsResultAssignment = true; } else if (returnType.isArrayOfCompoundTypeWrappers()) { - writer.println("final ByteBuffer[] _res;"); + unit.emitln("final ByteBuffer[] _res;"); needsResultAssignment = true; } else if (((epilogue != null) && (epilogue.size() > 0)) || binding.signatureUsesArraysOfCompoundTypeWrappers()) { - writer.print("final "); - emitReturnType(writer); - writer.println(" _res;"); + unit.emit("final "); + emitReturnType(); + unit.emitln(" _res;"); needsResultAssignment = true; } } if (needsResultAssignment) { - writer.print(" _res = "); + unit.emit(" _res = "); } else { - writer.print(" "); + unit.emit(" "); if (!returnType.isVoid()) { - writer.print("return "); + unit.emit("return "); } } - emitCall(binding, writer); - writer.println(); + emitCall(binding); + unit.emitln(); - emitPostCallCleanup(binding, writer); - emitPrologueOrEpilogue(epilogue, writer); + emitPostCallCleanup(binding); + emitPrologueOrEpilogue(epilogue); if (needsResultAssignment) { - emitCallResultReturn(binding, writer); + emitCallResultReturn(binding); } } - protected int emitCallArguments(final MethodBinding binding, final PrintWriter writer) { + protected int emitCallArguments(final MethodBinding binding) { boolean needComma = false; int numArgsEmitted = 0; + if( binding.isReturnCompoundByValue() ) { + unit.emit("com.jogamp.common.nio.Buffers.class"); + needComma = true; + ++numArgsEmitted; + } if (binding.hasContainingType()) { // Emit this pointer assert(binding.getContainingType().isCompoundTypeWrapper()); - writer.print("getBuffer()"); + if (needComma) { + unit.emit(", "); + } + unit.emit("getBuffer()"); needComma = true; ++numArgsEmitted; } @@ -635,81 +645,81 @@ public class JavaMethodBindingEmitter extends FunctionEmitter { } if (needComma) { - writer.print(", "); + unit.emit(", "); } if (type.isCompoundTypeWrapper()) { - writer.print("(("); + unit.emit("(("); } if (type.isNIOBuffer()) { if(type.isNIOPointerBuffer()) { if (useNIODirectOnly) { - writer.print( getArgumentName(i)+ " != null ? " + getArgumentName(i) + ".getBuffer() : null"); + unit.emit( getArgumentName(i)+ " != null ? " + getArgumentName(i) + ".getBuffer() : null"); } else { - writer.print( isNIOArgName(i) + " ? ( " + getArgumentName(i)+ " != null ? " + getArgumentName(i) + ".getBuffer() : null )"); - writer.print( " : Buffers.getArray(" + getArgumentName(i) + ")" ); + unit.emit( isNIOArgName(i) + " ? ( " + getArgumentName(i)+ " != null ? " + getArgumentName(i) + ".getBuffer() : null )"); + unit.emit( " : Buffers.getArray(" + getArgumentName(i) + ")" ); } } else { if (useNIODirectOnly) { - writer.print( getArgumentName(i) ); + unit.emit( getArgumentName(i) ); } else { - writer.print( isNIOArgName(i) + " ? " + getArgumentName(i) + " : Buffers.getArray(" + getArgumentName(i) + ")" ); + unit.emit( isNIOArgName(i) + " ? " + getArgumentName(i) + " : Buffers.getArray(" + getArgumentName(i) + ")" ); } } } else if (type.isArrayOfCompoundTypeWrappers()) { - writer.print(getArgumentName(i) + COMPOUND_ARRAY_SUFFIX); + unit.emit(getArgumentName(i) + COMPOUND_ARRAY_SUFFIX); } else { - writer.print(getArgumentName(i)); + unit.emit(getArgumentName(i)); } if (type.isCompoundTypeWrapper()) { - writer.print(" == null) ? null : "); - writer.print(getArgumentName(i)); - writer.print(".getBuffer())"); + unit.emit(" == null) ? null : "); + unit.emit(getArgumentName(i)); + unit.emit(".getBuffer())"); } if (type.isNIOBuffer()) { if (useNIODirectOnly) { - writer.print( ", Buffers.getDirectBufferByteOffset(" + getArgumentName(i) + ")"); + unit.emit( ", Buffers.getDirectBufferByteOffset(" + getArgumentName(i) + ")"); } else { - writer.print( ", " + isNIOArgName(i) + " ? Buffers.getDirectBufferByteOffset(" + getArgumentName(i) + ")"); - writer.print( " : Buffers.getIndirectBufferByteOffset(" + getArgumentName(i) + ")"); + unit.emit( ", " + isNIOArgName(i) + " ? Buffers.getDirectBufferByteOffset(" + getArgumentName(i) + ")"); + unit.emit( " : Buffers.getIndirectBufferByteOffset(" + getArgumentName(i) + ")"); } } else if (type.isNIOBufferArray()) { - writer.print(", " + byteOffsetArrayArgName(i)); + unit.emit(", " + byteOffsetArrayArgName(i)); } else if (type.isPrimitiveArray()) { if(type.isFloatArray()) { - writer.print(", Buffers.SIZEOF_FLOAT * "); + unit.emit(", Buffers.SIZEOF_FLOAT * "); } else if(type.isDoubleArray()) { - writer.print(", Buffers.SIZEOF_DOUBLE * "); + unit.emit(", Buffers.SIZEOF_DOUBLE * "); } else if(type.isByteArray()) { - writer.print(", "); + unit.emit(", "); } else if(type.isLongArray()) { - writer.print(", Buffers.SIZEOF_LONG * "); + unit.emit(", Buffers.SIZEOF_LONG * "); } else if(type.isShortArray()) { - writer.print(", Buffers.SIZEOF_SHORT * "); + unit.emit(", Buffers.SIZEOF_SHORT * "); } else if(type.isIntArray()) { - writer.print(", Buffers.SIZEOF_INT * "); + unit.emit(", Buffers.SIZEOF_INT * "); } else { throw new GlueGenException("Unsupported type for calculating array offset argument for " + getArgumentName(i) + " -- error occurred while processing Java glue code for " + getCSymbol().getAliasedString(), getCSymbol().getASTLocusTag()); } - writer.print(offsetArgName(i)); + unit.emit(offsetArgName(i)); } if (type.isNIOBuffer()) { if (!useNIODirectOnly) { - writer.print( ", " + isNIOArgName(i) ); + unit.emit( ", " + isNIOArgName(i) ); } } else if (type.isPrimitiveArray()) { if (useNIOOnly) { throw new GlueGenException("NIO[Direct]Only "+binding+" is set, but "+getArgumentName(i)+" is a primitive array", getCSymbol().getASTLocusTag()); } - writer.print( ", false"); + unit.emit( ", false"); } needComma = true; @@ -718,7 +728,7 @@ public class JavaMethodBindingEmitter extends FunctionEmitter { return numArgsEmitted; } - protected void emitPostCallCleanup(final MethodBinding binding, final PrintWriter writer) { + protected void emitPostCallCleanup(final MethodBinding binding) { if (binding.signatureUsesArraysOfCompoundTypeWrappers()) { // For each such array, we need to take the ByteBuffer[] that // came back from the C method invocation and wrap the @@ -727,65 +737,65 @@ public class JavaMethodBindingEmitter extends FunctionEmitter { final JavaType javaArgType = binding.getJavaArgumentType(i); if ( javaArgType.isArrayOfCompoundTypeWrappers() && !javaArgType.getElementCType().isBaseTypeConst() ) { final String argName = binding.getArgumentName(i); - writer.println(" for (int _ctr = 0; _ctr < " + argName + ".length; _ctr++) {"); - writer.println(" if ((" + argName + "[_ctr] == null && " + argName + COMPOUND_ARRAY_SUFFIX + "[_ctr] == null) ||"); - writer.println(" (" + argName + "[_ctr] != null && " + argName + "[_ctr].getBuffer() == " + argName + COMPOUND_ARRAY_SUFFIX + "[_ctr])) {"); - writer.println(" // No copy back needed"); - writer.println(" } else {"); - writer.println(" if (" + argName + COMPOUND_ARRAY_SUFFIX + "[_ctr] == null) {"); - writer.println(" " + argName + "[_ctr] = null;"); - writer.println(" } else {"); - writer.println(" " + argName + "[_ctr] = " + javaArgType.getName() + ".create(" + argName + COMPOUND_ARRAY_SUFFIX + "[_ctr]);"); - writer.println(" }"); - writer.println(" }"); - writer.println(" }"); + unit.emitln(" for (int _ctr = 0; _ctr < " + argName + ".length; _ctr++) {"); + unit.emitln(" if ((" + argName + "[_ctr] == null && " + argName + COMPOUND_ARRAY_SUFFIX + "[_ctr] == null) ||"); + unit.emitln(" (" + argName + "[_ctr] != null && " + argName + "[_ctr].getBuffer() == " + argName + COMPOUND_ARRAY_SUFFIX + "[_ctr])) {"); + unit.emitln(" // No copy back needed"); + unit.emitln(" } else {"); + unit.emitln(" if (" + argName + COMPOUND_ARRAY_SUFFIX + "[_ctr] == null) {"); + unit.emitln(" " + argName + "[_ctr] = null;"); + unit.emitln(" } else {"); + unit.emitln(" " + argName + "[_ctr] = " + javaArgType.getName() + ".create(" + argName + COMPOUND_ARRAY_SUFFIX + "[_ctr]);"); + unit.emitln(" }"); + unit.emitln(" }"); + unit.emitln(" }"); } } } } - protected void emitCallResultReturn(final MethodBinding binding, final PrintWriter writer) { + protected void emitCallResultReturn(final MethodBinding binding) { final JavaType returnType = binding.getJavaReturnType(); if (returnType.isCompoundTypeWrapper()) { // Details are handled in JavaEmitter's struct handling! - writer.println(" if (_res == null) return null;"); - writer.println(" return " + returnType.getName() + ".create(Buffers.nativeOrder(_res));"); + unit.emitln(" if (_res == null) return null;"); + unit.emitln(" return " + returnType.getName() + ".create(Buffers.nativeOrder(_res));"); } else if (returnType.isNIOBuffer()) { - writer.println(" if (_res == null) return null;"); - writer.println(" Buffers.nativeOrder(_res);"); + unit.emitln(" if (_res == null) return null;"); + unit.emitln(" Buffers.nativeOrder(_res);"); if (!returnType.isNIOByteBuffer()) { // See whether we have to expand pointers to longs if (getBinding().getCReturnType().pointerDepth() >= 2) { if (returnType.isNIOPointerBuffer()) { - writer.println(" return PointerBuffer.wrap(_res);"); + unit.emitln(" return PointerBuffer.wrap(_res);"); } else if (returnType.isNIOLongBuffer()) { - writer.println(" return _res.asLongBuffer();"); + unit.emitln(" return _res.asLongBuffer();"); } else { throw new GlueGenException("While emitting glue code for " + getCSymbol().getAliasedString() + ": can not legally make pointers opaque to anything but PointerBuffer or LongBuffer/long", getCSymbol().getASTLocusTag()); } } else if (getBinding().getCReturnType().pointerDepth() == 1 && returnType.isNIOLongBuffer()) { - writer.println(" return _res.asLongBuffer();"); + unit.emitln(" return _res.asLongBuffer();"); } else { final String returnTypeName = returnType.getName().substring("java.nio.".length()); - writer.println(" return _res.as" + returnTypeName + "();"); + unit.emitln(" return _res.as" + returnTypeName + "();"); } } else { - writer.println(" return _res;"); + unit.emitln(" return _res;"); } } else if (returnType.isArrayOfCompoundTypeWrappers()) { - writer.println(" if (_res == null) return null;"); - writer.println(" final " + getReturnTypeString(false) + " _retarray = new " + getReturnTypeString(true) + "[_res.length];"); - writer.println(" for (int _count = 0; _count < _res.length; _count++) {"); - writer.println(" _retarray[_count] = " + getReturnTypeString(true) + ".create(_res[_count]);"); - writer.println(" }"); - writer.println(" return _retarray;"); + unit.emitln(" if (_res == null) return null;"); + unit.emitln(" final " + getReturnTypeString(false) + " _retarray = new " + getReturnTypeString(true) + "[_res.length];"); + unit.emitln(" for (int _count = 0; _count < _res.length; _count++) {"); + unit.emitln(" _retarray[_count] = " + getReturnTypeString(true) + ".create(_res[_count]);"); + unit.emitln(" }"); + unit.emitln(" return _retarray;"); } else { // Assume it's a primitive type or other type we don't have to // do any conversion on - writer.println(" return _res;"); + unit.emitln(" return _res;"); } } diff --git a/src/java/com/jogamp/gluegen/MethodBinding.java b/src/java/com/jogamp/gluegen/MethodBinding.java index 95a10c6..efa938f 100644 --- a/src/java/com/jogamp/gluegen/MethodBinding.java +++ b/src/java/com/jogamp/gluegen/MethodBinding.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2010-2023 JogAmp Community. All rights reserved. * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without @@ -155,6 +156,17 @@ public class MethodBinding { return sym.getArgumentType(i); } + public final boolean isReturnCompoundByValue() { + final Type cReturnType = getCReturnType(); + if (cReturnType.isVoid()) { + return false; + } + if (javaReturnType.isPrimitive()) { + return false; + } + return !cReturnType.isPointer() && javaReturnType.isCompoundTypeWrapper(); + } + /** Returns the {@link FunctionSymbol}. */ public FunctionSymbol getCSymbol() { return sym; diff --git a/src/java/com/jogamp/gluegen/cgram/types/CompoundType.java b/src/java/com/jogamp/gluegen/cgram/types/CompoundType.java index 56bcdda..fea2446 100644 --- a/src/java/com/jogamp/gluegen/cgram/types/CompoundType.java +++ b/src/java/com/jogamp/gluegen/cgram/types/CompoundType.java @@ -179,6 +179,16 @@ public abstract class CompoundType extends MemoryLayoutType implements Cloneable return fields.get(i); } + /** Returns the <i>name</i> matching field of this type. */ + public Field getField(final String name) { + for(final Field f : fields ) { + if( f.getName().equals(name) ) { + return f; + } + } + return null; + } + /** Adds a field to this type. */ public void addField(final Field f) { if (bodyParsed) { diff --git a/src/java/com/jogamp/gluegen/procaddress/ProcAddressCMethodBindingEmitter.java b/src/java/com/jogamp/gluegen/procaddress/ProcAddressCMethodBindingEmitter.java index 37a39e1..c3c374f 100644 --- a/src/java/com/jogamp/gluegen/procaddress/ProcAddressCMethodBindingEmitter.java +++ b/src/java/com/jogamp/gluegen/procaddress/ProcAddressCMethodBindingEmitter.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2010-2023 JogAmp Community. All rights reserved. * Copyright (c) 2003-2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without @@ -40,12 +41,11 @@ package com.jogamp.gluegen.procaddress; import com.jogamp.gluegen.CMethodBindingEmitter; -import com.jogamp.gluegen.MethodBinding; import com.jogamp.gluegen.JavaType; - -import java.io.*; - -import com.jogamp.gluegen.cgram.types.*; +import com.jogamp.gluegen.MethodBinding; +import com.jogamp.gluegen.cgram.types.FunctionSymbol; +import com.jogamp.gluegen.cgram.types.PointerType; +import com.jogamp.gluegen.cgram.types.Type; public class ProcAddressCMethodBindingEmitter extends CMethodBindingEmitter { @@ -74,7 +74,7 @@ public class ProcAddressCMethodBindingEmitter extends CMethodBindingEmitter { } } }, - methodToWrap.getDefaultOutput(), + methodToWrap.getUnit(), methodToWrap.getJavaPackageName(), methodToWrap.getJavaClassName(), methodToWrap.getIsOverloadedBinding(), @@ -102,14 +102,14 @@ public class ProcAddressCMethodBindingEmitter extends CMethodBindingEmitter { } @Override - protected int emitArguments(final PrintWriter writer) { - int numEmitted = super.emitArguments(writer); + protected int emitArguments() { + int numEmitted = super.emitArguments(); if (callThroughProcAddress) { if (numEmitted > 0) { - writer.print(", "); + unit.emit(", "); } - writer.print(procAddressJavaTypeName); - writer.print(" procAddress"); + unit.emit(procAddressJavaTypeName); + unit.emit(" procAddress"); ++numEmitted; } @@ -117,7 +117,7 @@ public class ProcAddressCMethodBindingEmitter extends CMethodBindingEmitter { } @Override - protected void emitBodyVariableDeclarations(final PrintWriter writer) { + protected void emitBodyVariableDeclarations() { if (callThroughProcAddress) { // create variable for the function pointer with the right type, and set // it to the value of the passed-in proc address @@ -138,23 +138,23 @@ public class ProcAddressCMethodBindingEmitter extends CMethodBindingEmitter { } final PointerType funcPtrType = new PointerType(null, cSym.getType(), 0); - writer.print(" typedef "); - writer.print(funcPtrType.toString(funcPointerTypedefLocalName, localTypedefCallingConvention)); - writer.println(";"); + unit.emit(" typedef "); + unit.emit(funcPtrType.toString(funcPointerTypedefLocalName, localTypedefCallingConvention)); + unit.emitln(";"); - writer.print(" "); - writer.print(funcPointerTypedefName); // Uses public typedef if available! - writer.print(" ptr_"); - writer.print(getNativeName()); - writer.println(";"); + unit.emit(" "); + unit.emit(funcPointerTypedefName); // Uses public typedef if available! + unit.emit(" ptr_"); + unit.emit(getNativeName()); + unit.emitln(";"); } - super.emitBodyVariableDeclarations(writer); + super.emitBodyVariableDeclarations(); } @Override - protected void emitBodyVariablePreCallSetup(final PrintWriter writer) { - super.emitBodyVariablePreCallSetup(writer); + protected void emitBodyVariablePreCallSetup() { + super.emitBodyVariablePreCallSetup(); if (callThroughProcAddress) { // set the function pointer to the value of the passed-in procAddress @@ -171,25 +171,25 @@ public class ProcAddressCMethodBindingEmitter extends CMethodBindingEmitter { final String ptrVarName = "ptr_" + getNativeName(); if (hasProcAddrTypedef) { - writer.println(" // implicit type validation of "+funcPointerTypedefLocalName+" -> "+funcPointerTypedefName); + unit.emitln(" // implicit type validation of "+funcPointerTypedefLocalName+" -> "+funcPointerTypedefName); } - writer.print(" "); - writer.print(ptrVarName); - writer.print(" = ("); - writer.print(funcPointerTypedefLocalName); - writer.println(") (intptr_t) procAddress;"); + unit.emit(" "); + unit.emit(ptrVarName); + unit.emit(" = ("); + unit.emit(funcPointerTypedefLocalName); + unit.emitln(") (intptr_t) procAddress;"); - writer.println(" assert(" + ptrVarName + " != NULL);"); + unit.emitln(" assert(" + ptrVarName + " != NULL);"); } } @Override - protected void emitBodyCallCFunction(final PrintWriter writer) { + protected void emitBodyCallCFunction() { if (!callThroughProcAddress) { - super.emitBodyCallCFunction(writer); + super.emitBodyCallCFunction(); } else { // Make the call to the actual C function - writer.print(" "); + unit.emit(" "); // WARNING: this code assumes that the return type has already been // typedef-resolved. @@ -199,9 +199,9 @@ public class ProcAddressCMethodBindingEmitter extends CMethodBindingEmitter { // Note we respect const/volatile in the function return type. // However, we cannot have it 'const' for our local variable. // See return type in CMethodBindingEmitter.emitBodyVariableDeclarations(..)! - writer.print("_res = ("); - writer.print(cReturnType.getCName(false)); - writer.print(") "); + unit.emit("_res = ("); + unit.emit(cReturnType.getCName(false)); + unit.emit(") "); } final MethodBinding mBinding = getBinding(); if (mBinding.hasContainingType()) { @@ -211,12 +211,12 @@ public class ProcAddressCMethodBindingEmitter extends CMethodBindingEmitter { } // call throught the run-time function pointer - writer.print("(* ptr_"); - writer.print(getNativeName()); - writer.print(") "); - writer.print("("); - emitBodyPassCArguments(writer); - writer.println(");"); + unit.emit("(* ptr_"); + unit.emit(getNativeName()); + unit.emit(") "); + unit.emit("("); + emitBodyPassCArguments(); + unit.emitln(");"); } } diff --git a/src/java/com/jogamp/gluegen/procaddress/ProcAddressEmitter.java b/src/java/com/jogamp/gluegen/procaddress/ProcAddressEmitter.java index ec29b08..b812416 100644 --- a/src/java/com/jogamp/gluegen/procaddress/ProcAddressEmitter.java +++ b/src/java/com/jogamp/gluegen/procaddress/ProcAddressEmitter.java @@ -1,6 +1,6 @@ /* + * Copyright (c) 2010-2023 JogAmp Community. All rights reserved. * Copyright (c) 2003-2005 Sun Microsystems, Inc. All Rights Reserved. - * Copyright (c) 2013 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -40,7 +40,6 @@ package com.jogamp.gluegen.procaddress; import java.io.File; -import java.io.PrintWriter; import java.text.MessageFormat; import java.util.ArrayList; import java.util.HashSet; @@ -52,6 +51,7 @@ import java.util.logging.Level; import com.jogamp.gluegen.CMethodBindingEmitter; import com.jogamp.gluegen.CodeGenUtils; import com.jogamp.gluegen.FunctionEmitter; +import com.jogamp.gluegen.JavaCodeUnit; import com.jogamp.gluegen.JavaConfiguration; import com.jogamp.gluegen.JavaEmitter; import com.jogamp.gluegen.JavaMethodBindingEmitter; @@ -72,7 +72,7 @@ public class ProcAddressEmitter extends JavaEmitter { public static final String PROCADDRESS_VAR_PREFIX = "_addressof_"; protected static final String WRAP_PREFIX = "dispatch_"; private TypeDictionary typedefDictionary; - protected PrintWriter tableWriter; + protected JavaCodeUnit tableJavaUnit; protected Set<String> emittedTableEntries; protected String tableClassPackage; protected String tableClassName; @@ -307,47 +307,47 @@ public class ProcAddressEmitter extends JavaEmitter { final String jImplRoot = getJavaOutputDir() + File.separator + CodeGenUtils.packageAsPath(implPackageName); - tableWriter = openFile(jImplRoot + File.separator + tableClassName + ".java", tableClassName); - emittedTableEntries = new HashSet<String>(); + final String javaFileName = jImplRoot + File.separator + tableClassName + ".java"; + tableJavaUnit = openJavaUnit(javaFileName, implPackageName, tableClassName); - CodeGenUtils.emitAutogeneratedWarning(tableWriter, this); + emittedTableEntries = new HashSet<String>(); - tableWriter.println("package " + implPackageName + ";"); - tableWriter.println(); + tableJavaUnit.emitln("package " + implPackageName + ";"); + tableJavaUnit.emitln(); for (final String imporT : getConfig().imports()) { - tableWriter.println("import " + imporT + ";"); + tableJavaUnit.emitln("import " + imporT + ";"); } - tableWriter.println("import " + ProcAddressTable.class.getName() + ";"); - tableWriter.println("import com.jogamp.common.util.SecurityUtil;"); - tableWriter.println(); - - tableWriter.println("/**"); - tableWriter.println(" * This table is a cache of pointers to the dynamically-linkable C library."); - tableWriter.println(" * @see " + ProcAddressTable.class.getSimpleName()); - tableWriter.println(" */"); + tableJavaUnit.emitln("import " + ProcAddressTable.class.getName() + ";"); + tableJavaUnit.emitln("import com.jogamp.common.util.SecurityUtil;"); + tableJavaUnit.emitln(); + + tableJavaUnit.emitln("/**"); + tableJavaUnit.emitln(" * This table is a cache of pointers to the dynamically-linkable C library."); + tableJavaUnit.emitln(" * @see " + ProcAddressTable.class.getSimpleName()); + tableJavaUnit.emitln(" */"); for (int i = 0; accessModifiers != null && i < accessModifiers.length; ++i) { - tableWriter.print(accessModifiers[i]); - tableWriter.print(' '); + tableJavaUnit.emit(accessModifiers[i]); + tableJavaUnit.emit(" "); } - tableWriter.println("final class " + tableClassName + " extends "+ ProcAddressTable.class.getSimpleName() + " {"); - tableWriter.println(); + tableJavaUnit.emitln("final class " + tableClassName + " extends "+ ProcAddressTable.class.getSimpleName() + " {"); + tableJavaUnit.emitln(); for (final String string : getProcAddressConfig().getForceProcAddressGen()) { emitProcAddressTableEntryForString(string); } - tableWriter.println(); - tableWriter.println(" public "+tableClassName+"(){ super(); }"); - tableWriter.println(); - tableWriter.println(" public "+tableClassName+"("+FunctionAddressResolver.class.getName()+" resolver){ super(resolver); }"); - tableWriter.println(); + tableJavaUnit.emitln(); + tableJavaUnit.emitln(" public "+tableClassName+"(){ super(); }"); + tableJavaUnit.emitln(); + tableJavaUnit.emitln(" public "+tableClassName+"("+FunctionAddressResolver.class.getName()+" resolver){ super(resolver); }"); + tableJavaUnit.emitln(); } protected void endProcAddressTable() throws Exception { - tableWriter.println("} // end of class " + tableClassName); - tableWriter.flush(); - tableWriter.close(); + tableJavaUnit.emitln("} // end of class " + tableClassName); + tableJavaUnit.close(); + tableJavaUnit = null; } protected void emitProcAddressTableEntryForString(final String str) { @@ -357,10 +357,10 @@ public class ProcAddressEmitter extends JavaEmitter { return; } emittedTableEntries.add(str); - tableWriter.print(" /* pp */ long "); - tableWriter.print(PROCADDRESS_VAR_PREFIX); - tableWriter.print(str); - tableWriter.println(";"); + tableJavaUnit.emit(" /* pp */ long "); + tableJavaUnit.emit(PROCADDRESS_VAR_PREFIX); + tableJavaUnit.emit(str); + tableJavaUnit.emitln(";"); } protected ProcAddressConfiguration getProcAddressConfig() { diff --git a/src/java/com/jogamp/gluegen/procaddress/ProcAddressJavaMethodBindingEmitter.java b/src/java/com/jogamp/gluegen/procaddress/ProcAddressJavaMethodBindingEmitter.java index 5298a8d..0d5de1c 100644 --- a/src/java/com/jogamp/gluegen/procaddress/ProcAddressJavaMethodBindingEmitter.java +++ b/src/java/com/jogamp/gluegen/procaddress/ProcAddressJavaMethodBindingEmitter.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2010-2023 JogAmp Community. All rights reserved. * Copyright (c) 2003-2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without @@ -90,15 +91,15 @@ public class ProcAddressJavaMethodBindingEmitter extends JavaMethodBindingEmitte } @Override - protected int emitArguments(final PrintWriter writer) { - int numEmitted = super.emitArguments(writer); + protected int emitArguments() { + int numEmitted = super.emitArguments(); if (callThroughProcAddress) { if (changeNameAndArguments) { if (numEmitted > 0) { - writer.print(", "); + unit.emit(", "); } - writer.print("long procAddress"); + unit.emit("long procAddress"); ++numEmitted; } } @@ -116,27 +117,27 @@ public class ProcAddressJavaMethodBindingEmitter extends JavaMethodBindingEmitte } @Override - protected void emitPreCallSetup(final MethodBinding binding, final PrintWriter writer) { - super.emitPreCallSetup(binding, writer); + protected void emitPreCallSetup(final MethodBinding binding) { + super.emitPreCallSetup(binding); if (callThroughProcAddress) { final String procAddressVariable = ProcAddressEmitter.PROCADDRESS_VAR_PREFIX + binding.getNativeName(); - writer.println(" final long __addr_ = " + getProcAddressTableExpr + "." + procAddressVariable + ";"); - writer.println(" if (__addr_ == 0) {"); - writer.format(" throw new %s(String.format(\"Method \\\"%%s\\\" not available\", \"%s\"));%n", + unit.emitln(" final long __addr_ = " + getProcAddressTableExpr + "." + procAddressVariable + ";"); + unit.emitln(" if (__addr_ == 0) {"); + unit.emitf(" throw new %s(String.format(\"Method \\\"%%s\\\" not available\", \"%s\"));%n", emitter.unsupportedExceptionType(), binding.getName()); - writer.println(" }"); + unit.emitln(" }"); } } @Override - protected int emitCallArguments(final MethodBinding binding, final PrintWriter writer) { - int numEmitted = super.emitCallArguments(binding, writer); + protected int emitCallArguments(final MethodBinding binding) { + int numEmitted = super.emitCallArguments(binding); if (callThroughProcAddress) { if (numEmitted > 0) { - writer.print(", "); + unit.emit(", "); } - writer.print("__addr_"); + unit.emit("__addr_"); ++numEmitted; } diff --git a/src/java/com/jogamp/gluegen/structgen/CStructAnnotationProcessor.java b/src/java/com/jogamp/gluegen/structgen/CStructAnnotationProcessor.java index 45293f8..13bf418 100644 --- a/src/java/com/jogamp/gluegen/structgen/CStructAnnotationProcessor.java +++ b/src/java/com/jogamp/gluegen/structgen/CStructAnnotationProcessor.java @@ -28,7 +28,9 @@ package com.jogamp.gluegen.structgen; import com.jogamp.common.util.PropertyAccess; +import com.jogamp.gluegen.CCodeUnit; import com.jogamp.gluegen.GlueGen; +import com.jogamp.gluegen.JavaCodeUnit; import com.jogamp.gluegen.JavaEmitter; import java.io.BufferedReader; @@ -282,12 +284,10 @@ public class CStructAnnotationProcessor extends AbstractProcessor { public static class AnnotationProcessorJavaStructEmitter extends JavaEmitter { - @Override - protected PrintWriter openFile(final String filename, final String simpleClassName) throws IOException { - + private boolean filter(final String simpleClassName) { if( generatedStructs.contains(simpleClassName) ) { System.err.println("skipping -> " + simpleClassName); - return null; + return false; } // look for recursive generated structs... keep it DRY @@ -296,9 +296,31 @@ public class CStructAnnotationProcessor extends AbstractProcessor { System.err.println("generating -> " + simpleClassName); generatedStructs.add(simpleClassName); } - return super.openFile(filename, simpleClassName); + return true; + } + + @Override + protected CCodeUnit openCUnit(final String filename, final String cUnitName) throws IOException { + if( !filter(cUnitName) ) { + return null; + } + return super.openCUnit(filename, cUnitName); } + /** + * @param filename the class's full filename to open w/ write access + * @param packageName the package name of the class + * @param simpleClassName the simple class name, i.e. w/o package name or c-file basename + * @param generator informal optional object that is creating this unit, used to be mentioned in a warning message if not null. + * @throws IOException + */ + @Override + protected JavaCodeUnit openJavaUnit(final String filename, final String packageName, final String simpleClassName) throws IOException { + if( !filter(simpleClassName) ) { + return null; + } + return super.openJavaUnit(filename, packageName, simpleClassName); + } } } |