summaryrefslogtreecommitdiffstats
path: root/src/java/com/sun/gluegen
diff options
context:
space:
mode:
authorKenneth Russel <[email protected]>2008-05-27 10:06:20 +0000
committerKenneth Russel <[email protected]>2008-05-27 10:06:20 +0000
commitf1e08a23facb2d718276b3fbf59b0df2b54fceb9 (patch)
treeb7f5b37c2187d39e90681400206685293d758aaa /src/java/com/sun/gluegen
parent0ce0a36ec694da77a0ef02ed46c2b152a17d5c80 (diff)
Changed implementation of ArgumentIsString to work with wide-character
null-terminated strings on Windows. Changed Windows dynamic linker to use LoadLibraryW which is the only variant available on Windows CE. Changed GetProcAddress to explicitly named GetProcAddressA; this is implicitly the only variant available on Windows XP. Tested by compiling gluegen-rt.dll for both Windows XP and Windows CE. Also brought dynlink-unix-CustomJavaCode.java in line with modifications that were apparently hand made to the UnixDynamicLinkerImpl and MacOSXDynamicLinkerImpl classes. git-svn-id: file:///usr/local/projects/SUN/JOGL/git-svn/../svn-server-sync/gluegen/trunk@79 a78bb65f-1512-4460-ba86-f6dc96a7bf27
Diffstat (limited to 'src/java/com/sun/gluegen')
-rw-r--r--src/java/com/sun/gluegen/CMethodBindingEmitter.java176
-rw-r--r--src/java/com/sun/gluegen/JavaConfiguration.java11
-rw-r--r--src/java/com/sun/gluegen/JavaEmitter.java24
-rwxr-xr-xsrc/java/com/sun/gluegen/procaddress/ProcAddressCMethodBindingEmitter.java3
-rwxr-xr-xsrc/java/com/sun/gluegen/runtime/WindowsDynamicLinkerImpl.java14
5 files changed, 157 insertions, 71 deletions
diff --git a/src/java/com/sun/gluegen/CMethodBindingEmitter.java b/src/java/com/sun/gluegen/CMethodBindingEmitter.java
index 93a625f..446e5ca 100644
--- a/src/java/com/sun/gluegen/CMethodBindingEmitter.java
+++ b/src/java/com/sun/gluegen/CMethodBindingEmitter.java
@@ -113,6 +113,11 @@ public class CMethodBindingEmitter extends FunctionEmitter
// warnings are incorrect.
private static final boolean EMIT_NULL_CHECKS = true;
+ protected static final String STRING_CHARS_PREFIX = "_strchars_";
+
+ // We need this in order to compute sizes of certain types
+ protected MachineDescription machDesc;
+
/**
* Constructs an emitter for the specified binding, and sets a default
* comment emitter that will emit the signature of the C function that is
@@ -125,7 +130,8 @@ public class CMethodBindingEmitter extends FunctionEmitter
boolean isOverloadedBinding,
boolean isJavaMethodStatic,
boolean forImplementingMethodCall,
- boolean forIndirectBufferAndArrayImplementation)
+ boolean forIndirectBufferAndArrayImplementation,
+ MachineDescription machDesc)
{
super(output);
@@ -141,6 +147,7 @@ public class CMethodBindingEmitter extends FunctionEmitter
this.forImplementingMethodCall = forImplementingMethodCall;
this.forIndirectBufferAndArrayImplementation = forIndirectBufferAndArrayImplementation;
+ this.machDesc = machDesc;
setCommentEmitter(defaultCommentEmitter);
}
@@ -291,6 +298,12 @@ public class CMethodBindingEmitter extends FunctionEmitter
*/
public final boolean forIndirectBufferAndArrayImplementation() { return forIndirectBufferAndArrayImplementation; }
+ /**
+ * Used for certain internal type size computations
+ */
+ public final MachineDescription getMachineDescription() { return machDesc; }
+
+
protected void emitReturnType(PrintWriter writer)
{
writer.print("JNIEXPORT ");
@@ -437,7 +450,13 @@ public class CMethodBindingEmitter extends FunctionEmitter
emittedDataCopyTemps = true;
}
} else if (type.isString()) {
- writer.print(" const char* _UTF8");
+ Type cType = binding.getCArgumentType(i);
+ if (isUTF8Type(cType)) {
+ writer.print(" const char* ");
+ } else {
+ writer.print(" jchar* ");
+ }
+ writer.print(STRING_CHARS_PREFIX);
writer.print(binding.getArgumentName(i));
writer.println(" = NULL;");
}
@@ -500,6 +519,33 @@ public class CMethodBindingEmitter extends FunctionEmitter
}
}
+ /** Checks a type to see whether it is for a UTF-8 pointer type
+ (i.e., "const char *", "const char **"). False implies that this
+ type is for a Unicode pointer type ("jchar *", "jchar **"). */
+ protected boolean isUTF8Type(Type type) {
+ int i = 0;
+ // Try to dereference the type at most two levels
+ while (!type.isInt() && (i < 2)) {
+ PointerType pt = type.asPointer();
+ if (pt != null) {
+ type = pt.getTargetType();
+ } else {
+ ArrayType arrt = type.asArray();
+ if (arrt == null) {
+ throw new IllegalArgumentException("Type " + type + " should have been a pointer or array type");
+ }
+ type = arrt.getElementType();
+ }
+ }
+ if (!type.isInt()) {
+ throw new IllegalArgumentException("Type " + type + " should have been a one- or two-dimensional integer pointer or array type");
+ }
+ if (type.getSize(machDesc) != 1 && type.getSize(machDesc) != 2) {
+ throw new IllegalArgumentException("Type " + type + " should have been a one- or two-dimensional pointer to char or short");
+ }
+ return (type.getSize(machDesc) == 1);
+ }
+
/** Checks a type (expected to be pointer-to-pointer) for const-ness */
protected boolean isConstPtrPtr(Type type) {
if (type.pointerDepth() != 2) {
@@ -672,10 +718,11 @@ public class CMethodBindingEmitter extends FunctionEmitter
if (javaArgType.isStringArray()) {
writer.print(" ");
- emitGetStringUTFChars(writer,
- "(jstring) _tmpObj",
- convName+"_copy[_copyIndex]",
- true);
+ emitGetStringChars(writer,
+ "(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. */
@@ -735,20 +782,11 @@ public class CMethodBindingEmitter extends FunctionEmitter
continue;
}
- if (EMIT_NULL_CHECKS) {
- writer.print(" if (");
- writer.print(binding.getArgumentName(i));
- writer.println(" != NULL) {");
- }
-
- emitGetStringUTFChars(writer,
- binding.getArgumentName(i),
- "_UTF8" + binding.getArgumentName(i),
- false);
-
- if (EMIT_NULL_CHECKS) {
- writer.println(" }");
- }
+ emitGetStringChars(writer,
+ binding.getArgumentName(i),
+ STRING_CHARS_PREFIX + binding.getArgumentName(i),
+ isUTF8Type(binding.getCArgumentType(i)),
+ false);
}
}
}
@@ -767,6 +805,7 @@ public class CMethodBindingEmitter extends FunctionEmitter
if (javaArgType.isJNIEnv() || binding.isArgumentThisPointer(i)) {
continue;
}
+ Type cArgType = binding.getCArgumentType(i);
if (javaArgType.isArray() ||
(javaArgType.isNIOBuffer() && forIndirectBufferAndArrayImplementation) ||
@@ -800,9 +839,6 @@ public class CMethodBindingEmitter extends FunctionEmitter
//
// FIXME: should factor out this whole block of code into a separate
// method for clarity and maintenance purposes
- Type cArgType = binding.getCArgumentType(i);
- String cArgTypeName = cArgType.getName();
-
if (!isConstPtrPtr(cArgType)) {
// FIXME: handle any cleanup from treatment of non-const args,
// assuming they were treated differently in
@@ -902,11 +938,15 @@ public class CMethodBindingEmitter extends FunctionEmitter
writer.println(" != NULL) {");
}
- writer.print(" (*env)->ReleaseStringUTFChars(env, ");
- writer.print(binding.getArgumentName(i));
- writer.print(", _UTF8");
- writer.print(binding.getArgumentName(i));
- writer.println(");");
+ if (isUTF8Type(cArgType)) {
+ writer.print(" (*env)->ReleaseStringUTFChars(env, ");
+ writer.print(binding.getArgumentName(i));
+ writer.print(", " + STRING_CHARS_PREFIX);
+ writer.print(binding.getArgumentName(i));
+ writer.println(");");
+ } else {
+ writer.println(" free((void*) " + STRING_CHARS_PREFIX + binding.getArgumentName(i) + ");");
+ }
if (EMIT_NULL_CHECKS) {
writer.println(" }");
@@ -950,7 +990,7 @@ public class CMethodBindingEmitter extends FunctionEmitter
writer.print("_copy");
}
} else {
- if (javaArgType.isString()) { writer.print("_UTF8"); }
+ if (javaArgType.isString()) { writer.print(STRING_CHARS_PREFIX); }
writer.print(binding.getArgumentName(i));
}
}
@@ -1249,44 +1289,82 @@ public class CMethodBindingEmitter extends FunctionEmitter
}
}
- private void emitGetStringUTFChars(PrintWriter writer,
- String sourceVarName,
- String receivingVarName,
- boolean emitElseClause)
+ private void emitCalloc(PrintWriter writer,
+ String targetVarName,
+ String elementTypeString,
+ String numElementsExpression,
+ 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("));");
+ // Catch memory allocation failure
if (EMIT_NULL_CHECKS) {
- writer.print(" if (");
+ emitOutOfMemoryCheck(
+ writer, targetVarName,
+ mallocFailureErrorString);
+ }
+ }
+
+ private void emitGetStringChars(PrintWriter writer,
+ String sourceVarName,
+ String receivingVarName,
+ boolean isUTF8,
+ boolean emitElseClause)
+ {
+ if (EMIT_NULL_CHECKS) {
+ writer.print(" if (");
writer.print(sourceVarName);
writer.println(" != NULL) {");
}
- writer.print(" ");
- writer.print(receivingVarName);
- writer.print(" = (*env)->GetStringUTFChars(env, ");
- writer.print(sourceVarName);
- writer.println(", (jboolean*)NULL);");
- // Catch memory allocation failure in the event that the VM didn't pin
- // the String and failed to allocate a copy
- if (EMIT_NULL_CHECKS) {
- emitOutOfMemoryCheck(
- writer, receivingVarName,
- "Failed to get UTF-8 chars for argument \\\""+sourceVarName+"\\\"");
+ if (isUTF8) {
+ writer.print(" ");
+ writer.print(receivingVarName);
+ writer.print(" = (*env)->GetStringUTFChars(env, ");
+ writer.print(sourceVarName);
+ writer.println(", (jboolean*)NULL);");
+ // Catch memory allocation failure in the event that the VM didn't pin
+ // the String and failed to allocate a copy
+ if (EMIT_NULL_CHECKS) {
+ emitOutOfMemoryCheck(
+ writer, 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
+ // is that wide character strings are expected to be null
+ // terminated, but the JNI GetStringChars doesn't return a
+ // 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,
+ "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 + ");");
}
if (EMIT_NULL_CHECKS) {
- writer.print(" }");
+ writer.print(" }");
if (emitElseClause) {
writer.print(" else {");
writer.print(" ");
writer.print(receivingVarName);
writer.println(" = NULL;");
- writer.println(" }");
+ writer.println(" }");
} else {
writer.println();
}
}
}
-
-
private void emitGetDirectBufferAddress(PrintWriter writer,
String sourceVarName,
String receivingVarTypeString,
diff --git a/src/java/com/sun/gluegen/JavaConfiguration.java b/src/java/com/sun/gluegen/JavaConfiguration.java
index 7f6efa9..a452183 100644
--- a/src/java/com/sun/gluegen/JavaConfiguration.java
+++ b/src/java/com/sun/gluegen/JavaConfiguration.java
@@ -105,7 +105,7 @@ public class JavaConfiguration {
private Set/*<String>*/ returnsString = new HashSet();
private Map/*<String, String>*/ returnedArrayLengths = new HashMap();
/**
- * Key is function that has some byte[] arguments that should be
+ * Key is function that has some byte[] or short[] arguments that should be
* converted to String args; value is List of Integer argument indices
*/
private Map/*<String,List<Integer>>*/ argumentsAreString = new HashMap();
@@ -1065,8 +1065,8 @@ public class JavaConfiguration {
* </pre>
*
*/
- protected void readArgumentIsString(StringTokenizer tok, String filename, int lineNo) {
- try {
+ protected void readArgumentIsString(StringTokenizer tok, String filename, int lineNo) {
+ try {
String methodName = tok.nextToken();
ArrayList argIndices = new ArrayList(2);
while (tok.hasMoreTokens()) {
@@ -1074,10 +1074,9 @@ public class JavaConfiguration {
argIndices.add(idx);
}
- if(argIndices.size() > 0) {
+ if (argIndices.size() > 0) {
argumentsAreString.put(methodName, argIndices);
- }
- else {
+ } else {
throw new RuntimeException("ERROR: Error parsing \"ArgumentIsString\" command at line " + lineNo +
" in file \"" + filename + "\": directive requires specification of at least 1 index");
}
diff --git a/src/java/com/sun/gluegen/JavaEmitter.java b/src/java/com/sun/gluegen/JavaEmitter.java
index 6b51ef0..ef5c36d 100644
--- a/src/java/com/sun/gluegen/JavaEmitter.java
+++ b/src/java/com/sun/gluegen/JavaEmitter.java
@@ -508,7 +508,8 @@ public class JavaEmitter implements GlueEmitter {
true, /* NOTE: we always disambiguate with a suffix now, so this is optional */
cfg.allStatic(),
(binding.needsNIOWrappingOrUnwrapping() || hasPrologueOrEpilogue),
- false);
+ false,
+ machDesc64);
if (returnValueCapacityFormat != null) {
cEmitter.setReturnValueCapacityExpression(returnValueCapacityFormat);
}
@@ -532,7 +533,8 @@ public class JavaEmitter implements GlueEmitter {
true, /* NOTE: we always disambiguate with a suffix now, so this is optional */
cfg.allStatic(),
binding.needsNIOWrappingOrUnwrapping(),
- true);
+ true,
+ machDesc64);
if (returnValueCapacityFormat != null) {
cEmitter.setReturnValueCapacityExpression(returnValueCapacityFormat);
}
@@ -898,7 +900,8 @@ public class JavaEmitter implements GlueEmitter {
true, // FIXME: this is optional at this point
false,
true,
- false); // FIXME: should unify this with the general emission code
+ false, // FIXME: should unify this with the general emission code
+ machDesc64);
cEmitter.emit();
} catch (Exception e) {
System.err.println("While processing field " + field + " of type " + name + ":");
@@ -1520,7 +1523,7 @@ public class JavaEmitter implements GlueEmitter {
}
// List of the indices of the arguments in this function that should be
- // converted from byte[] to String
+ // converted from byte[] or short[] to String
List stringArgIndices = cfg.stringArguments(binding.getName());
for (int i = 0; i < sym.getNumArguments(); i++) {
@@ -1534,9 +1537,14 @@ public class JavaEmitter implements GlueEmitter {
//System.out.println("Forcing conversion of " + binding.getName() + " arg #" + i + " from byte[] to String ");
if (mappedType.isCVoidPointerType() ||
mappedType.isCCharPointerType() ||
- (mappedType.isArray() && mappedType.getJavaClass() == ArrayTypes.byteBufferArrayClass)) {
- // convert mapped type from void* and byte[] to String, or ByteBuffer[] to String[]
- if (mappedType.getJavaClass() == ArrayTypes.byteBufferArrayClass) {
+ mappedType.isCShortPointerType() ||
+ (mappedType.isArray() &&
+ (mappedType.getJavaClass() == ArrayTypes.byteBufferArrayClass) ||
+ (mappedType.getJavaClass() == ArrayTypes.shortBufferArrayClass))) {
+ // convert mapped type from:
+ // void*, byte[], and short[] to String
+ // ByteBuffer[] and ShortBuffer[] to String[]
+ if (mappedType.isArray()) {
mappedType = javaType(ArrayTypes.stringArrayClass);
} else {
mappedType = javaType(String.class);
@@ -1546,7 +1554,7 @@ public class JavaEmitter implements GlueEmitter {
throw new RuntimeException(
"Cannot apply ArgumentIsString configuration directive to " +
"argument " + i + " of \"" + sym + "\": argument type is not " +
- "a \"void*\", \"char *\", or \"char**\" equivalent");
+ "a \"void*\", \"char *\", \"short *\", \"char**\", or \"short**\" equivalent");
}
}
binding.addJavaArgumentType(mappedType);
diff --git a/src/java/com/sun/gluegen/procaddress/ProcAddressCMethodBindingEmitter.java b/src/java/com/sun/gluegen/procaddress/ProcAddressCMethodBindingEmitter.java
index 84e8132..41bae10 100755
--- a/src/java/com/sun/gluegen/procaddress/ProcAddressCMethodBindingEmitter.java
+++ b/src/java/com/sun/gluegen/procaddress/ProcAddressCMethodBindingEmitter.java
@@ -79,7 +79,8 @@ public class ProcAddressCMethodBindingEmitter extends CMethodBindingEmitter {
methodToWrap.getIsOverloadedBinding(),
methodToWrap.getIsJavaMethodStatic(),
true,
- methodToWrap.forIndirectBufferAndArrayImplementation()
+ methodToWrap.forIndirectBufferAndArrayImplementation(),
+ methodToWrap.getMachineDescription()
);
if (methodToWrap.getReturnValueCapacityExpression() != null) {
diff --git a/src/java/com/sun/gluegen/runtime/WindowsDynamicLinkerImpl.java b/src/java/com/sun/gluegen/runtime/WindowsDynamicLinkerImpl.java
index c1d2fa0..553c2f2 100755
--- a/src/java/com/sun/gluegen/runtime/WindowsDynamicLinkerImpl.java
+++ b/src/java/com/sun/gluegen/runtime/WindowsDynamicLinkerImpl.java
@@ -1,4 +1,4 @@
-/* !---- DO NOT EDIT: This file autogenerated by com\sun\gluegen\JavaEmitter.java on Mon Jul 31 16:26:59 PDT 2006 ----! */
+/* !---- DO NOT EDIT: This file autogenerated by com\sun\gluegen\JavaEmitter.java on Tue May 27 02:37:55 PDT 2008 ----! */
package com.sun.gluegen.runtime;
@@ -14,20 +14,20 @@ public class WindowsDynamicLinkerImpl implements DynamicLinker
/** Interface to C language function: <br> <code> DWORD GetLastError(void); </code> */
private static native int GetLastError();
- /** Interface to C language function: <br> <code> PROC GetProcAddress(HANDLE hModule, LPCSTR lpProcName); </code> */
- private static native long GetProcAddress(long hModule, java.lang.String lpProcName);
+ /** Interface to C language function: <br> <code> PROC GetProcAddressA(HANDLE hModule, LPCSTR lpProcName); </code> */
+ private static native long GetProcAddressA(long hModule, java.lang.String lpProcName);
- /** Interface to C language function: <br> <code> HANDLE LoadLibraryA(LPCSTR lpLibFileName); </code> */
- private static native long LoadLibraryA(java.lang.String lpLibFileName);
+ /** Interface to C language function: <br> <code> HANDLE LoadLibraryW(LPCWSTR lpLibFileName); </code> */
+ private static native long LoadLibraryW(java.lang.String lpLibFileName);
// --- Begin CustomJavaCode .cfg declarations
public long openLibrary(String libraryName) {
- return LoadLibraryA(libraryName);
+ return LoadLibraryW(libraryName);
}
public long lookupSymbol(long libraryHandle, String symbolName) {
- return GetProcAddress(libraryHandle, symbolName);
+ return GetProcAddressA(libraryHandle, symbolName);
}
public void closeLibrary(long libraryHandle) {