aboutsummaryrefslogtreecommitdiffstats
path: root/src/java/com/jogamp/gluegen
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2015-03-11 15:10:15 +0100
committerSven Gothel <[email protected]>2015-03-11 15:10:15 +0100
commitbbea09816015ecf3596acdcc033553127fcc0ef3 (patch)
treeab38152b5b74ee7d99e955658c7778de4181438b /src/java/com/jogamp/gluegen
parent25f248669f603c2bbd6ad97f31e0c72ce780f507 (diff)
Bug 1144 - Add 'DelegateImplementation': Requires own MethodBinding for delegates impl. / Adding ReturnsOpaque
- DelegateImplementation requires own MethodBinding for delegates impl. The delegation name must be included within the FunctionSymbol's aliases _only_ for implementations, where delegation applies. This allows all subsequent type/cfg checks to hit on AliasedSymbol! Hence we need to create individual MethodBinding instances for interfaces and public/private implementations. - Adding ReturnsOpaque Configuration: ReturnsOpaque <Primitive Java Type> <Function Name> This feature is necessary to achieve 'Opaque' functionality for function's return type - instead of types in general. - Fix AliasedSymbolImpl copy-ctor, i.e. this.name = o.name !
Diffstat (limited to 'src/java/com/jogamp/gluegen')
-rw-r--r--src/java/com/jogamp/gluegen/CMethodBindingEmitter.java2
-rw-r--r--src/java/com/jogamp/gluegen/JavaConfiguration.java52
-rw-r--r--src/java/com/jogamp/gluegen/JavaEmitter.java96
-rw-r--r--src/java/com/jogamp/gluegen/MethodBinding.java2
-rw-r--r--src/java/com/jogamp/gluegen/cgram/types/AliasedSymbol.java2
-rw-r--r--src/java/com/jogamp/gluegen/cgram/types/FunctionSymbol.java11
-rw-r--r--src/java/com/jogamp/gluegen/procaddress/ProcAddressEmitter.java19
-rw-r--r--src/java/com/jogamp/gluegen/procaddress/ProcAddressJavaMethodBindingEmitter.java2
8 files changed, 128 insertions, 58 deletions
diff --git a/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java b/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java
index bb95226..7c88c37 100644
--- a/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java
+++ b/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java
@@ -1083,7 +1083,7 @@ public class CMethodBindingEmitter extends FunctionEmitter {
}
}
if( 0 == mode ) {
- if( null != cfg.typeInfo(cReturnType) ) {
+ if( null != cfg.typeInfo(cReturnType) ) { // javaReturnType.isOpaqued() covered above via isPrimitive()
// Opaque
writer.println("sizeof(" + cReturnType.getCName() + ") );");
mode = 88;
diff --git a/src/java/com/jogamp/gluegen/JavaConfiguration.java b/src/java/com/jogamp/gluegen/JavaConfiguration.java
index 21ba8d9..019ca2d 100644
--- a/src/java/com/jogamp/gluegen/JavaConfiguration.java
+++ b/src/java/com/jogamp/gluegen/JavaConfiguration.java
@@ -138,6 +138,7 @@ public class JavaConfiguration {
private final Map<String, MethodAccess> accessControl = new HashMap<String, MethodAccess>();
private final Map<String, TypeInfo> typeInfoMap = new HashMap<String, TypeInfo>();
private final Set<String> returnsString = new HashSet<String>();
+ private final Map<String, JavaType> returnsOpaqueJType = new HashMap<String, JavaType>();
private final Map<String, String> returnedArrayLengths = new HashMap<String, String>();
/**
@@ -519,7 +520,6 @@ public class JavaConfiguration {
oneInSet(returnsString, symbol.getAliasedNames());
}
-
/**
* Returns a MessageFormat string of the Java expression calculating
* the number of elements in the returned array from the specified function
@@ -886,7 +886,7 @@ public class JavaConfiguration {
if( null == res ) {
return null;
}
- LOG.log(INFO, "DelegatedImplementation: {0}", functionName);
+ LOG.log(INFO, "DelegatedImplementation: {0} -> {1}", functionName, res);
return res;
}
@@ -925,6 +925,41 @@ public class JavaConfiguration {
}
/**
+ * Variant of {@link #getOpaqueReturnType(AliasedSymbol)},
+ * where this method only considers the {@link AliasedSymbol#getName() current-name}
+ * of the given symbol, not the {@link #getJavaSymbolRename(String) renamed-symbol}.
+ */
+ public JavaType getOpaqueReturnType(final String functionName) {
+ final JavaType res = returnsOpaqueJType.get(functionName);
+ if( null == res ) {
+ return null;
+ }
+ LOG.log(INFO, "ReturnsOpaque: {0} -> {1}", functionName, res);
+ return res;
+ }
+
+ /**
+ * Returns the opaque {@link JavaType} for the given function {@link AliasedSymbol}
+ * or {@code null} if not opaque.
+ * <p>
+ * {@code ReturnsOpaque <Primitive Java Type> <Function Name>}
+ * </p>
+ */
+ public JavaType getOpaqueReturnType(final AliasedSymbol symbol) {
+ final String name = symbol.getName();
+ final Set<String> aliases = symbol.getAliasedNames();
+ JavaType res = returnsOpaqueJType.get(name);
+ if( null == res ) {
+ res = oneInMap(returnsOpaqueJType, aliases);
+ if( null == res ) {
+ return null;
+ }
+ }
+ LOG.log(INFO, getASTLocusTag(symbol), "ReturnsOpaque: {0} -> {1}", symbol, res);
+ return res;
+ }
+
+ /**
* Variant of {@link #shouldIgnoreInInterface(AliasedSymbol)},
* where this method only considers the {@link AliasedSymbol#getName() current-name}
* of the given symbol, not the {@link #getJavaSymbolRename(String) renamed-symbol}.
@@ -1222,6 +1257,8 @@ public class JavaConfiguration {
readOpaque(tok, filename, lineNo);
} else if (cmd.equalsIgnoreCase("ReturnsString")) {
readReturnsString(tok, filename, lineNo);
+ } else if (cmd.equalsIgnoreCase("ReturnsOpaque")) {
+ readReturnsOpaque(tok, filename, lineNo);
} else if (cmd.equalsIgnoreCase("ReturnedArrayLength")) {
readReturnedArrayLength(tok, filename, lineNo);
// Warning: make sure delimiters are reset at the top of this loop
@@ -1418,6 +1455,17 @@ public class JavaConfiguration {
}
}
+ protected void readReturnsOpaque(final StringTokenizer tok, final String filename, final int lineNo) {
+ try {
+ final JavaType javaType = JavaType.createForOpaqueClass(stringToPrimitiveType(tok.nextToken()));
+ final String funcName = tok.nextToken();
+ returnsOpaqueJType.put(funcName, javaType);
+ } catch (final Exception e) {
+ throw new RuntimeException("Error parsing \"ReturnsOpaque\" command at line " + lineNo +
+ " in file \"" + filename + "\"", e);
+ }
+ }
+
protected void readReturnsString(final StringTokenizer tok, final String filename, final int lineNo) {
try {
final String name = tok.nextToken();
diff --git a/src/java/com/jogamp/gluegen/JavaEmitter.java b/src/java/com/jogamp/gluegen/JavaEmitter.java
index 5264531..0e2efbb 100644
--- a/src/java/com/jogamp/gluegen/JavaEmitter.java
+++ b/src/java/com/jogamp/gluegen/JavaEmitter.java
@@ -484,14 +484,13 @@ public class JavaEmitter implements GlueEmitter {
@Override
public Iterator<FunctionSymbol> emitFunctions(final List<FunctionSymbol> funcsToBind) throws Exception {
// Bind all the C funcs to Java methods
- final HashSet<MethodBinding> methodBindingSet = new HashSet<MethodBinding>();
final ArrayList<FunctionEmitter> methodBindingEmitters = new ArrayList<FunctionEmitter>(2*funcsToBind.size());
{
int i=0;
for (final FunctionSymbol cFunc : funcsToBind) {
// Check to see whether this function should be ignored
if ( !cfg.shouldIgnoreInImpl(cFunc) ) {
- methodBindingEmitters.addAll(generateMethodBindingEmitters(methodBindingSet, cFunc));
+ methodBindingEmitters.addAll(generateMethodBindingEmitters(cFunc));
LOG.log(INFO, cFunc.getASTLocusTag(), "Non-Ignored Impl[{0}]: {1}", i++, cFunc);
}
@@ -560,7 +559,8 @@ public class JavaEmitter implements GlueEmitter {
* native code because it doesn't need any processing of the
* outgoing arguments).
*/
- protected void generatePublicEmitters(final MethodBinding binding, final List<FunctionEmitter> allEmitters, final boolean signatureOnly) {
+ protected void generatePublicEmitters(final MethodBinding binding, final List<FunctionEmitter> allEmitters,
+ final boolean signatureOnly) {
final FunctionSymbol cSymbol = binding.getCSymbol();
if ( !signatureOnly && cfg.manuallyImplement(cSymbol) ) {
// We only generate signatures for manually-implemented methods;
@@ -568,6 +568,20 @@ public class JavaEmitter implements GlueEmitter {
return;
}
+ final MethodAccess accessControl;
+
+ if ( !signatureOnly && null != binding.getDelegationImplName() ) {
+ // private access for delegation implementation methods
+ accessControl = PRIVATE;
+ } else {
+ accessControl = cfg.accessControl(binding.getName());
+ }
+
+ // We should not emit anything except public APIs into interfaces
+ if ( signatureOnly && PUBLIC != accessControl ) {
+ return;
+ }
+
// It's possible we may not need a body even if signatureOnly is
// set to false; for example, if the routine doesn't take any
// arrays or buffers as arguments
@@ -590,20 +604,6 @@ public class JavaEmitter implements GlueEmitter {
final boolean emitBody = !signatureOnly && needsBody;
final boolean isNativeMethod = !isUnimplemented && !needsBody && !signatureOnly;
- final MethodAccess accessControl;
-
- if ( !signatureOnly && null != binding.getDelegationImplName() ) {
- // private access for delegation implementation methods
- accessControl = PRIVATE;
- } else {
- accessControl = cfg.accessControl(binding.getName());
- }
-
- // We should not emit anything except public APIs into interfaces
- if ( signatureOnly && PUBLIC != accessControl ) {
- return;
- }
-
final PrintWriter writer = ((signatureOnly || cfg.allStatic()) ? javaWriter() : javaImplWriter());
final JavaMethodBindingEmitter emitter =
@@ -769,18 +769,34 @@ public class JavaEmitter implements GlueEmitter {
* Generate all appropriate Java bindings for the specified C function
* symbols.
*/
- protected List<? extends FunctionEmitter> generateMethodBindingEmitters(final Set<MethodBinding> methodBindingSet, final FunctionSymbol sym) throws Exception {
-
+ protected List<? extends FunctionEmitter> generateMethodBindingEmitters(final FunctionSymbol sym) throws Exception {
final ArrayList<FunctionEmitter> allEmitters = new ArrayList<FunctionEmitter>();
-
try {
+ if( cfg.emitInterface() ) {
+ generateMethodBindingEmittersImpl(allEmitters, sym, true);
+ }
+ if( cfg.emitImpl() ) {
+ generateMethodBindingEmittersImpl(allEmitters, sym, false);
+ }
+ } catch (final Exception e) {
+ throw new GlueGenException("Error while generating bindings for \"" + sym + "\"", sym.getASTLocusTag(), e);
+ }
+
+ return allEmitters;
+ }
+ private void generateMethodBindingEmittersImpl(final ArrayList<FunctionEmitter> allEmitters,
+ final FunctionSymbol sym,
+ final boolean forInterface) throws Exception
+ {
// Get Java binding for the function
- final MethodBinding mb = bindFunction(sym, machDescJava, null, null);
+ final MethodBinding mb = bindFunction(sym, forInterface, machDescJava, null, null);
// JavaTypes representing C pointers in the initial
// MethodBinding have not been lowered yet to concrete types
final List<MethodBinding> bindings = expandMethodBinding(mb);
+ final HashSet<MethodBinding> methodBindingSet = new HashSet<MethodBinding>();
+
for (final MethodBinding binding : bindings) {
if(!methodBindingSet.add(binding)) {
@@ -841,21 +857,15 @@ public class JavaEmitter implements GlueEmitter {
// Note in particular that the public entry point taking an
// array is merely a special case of the indirect buffer case.
- if (cfg.emitInterface()) {
+ if ( forInterface ) {
generatePublicEmitters(binding, allEmitters, true);
- }
- if (cfg.emitImpl()) {
+ } else {
generatePublicEmitters(binding, allEmitters, false);
generatePrivateEmitters(binding, allEmitters);
}
} // end iteration over expanded bindings
- } catch (final Exception e) {
- throw new GlueGenException("Error while generating bindings for \"" + sym + "\"", sym.getASTLocusTag(), e);
}
- return allEmitters;
- }
-
@Override
public void endFunctions() throws Exception {
@@ -1416,7 +1426,7 @@ public class JavaEmitter implements GlueEmitter {
final Type containingCType, final JavaType containingJType,
final int i, final FunctionSymbol funcSym, final String returnSizeLookupName) {
// Emit method call and associated native code
- final MethodBinding mb = bindFunction(funcSym, machDescJava, containingJType, containingCType);
+ final MethodBinding mb = bindFunction(funcSym, true /* forInterface */, machDescJava, containingJType, containingCType);
mb.findThisPointer(); // FIXME: need to provide option to disable this on per-function basis
// JavaTypes representing C pointers in the initial
@@ -1498,7 +1508,7 @@ public class JavaEmitter implements GlueEmitter {
final int i, final FunctionSymbol funcSym,
final String returnSizeLookupName, final String docArrayLenExpr, final String nativeArrayLenExpr) {
// Emit method call and associated native code
- final MethodBinding mb = bindFunction(funcSym, machDescJava, containingJType, containingCType);
+ final MethodBinding mb = bindFunction(funcSym, true /* forInterface */, machDescJava, containingJType, containingCType);
mb.findThisPointer(); // FIXME: need to provide option to disable this on per-function basis
// JavaTypes representing C pointers in the initial
@@ -2744,12 +2754,19 @@ public class JavaEmitter implements GlueEmitter {
potentially representing C pointers rather than true Java types)
and must be lowered to concrete Java types before creating
emitters for them. */
- private MethodBinding bindFunction(final FunctionSymbol sym,
+ private MethodBinding bindFunction(FunctionSymbol sym,
+ final boolean forInterface,
final MachineDataInfo curMachDesc,
- final JavaType containingType,
- final Type containingCType) {
+ final JavaType containingType, final Type containingCType) {
- // System.out.println("bindFunction(0) "+sym.getReturnType());
+ final String delegationImplName = null == containingType && null == containingCType ?
+ cfg.getDelegatedImplementation(sym) : null;
+ if( !forInterface && null != delegationImplName ) {
+ // We need to reflect the 'delegationImplName' for implementations
+ // to allow all subsequent type/cfg checks to hit on AliasedSymbol!
+ sym = FunctionSymbol.cloneWithDeepAliases(sym);
+ sym.addAliasedName(delegationImplName);
+ }
final String name = sym.getName();
final JavaType javaReturnType;
@@ -2765,7 +2782,12 @@ public class JavaEmitter implements GlueEmitter {
}
javaReturnType = javaType(java.lang.String.class);
} else {
- javaReturnType = typeToJavaType(sym.getReturnType(), curMachDesc);
+ final JavaType r = cfg.getOpaqueReturnType(sym);
+ if( null != r ) {
+ javaReturnType = r;
+ } else {
+ javaReturnType = typeToJavaType(sym.getReturnType(), curMachDesc);
+ }
}
// List of the indices of the arguments in this function that should be
@@ -2809,8 +2831,6 @@ public class JavaEmitter implements GlueEmitter {
javaArgumentTypes.add(mappedType);
//System.out.println("During binding of [" + sym + "], added mapping from C type: " + cArgType + " to Java type: " + mappedType);
}
- final String delegationImplName = null == containingType && null == containingCType ?
- cfg.getDelegatedImplementation(sym) : null;
final MethodBinding mb = new MethodBinding(sym, delegationImplName,
javaReturnType, javaArgumentTypes,
containingType, containingCType);
diff --git a/src/java/com/jogamp/gluegen/MethodBinding.java b/src/java/com/jogamp/gluegen/MethodBinding.java
index 278fea0..95a10c6 100644
--- a/src/java/com/jogamp/gluegen/MethodBinding.java
+++ b/src/java/com/jogamp/gluegen/MethodBinding.java
@@ -203,7 +203,7 @@ public class MethodBinding {
/**
* Returns the {@link FunctionSymbol}'s name for the native function
* which is the {@link FunctionSymbol#getOrigName() original} C API name per default,
- * but may be overriden via {@link #setNativeName(String)}.
+ * but may be overridden via {@link #setNativeName(String)}.
*/
public String getNativeName() {
return null != nativeName ? nativeName : sym.getOrigName();
diff --git a/src/java/com/jogamp/gluegen/cgram/types/AliasedSymbol.java b/src/java/com/jogamp/gluegen/cgram/types/AliasedSymbol.java
index 73c65ef..869c658 100644
--- a/src/java/com/jogamp/gluegen/cgram/types/AliasedSymbol.java
+++ b/src/java/com/jogamp/gluegen/cgram/types/AliasedSymbol.java
@@ -110,7 +110,7 @@ public interface AliasedSymbol {
public AliasedSymbolImpl(final AliasedSymbolImpl o) {
this.origName = o.origName;
this.aliasedNames = new HashSet<String>(o.aliasedNames);
- this.name = o.origName;
+ this.name = o.name;
}
@Override
public void rename(final String newName) {
diff --git a/src/java/com/jogamp/gluegen/cgram/types/FunctionSymbol.java b/src/java/com/jogamp/gluegen/cgram/types/FunctionSymbol.java
index 55585fc..91a0a5a 100644
--- a/src/java/com/jogamp/gluegen/cgram/types/FunctionSymbol.java
+++ b/src/java/com/jogamp/gluegen/cgram/types/FunctionSymbol.java
@@ -76,6 +76,17 @@ public class FunctionSymbol extends AliasedSymbolImpl implements AliasedSemantic
this.astLocus = locus;
}
+ /** Shallow'ish copy, only aliased names are re-created. */
+ public static FunctionSymbol cloneWithDeepAliases(final FunctionSymbol o) {
+ return new FunctionSymbol(o);
+ }
+ /** Warning: Shallow'ish copy, only aliased names are re-created. */
+ private FunctionSymbol(final FunctionSymbol o) {
+ super(o);
+ this.type = o.type;
+ this.astLocus = o.astLocus;
+ }
+
@Override
public ASTLocusTag getASTLocusTag() { return astLocus; }
diff --git a/src/java/com/jogamp/gluegen/procaddress/ProcAddressEmitter.java b/src/java/com/jogamp/gluegen/procaddress/ProcAddressEmitter.java
index 423efe9..ec29b08 100644
--- a/src/java/com/jogamp/gluegen/procaddress/ProcAddressEmitter.java
+++ b/src/java/com/jogamp/gluegen/procaddress/ProcAddressEmitter.java
@@ -55,7 +55,6 @@ import com.jogamp.gluegen.FunctionEmitter;
import com.jogamp.gluegen.JavaConfiguration;
import com.jogamp.gluegen.JavaEmitter;
import com.jogamp.gluegen.JavaMethodBindingEmitter;
-import com.jogamp.gluegen.MethodBinding;
import com.jogamp.gluegen.cgram.types.FunctionSymbol;
import com.jogamp.gluegen.cgram.types.Type;
import com.jogamp.gluegen.cgram.types.TypeDictionary;
@@ -115,8 +114,8 @@ public class ProcAddressEmitter extends JavaEmitter {
}
@Override
- protected List<? extends FunctionEmitter> generateMethodBindingEmitters(final Set<MethodBinding> methodBindingSet, final FunctionSymbol sym) throws Exception {
- return generateMethodBindingEmittersImpl(methodBindingSet, sym);
+ protected List<? extends FunctionEmitter> generateMethodBindingEmitters(final FunctionSymbol sym) throws Exception {
+ return generateMethodBindingEmittersImpl(sym);
}
protected boolean needsModifiedEmitters(final FunctionSymbol sym) {
@@ -127,8 +126,8 @@ public class ProcAddressEmitter extends JavaEmitter {
}
}
- private List<? extends FunctionEmitter> generateMethodBindingEmittersImpl(final Set<MethodBinding> methodBindingSet, final FunctionSymbol sym) throws Exception {
- final List<? extends FunctionEmitter> defaultEmitters = super.generateMethodBindingEmitters(methodBindingSet, sym);
+ private List<? extends FunctionEmitter> generateMethodBindingEmittersImpl(final FunctionSymbol sym) throws Exception {
+ final List<? extends FunctionEmitter> defaultEmitters = super.generateMethodBindingEmitters(sym);
// if the superclass didn't generate any bindings for the symbol, let's
// honor that (for example, the superclass might have caught an Ignore
@@ -153,7 +152,7 @@ public class ProcAddressEmitter extends JavaEmitter {
if ( callThroughProcAddress ) {
if (getProcAddressConfig().emitProcAddressTable()) {
// emit an entry in the GL proc address table for this method.
- emitProcAddressTableEntryForString(getAliasedSymName(sym));
+ emitProcAddressTableEntryForString(sym.getName());
}
}
for (final FunctionEmitter emitter : defaultEmitters) {
@@ -267,14 +266,6 @@ public class ProcAddressEmitter extends JavaEmitter {
emitters.add(res);
}
- private String getAliasedSymName(final FunctionSymbol sym) {
- String symName = getConfig().getJavaSymbolRename(sym.getName());
- if (null == symName) {
- symName = sym.getName();
- }
- return symName;
- }
-
protected boolean callThroughProcAddress(final FunctionSymbol sym) {
final ProcAddressConfiguration cfg = getProcAddressConfig();
boolean res = false;
diff --git a/src/java/com/jogamp/gluegen/procaddress/ProcAddressJavaMethodBindingEmitter.java b/src/java/com/jogamp/gluegen/procaddress/ProcAddressJavaMethodBindingEmitter.java
index 3faf155..5298a8d 100644
--- a/src/java/com/jogamp/gluegen/procaddress/ProcAddressJavaMethodBindingEmitter.java
+++ b/src/java/com/jogamp/gluegen/procaddress/ProcAddressJavaMethodBindingEmitter.java
@@ -120,7 +120,7 @@ public class ProcAddressJavaMethodBindingEmitter extends JavaMethodBindingEmitte
super.emitPreCallSetup(binding, writer);
if (callThroughProcAddress) {
- final String procAddressVariable = ProcAddressEmitter.PROCADDRESS_VAR_PREFIX + binding.getName();
+ 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",