Comparar commits

..

24 Commits

Autor SHA1 Mensagem Data
Timothy Wall 78cdc63b76 update libraries and docs
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@181 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2007-07-24 17:31:25 +00:00
Timothy Wall 6ef191563a Fix VM crash in Structure.toArray by clearing memory prior to read
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@180 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2007-07-18 19:08:01 +00:00
Timothy Wall daf616be22 jna.encoding controls native encoding, if set.
Remove superfluous comparison cruft from NativeString.
Update overview doc.

git-svn-id: https://svn.java.net/svn/jna~svn/trunk@176 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2007-07-18 01:26:09 +00:00
Timothy Wall 278dc84bb9 Fix reading WString into a Structure
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@174 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2007-07-17 12:25:01 +00:00
Timothy Wall 686a2931e6 Add test for proper Kernel32.GetLastError operation
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@173 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2007-07-16 20:33:37 +00:00
Timothy Wall 5be5a0e417 Enhance javadoc
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@172 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2007-07-16 20:32:30 +00:00
Timothy Wall cd2d1dbb76 Avoid potential errors converting native byte[]/char[] to String
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@171 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2007-07-16 20:31:43 +00:00
Timothy Wall 68a92623d0 Write memory for initialized structure array arguments
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@170 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2007-07-16 20:30:16 +00:00
tweea 81b3255577 Organize imports.
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@158 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2007-07-11 09:42:19 +00:00
Timothy Wall fc33a22f27 Add union support
Fix bug clearing OSX window mask
Add access to ByteBuffer direct address as Pointer

git-svn-id: https://svn.java.net/svn/jna~svn/trunk@157 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2007-07-11 02:57:04 +00:00
Timothy Wall 5267c76580 part of last commit
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@150 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2007-06-27 20:59:54 +00:00
Timothy Wall 2908b993a3 Enable type mapping for callbacks
Avoid static instance variables in tests
Fill out wide character support
Fix osx/ppc struct alignment bug

git-svn-id: https://svn.java.net/svn/jna~svn/trunk@149 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2007-06-27 20:58:59 +00:00
Timothy Wall 1c172bf513 Fix sporadic exception on X11
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@148 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2007-06-25 18:49:09 +00:00
Timothy Wall aa037e4a0c Fix sporadic exception on X11
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@147 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2007-06-25 18:46:27 +00:00
Timothy Wall 10dd04e03c Update demo with optimized, shaped windows
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@146 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2007-06-25 18:23:40 +00:00
Timothy Wall 560f75c755 Elaborate callback example
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@145 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2007-06-25 18:22:07 +00:00
Timothy Wall f2ce65fb84 Add optimization for window shape masks (ochafik/cdecker)
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@144 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2007-06-25 16:09:48 +00:00
Timothy Wall eb1d463889 fix editor droppings
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@143 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2007-06-18 14:07:46 +00:00
Timothy Wall 8d021cb29c Use proper array typing
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@142 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2007-06-18 14:06:25 +00:00
Timothy Wall 70faac1b6a Copy proper varargs handling/test from v3 branch
Handle void callback return type in native code
Do not use java.library.path for JNA library lookups (from v3)
Make some internal Function methods private instead of public
Clean up Function.invokeString variants

git-svn-id: https://svn.java.net/svn/jna~svn/trunk@141 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2007-06-18 14:04:41 +00:00
Timothy Wall abaf425a36 fix typo in field name comparison (nik)
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@138 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2007-06-15 14:08:37 +00:00
Timothy Wall 95a0333057 Fix issue 22; validate structure member ordering
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@137 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2007-06-12 16:04:57 +00:00
Timothy Wall a49bba636a update front page/javadoc
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@136 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2007-06-11 18:31:25 +00:00
Timothy Wall e252ef2cb2 reinstate invokeXXX methods (for extra-Java convenience)
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@135 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2007-06-11 18:30:00 +00:00
204 arquivos alterados com 2661 adições e 1027 exclusões
+51 -32
Ver Arquivo
@@ -6,9 +6,10 @@
# TODO:
* review/use refactor nativelibrary/function
* review/use ByteBuffer everywhere
* change/augment getWindowHandle0 to provide any heavyweight component window
* use jna.encoding property to affect string encoding instead of just using
the system default encoding.
* design:
@@ -25,41 +26,35 @@
- pointer to type in struct should be handled with Pointer
- how to do pointer to struct in struct? (Pointer to start with)
o "free" should be invisible wherever possible
* auto-convert struct pointers in callback args to Java Structure
(may need a proxy wrapper around callback to avoid excessive JNI)
* per-library jna.library.path: many libraries have a "standard" location (or
several); let the library author indicate what these are (X11, for example)
* return array of struct (annotation to indicate which argument has the
length of the returned value might be nice)
* determine X11 display name from current java program (if any); null is ok
since it uses getenv(DISPLAY), which is what java would do
note: DISPLAY may be avilable in GraphicsDevice->getIDstring
* split unit tests
* universal OSX build w/cross-compile (callbacks fail)
* universal GCC build w/cross-compile
* catch native crash/exception/faults and re-throw as java exception
* use libffi from gcc to handle calls and callbacks?
or move callback asm templates into dispatch_<arch>.c
* auto-generate stdcall decorated symbols (try if undecorated lookup fails)
* make Pointer free-able (system allocates memory, client frees it); actually,
this should probably be automatic so the user doesn't have to think about it.
Maybe a custom type representing "function-allocated-pointer" or
"pointer-requiring-free" (which is just Memory).
* callbacks need a dispose if they are to live beyond the lifetime of the
function to which they are passed; maybe a simpler callback interface for
transient callbacks, and require callback+dispose for most callbacks?
TransientCallback: callback
NonTransientCallback: callback+dispose
* return Pointer.SIZE/LONG_SIZE in bits (for consistency with 1.5)
* use proxy for callbacks to enable auto-conversion of arguments and/or return
value (in java-land instead of C-land).
* provide library load/unload hooks (Runnables in options?). Examples:
o GetLastError in kernel32
o WSAInit?
* determine X11 display name from current java program (if any); null is ok
since it uses getenv(DISPLAY), which is what java would do
note: DISPLAY may be available in GraphicsDevice->getIDstring
* universal OSX build w/cross-compile (hard to do with libffi)
* universal GCC build w/cross-compile
* catch native crash/exception/faults and re-throw as java exception
this is mostly for debugging a new mapping to avoid crashing the VM
could do setjmp/longjmp on *nix and catch C++ exception on w32
* return Pointer.SIZE/LONG_SIZE/WCHAR_SIZE in bits (for consistency with 1.5)
Long.SIZE, Integer.SIZE, et al.
* interface "lvalue", which can provide a pointer to itself (reference() or
addressOf())?
* how to do direct struct argument (vs struct pointer) (uncommon)?
* how to do struct return (vs struct pointer) (uncommon)?
* more tests for argument types (2 args, all permutations of basic data types)
ensures native stack handling is done properly
* make Pointer free-able (system allocates memory, client frees it); actually,
this should probably be automatic so the user doesn't have to think about it.
Maybe a custom type representing "function-allocated-pointer" or
"pointer-requiring-free" (which is just Memory). For now, leave it up to
the user to manage the pointer, since they have to define the free method
anyway.
* flag string(/wstring)-returning methods which need to free their result
to avoid leaking memory whan auto-creating strings from the result
(since normally we don't take explicit ownership of any returned pointers)
@@ -73,10 +68,10 @@ transient callbacks, and require callback+dispose for most callbacks?
* unions (copy-on-call is problematic: which member is active?) must require
explicit write, either per member or whole object before export
* verify get/set methods vs read/write is for performance (Pointer)?
* type safety between returned and passed in pointers (w32 API)
* type safety between returned and passed in pointers (w32 API); advantage of
deriving from Pointer is that type mapping can be made automatic, without an
explicit type mapping defined.
* bitfields et al. for structs
* auto-convert strings in w32 functions ending in 'W'? would this introduce
any ambiguity?
* use annotations + result codes + GetLastError/errno/errstr to auto-generate
runtime exceptions? (cf P/Invoke; also useful for X11 return types)
provide annotation/custom invocation handler/hook to examine return value and
@@ -90,6 +85,29 @@ transient callbacks, and require callback+dispose for most callbacks?
# DONE
* Union
* rename Argument/Result Converter to be fromNative/toNative
* split unit tests
* auto-convert struct pointers in callback args to Java Structure
(may need a proxy wrapper around callback to avoid excessive JNI)
use proxy for callbacks to enable auto-conversion of arguments and/or return
value (in java-land instead of C-land).
* review/use refactor nativelibrary/function
* auto-generate stdcall decorated symbols (try if undecorated lookup fails)
* per-library jna.library.path: many libraries have a "standard" location (or
several); let the library author indicate what these are (X11, for example)
* return array of struct (annotation to indicate which argument has the
length of the returned value might be nice) (this can now be done with a
type mapper)
* callbacks need a dispose if they are to live beyond the lifetime of the
function to which they are passed; maybe a simpler callback interface for
transient callbacks, and require callback+dispose for most callbacks?
TransientCallback: callback
NonTransientCallback: callback+dispose
(callback is disposed when no longer referenced; user must ensure callback
is not GC'd until it is removed as a native callback)
* auto-convert strings in w32 functions ending in 'W'? would this introduce
any ambiguity?
* Dispose/unload library on GC (use ref queue)
* fix dnd on linux (no hole?) (mostly fixed, still some artifacts)
* transparent/shaped drag image
@@ -151,7 +169,8 @@ int findNativeWindow(Window w);
# jnieasy: c++ mappings (http://www.innowhere.com:8080/webapp/jsp/products/jnieasy/index.jsp?_page=products.jnieasy)
# j2native (www.smardec.com)
# j-interop.sf.net
# jawinproject.sf.net
# jawinproject.sf.net (COM DLL access)
# jacob-project.sf.net (COM DLL access)
# nativecall.sf.net (minimal)
# cxxwrap.sf.net
# xFunction (osx)
+33 -2
Ver Arquivo
@@ -29,7 +29,7 @@
value="Copyright &amp;copy; 2007 ${company.full}. All Rights Reserved."/>
<!-- Software release version -->
<property name="version" value="2.4"/>
<property name="version" value="2.5"/>
<property name="jdk" value="1.4"/>
<!-- Miscellaneous -->
@@ -354,9 +354,40 @@
<nbprofiledirect>
<classpath> <pathelement location="${build}/examples.jar"/> </classpath>
</nbprofiledirect>
<java jar="${build}/examples.jar" fork="true">
<java classname="${main.class}" fork="true">
<jvmarg value="${profiler.info.jvmargs.agent}"/>
<jvmarg value="${profiler.info.jvmargs}"/>
<jvmarg value="-Djna.library.path=${build.native}"/>
<classpath>
<pathelement location="${build}/examples.jar"/>
</classpath>
</java>
</target>
<target name="profile-test-single" depends="examples-jar,compile-tests"
description="Profile Test Class">
<fail unless="netbeans.home">This target can only run inside the NetBeans IDE.</fail>
<nbprofiledirect>
<classpath>
<pathelement location="${build}/examples.jar"/>
<pathelement location="${test.classes}"/>
</classpath>
</nbprofiledirect>
<junit dir="${build.native}" jvm="${profiler.info.jvm}"
failureproperty="tests.failed" errorproperty="tests.failed" fork="true">
<jvmarg value="${profiler.info.jvmargs.agent}"/>
<jvmarg value="${profiler.info.jvmargs}"/>
<jvmarg value="-Djna.library.path=${build.native}"/>
<test name="${profile.class}"/>
<classpath>
<pathelement location="${build}/examples.jar"/>
<pathelement location="${test.classes}"/>
</classpath>
<formatter type="brief" usefile="false"/>
<formatter type="xml"/>
</junit>
</target>
</project>
BIN
Ver Arquivo
Arquivo binário não exibido.
BIN
Ver Arquivo
Arquivo binário não exibido.
BIN
Ver Arquivo
Arquivo binário não exibido.
BIN
Ver Arquivo
Arquivo binário não exibido.
BIN
Ver Arquivo
Arquivo binário não exibido.
BIN
Ver Arquivo
Arquivo binário não exibido.
+24 -61
Ver Arquivo
@@ -208,8 +208,7 @@ extern void asm_template_end();
callback*
create_callback(JNIEnv* env, jobject obj, jobject method,
jobjectArray param_types, jclass return_type,
callconv_t call_conv) {
jobjectArray param_types, callconv_t call_conv) {
callback* cb;
unsigned long* insns;
int args_size = 0;
@@ -249,8 +248,6 @@ create_callback(JNIEnv* env, jobject obj, jobject method,
args_size += 4;
}
}
cb->return_jtype = get_jtype(env, return_type);
cb->return_type = get_type(cb->return_jtype);
// initialize and customize the callback template
memcpy((void*)insns, (void*)callback_asm_template, len);
@@ -316,6 +313,7 @@ create_callback(JNIEnv* env, jobject obj, jobject method,
static type_t
get_type(char type) {
switch(type) {
case 'V':
case 'Z':
case 'B':
case 'C':
@@ -338,10 +336,11 @@ static void
callback_dispatch(JavaVM* jvm, callback* cb, char* ap) {
jobject obj;
jmethodID mid;
jvalue args[MAX_NARGS];
jvalue result;
type_t return_type;
JNIEnv* env;
int attached;
jobjectArray args;
int i;
attached = (*jvm)->GetEnv(jvm, (void *)&env, JNI_VERSION_1_4) == JNI_OK;
@@ -353,74 +352,38 @@ callback_dispatch(JavaVM* jvm, callback* cb, char* ap) {
}
}
// NOTE: some targets may require alignment of stack items...
for (i=0;i < cb->param_count;i++) {
switch(cb->param_jtypes[i]) {
case 'L': {
int ptr_size = sizeof(void*);
jlong ptr = ptr_size == sizeof(jlong) ? *(jlong*)ap : *(jint*)ap;
// TODO: create a corresponding java structure type
// based on the callback argument type
args[i].l = newJavaPointer(env, L2A(ptr));
ap += ptr_size;
break;
}
case 'J':
args[i].j = *(jlong *)ap;
ap += sizeof(jlong);
break;
case 'F':
args[i].f = *(float *)ap;
ap += sizeof(float);
break;
case 'D':
args[i].d = *(double *)ap;
ap += sizeof(double);
break;
case 'Z':
case 'B':
case 'S':
case 'I':
default:
args[i].i = *(int *)ap;
ap += sizeof(int);
break;
}
}
obj = (*env)->NewLocalRef(env, cb->object);
mid = cb->methodID;
args = (*env)->NewObjectArray(env, cb->param_count,
(*env)->FindClass(env, "java/lang/Object"),
NULL);
// Convert primitive types into objects so we can properly stuff
// an array of Object for the callback proxy argument list
// NOTE: some targets may require different alignment of stack items...
for (i=0;i < cb->param_count;i++) {
int size;
jobject arg = new_object(env, cb->param_jtypes[i], (void*)ap, &size);
ap += size;
(*env)->SetObjectArrayElement(env, args, i, arg);
}
// Avoid calling back to a GC'd object
if ((*env)->IsSameObject(env, obj, NULL)) {
fprintf(stderr, "Warning: attempt to call GC'd callback\n");
result.j = 0;
return_type = TYPE_VOID;
}
else switch(cb->return_jtype) {
case 'Z':
result.i = (*env)->CallBooleanMethodA(env, obj, mid, args); break;
case 'B':
result.i = (*env)->CallByteMethodA(env, obj, mid, args); break;
case 'C':
result.i = (*env)->CallCharMethodA(env, obj, mid, args); break;
case 'S':
result.i = (*env)->CallShortMethodA(env, obj, mid, args); break;
case 'I':
result.i = (*env)->CallIntMethodA(env, obj, mid, args); break;
case 'J':
result.j = (*env)->CallLongMethodA(env, obj, mid, args); break;
case 'F':
result.f = (*env)->CallFloatMethodA(env, obj, mid, args); break;
case 'D':
result.d = (*env)->CallDoubleMethodA(env, obj, mid, args); break;
case 'L':
default:
result.l = (*env)->CallObjectMethodA(env, obj, mid, args); break;
else {
jobject value = (*env)->CallObjectMethod(env, obj, mid, args);
result = extract_value(env, value, &return_type);
}
if (!attached) {
(*jvm)->DetachCurrentThread(jvm);
}
switch(cb->return_type) {
switch(return_type) {
case TYPE_PTR:
RETURN_PTR(result.l);
return;
+191 -20
Ver Arquivo
@@ -59,6 +59,7 @@ extern "C"
static jclass classObject;
static jclass classClass;
static jclass classMethod;
static jclass classVoid, classPrimitiveVoid;
static jclass classBoolean, classPrimitiveBoolean;
static jclass classByte, classPrimitiveByte;
static jclass classCharacter, classPrimitiveCharacter;
@@ -71,7 +72,6 @@ static jclass classString;
static jclass classPointer;
static jclass classByteBuffer;
static jmethodID MID_getClass;
static jmethodID MID_Class_getComponentType;
static jmethodID MID_String_getBytes;
static jmethodID MID_String_toCharArray;
@@ -79,9 +79,19 @@ static jmethodID MID_String_init_bytes;
static jmethodID MID_Pointer_init;
static jmethodID MID_Method_getReturnType;
static jmethodID MID_Method_getParameterTypes;
static jmethodID MID_Long_init;
static jmethodID MID_Integer_init;
static jmethodID MID_Short_init;
static jmethodID MID_Character_init;
static jmethodID MID_Byte_init;
static jmethodID MID_Boolean_init;
static jmethodID MID_Float_init;
static jmethodID MID_Double_init;
static jfieldID FID_Boolean_value;
static jfieldID FID_Byte_value;
static jfieldID FID_Short_value;
static jfieldID FID_Character_value;
static jfieldID FID_Integer_value;
static jfieldID FID_Long_value;
static jfieldID FID_Float_value;
@@ -137,6 +147,10 @@ static void dispatch(JNIEnv *env, jobject self, jint callconv,
c_args[nwords].p = NULL;
nwords += sizeof(void *) / sizeof(word_t);
}
else if ((*env)->IsInstanceOf(env, arg, classBoolean)) {
arg_types[i] = TYPE_INT32;
c_args[nwords++].i = (*env)->GetBooleanField(env, arg, FID_Boolean_value);
}
else if ((*env)->IsInstanceOf(env, arg, classByte)) {
arg_types[i] = TYPE_INT32;
c_args[nwords++].i = (*env)->GetByteField(env, arg, FID_Byte_value);
@@ -145,6 +159,10 @@ static void dispatch(JNIEnv *env, jobject self, jint callconv,
arg_types[i] = TYPE_INT32;
c_args[nwords++].i = (*env)->GetShortField(env, arg, FID_Short_value);
}
else if ((*env)->IsInstanceOf(env, arg, classCharacter)) {
arg_types[i] = TYPE_INT32;
c_args[nwords++].i = (*env)->GetCharField(env, arg, FID_Character_value);
}
else if ((*env)->IsInstanceOf(env, arg, classInteger)) {
arg_types[i] = TYPE_INT32;
c_args[nwords++].i = (*env)->GetIntField(env, arg, FID_Integer_value);
@@ -200,7 +218,7 @@ static void dispatch(JNIEnv *env, jobject self, jint callconv,
arg_types[i] = TYPE_PTR;
c_args[nwords].p = (*env)->GetDirectBufferAddress(env, arg);
if (c_args[nwords].p == NULL) {
// TODO: treat as byte[]?
// TODO: treat buf.array() as byte[]?
throwByName(env,"java/lang/IllegalArgumentException",
"Non-direct ByteBuffer is not supported");
goto cleanup;
@@ -208,8 +226,9 @@ static void dispatch(JNIEnv *env, jobject self, jint callconv,
nwords += sizeof(void *)/sizeof(word_t);
}
else {
throwByName(env,"java/lang/IllegalArgumentException",
"Unrecognized argument type");
char buf[1024];
sprintf(buf, "Unsupported type at parameter %d", i);
throwByName(env,"java/lang/IllegalArgumentException", buf);
goto cleanup;
}
}
@@ -226,7 +245,7 @@ static void dispatch(JNIEnv *env, jobject self, jint callconv,
#endif // _WIN32
default:
throwByName(env,"java/lang/IllegalArgumentException","Unrecognized call type");
throwByName(env,"java/lang/IllegalArgumentException","Unrecognized calling convention");
}
cleanup:
@@ -356,13 +375,13 @@ Java_com_sun_jna_Function_invokeVoid(JNIEnv *env, jobject self,
}
JNIEXPORT jobject JNICALL
Java_com_sun_jna_Function_createCallback(JNIEnv *env, jclass functionClass,
jobject obj, jobject method,
jobjectArray param_types,
jclass return_type,
jint call_conv) {
Java_com_sun_jna_CallbackReference_createCallback(JNIEnv *env,
jclass clazz,
jobject obj, jobject method,
jobjectArray param_types,
jint call_conv) {
callback* cb =
create_callback(env, obj, method, param_types, return_type, call_conv);
create_callback(env, obj, method, param_types, call_conv);
if (cb != NULL) {
return newJavaPointer(env, cb);
}
@@ -370,8 +389,9 @@ Java_com_sun_jna_Function_createCallback(JNIEnv *env, jclass functionClass,
}
JNIEXPORT void JNICALL
Java_com_sun_jna_Function_freeCallback(JNIEnv *env,
jclass functionClass, jlong ptr) {
Java_com_sun_jna_CallbackReference_freeCallback(JNIEnv *env,
jclass clazz,
jlong ptr) {
callback* cb = (callback*)L2A(ptr);
(*env)->DeleteWeakGlobalRef(env, cb->object);
free(cb->insns);
@@ -423,7 +443,6 @@ JNIEXPORT jlong JNICALL Java_com_sun_jna_NativeLibrary_findSymbol(JNIEnv *env,
free(funname);
}
return (jlong)A2L(func);
}
/*
@@ -444,6 +463,7 @@ Java_com_sun_jna_Pointer_initIDs(JNIEnv *env, jclass cls)
classPointer = cls;
if (!LOAD_REF(env, classPointer)) return 0;
if (!LOAD_PCREF(env, Void, "java/lang/Void")) return 0;
if (!LOAD_PCREF(env, Boolean, "java/lang/Boolean")) return 0;
if (!LOAD_PCREF(env, Byte, "java/lang/Byte")) return 0;
if (!LOAD_PCREF(env, Character, "java/lang/Character")) return 0;
@@ -456,8 +476,29 @@ Java_com_sun_jna_Pointer_initIDs(JNIEnv *env, jclass cls)
if (!LOAD_MID(env, MID_Pointer_init, classPointer,
"<init>", "(J)V"))
return 0;
if (!LOAD_MID(env, MID_getClass, classObject,
"getClass", "()Ljava/lang/Class;"))
if (!LOAD_MID(env, MID_Long_init, classLong,
"<init>", "(J)V"))
return 0;
if (!LOAD_MID(env, MID_Integer_init, classInteger,
"<init>", "(I)V"))
return 0;
if (!LOAD_MID(env, MID_Short_init, classShort,
"<init>", "(S)V"))
return 0;
if (!LOAD_MID(env, MID_Character_init, classCharacter,
"<init>", "(C)V"))
return 0;
if (!LOAD_MID(env, MID_Byte_init, classByte,
"<init>", "(B)V"))
return 0;
if (!LOAD_MID(env, MID_Boolean_init, classBoolean,
"<init>", "(Z)V"))
return 0;
if (!LOAD_MID(env, MID_Float_init, classFloat,
"<init>", "(F)V"))
return 0;
if (!LOAD_MID(env, MID_Double_init, classDouble,
"<init>", "(D)V"))
return 0;
if (!LOAD_MID(env, MID_Class_getComponentType, classClass,
"getComponentType", "()Ljava/lang/Class;"))
@@ -478,10 +519,14 @@ Java_com_sun_jna_Pointer_initIDs(JNIEnv *env, jclass cls)
"getReturnType", "()Ljava/lang/Class;"))
return 0;
if (!LOAD_FID(env, FID_Boolean_value, classBoolean, "value", "Z"))
return 0;
if (!LOAD_FID(env, FID_Byte_value, classByte, "value", "B"))
return 0;
if (!LOAD_FID(env, FID_Short_value, classShort, "value", "S"))
return 0;
if (!LOAD_FID(env, FID_Character_value, classCharacter, "value", "C"))
return 0;
if (!LOAD_FID(env, FID_Integer_value, classInteger, "value", "I"))
return 0;
if (!LOAD_FID(env, FID_Long_value, classLong, "value", "J"))
@@ -600,6 +645,24 @@ JNIEXPORT void JNICALL Java_com_sun_jna_Pointer_write__I_3SII
(*env)->GetShortArrayRegion(env, arr, off, n, (jshort*)(peer + boff));
}
/*
* Class: Pointer
* Method: indexOf
* Signature: (IB)I
*/
JNIEXPORT jint JNICALL Java_com_sun_jna_Pointer_indexOf__IB
(JNIEnv *env, jobject self, jint boff, jbyte value)
{
jbyte *peer = (jbyte *)getNativeAddress(env, self) + boff;
int i = 0;
while (i >= 0) {
if (peer[i] == value)
return i;
++i;
}
return -1;
}
/*
* Class: Pointer
* Method: read
@@ -973,7 +1036,7 @@ throwByName(JNIEnv *env, const char *name, const char *msg)
/* Translates a Java string to a C string using the String.getBytes
* method, which uses default local encoding.
*/
// TODO: make sure encoding is correct
// TODO: use jna.encoding
static char *
newCString(JNIEnv *env, jstring jstr)
{
@@ -999,7 +1062,7 @@ newCString(JNIEnv *env, jstring jstr)
/* Translates a Java string to a wide C string using the String.toCharArray
* method.
*/
// TODO: make any required encoding changes
// TODO: are any encoding changes required?
static wchar_t *
newWideCString(JNIEnv *env, jstring str)
{
@@ -1089,6 +1152,9 @@ newJavaPointer(JNIEnv *env, void *p)
char
get_jtype(JNIEnv* env, jclass cls) {
if ((*env)->IsSameObject(env, classVoid, cls)
|| (*env)->IsSameObject(env, classPrimitiveVoid, cls))
return 'V';
if ((*env)->IsSameObject(env, classBoolean, cls)
|| (*env)->IsSameObject(env, classPrimitiveBoolean, cls))
return 'Z';
@@ -1125,7 +1191,7 @@ getNativeAddress(JNIEnv *env, jobject obj) {
static char
getArrayComponentType(JNIEnv *env, jobject obj) {
jclass cls = (*env)->CallObjectMethod(env, obj, MID_getClass);
jclass cls = (*env)->GetObjectClass(env, obj);
jclass type = (*env)->CallObjectMethod(env, cls, MID_Class_getComponentType);
if (type != NULL) {
return get_jtype(env, type);
@@ -1135,7 +1201,7 @@ getArrayComponentType(JNIEnv *env, jobject obj) {
JNIEXPORT jlong JNICALL
Java_com_sun_jna_Native_getWindowHandle0(JNIEnv *env, jobject unused, jobject w) {
Java_com_sun_jna_Native_getWindowHandle0(JNIEnv *env, jobject classp, jobject w) {
jlong handle = 0;
JAWT_DrawingSurface* ds;
JAWT_DrawingSurfaceInfo* dsi;
@@ -1209,6 +1275,15 @@ Java_com_sun_jna_Native_getWindowHandle0(JNIEnv *env, jobject unused, jobject w)
return handle;
}
JNIEXPORT jobject JNICALL
Java_com_sun_jna_Native_getByteBufferPointer(JNIEnv *env, jobject classp, jobject byteBuffer) {
void* addr = (*env)->GetDirectBufferAddress(env, byteBuffer);
if (addr == NULL) {
throwByName(env,"java/lang/IllegalArgumentException",
"Non-direct ByteBuffer is not supported");
}
return newJavaPointer(env, addr);
}
static jboolean
init_jawt(JNIEnv* env) {
@@ -1297,6 +1372,102 @@ init_jawt(JNIEnv* env) {
return JNI_TRUE;
}
jvalue
extract_value(JNIEnv* env, jobject value, type_t* return_type) {
jvalue result;
if (value == NULL) {
result.j = 0;
*return_type = TYPE_PTR;
}
else if ((*env)->IsInstanceOf(env, value, classVoid)) {
result.j = 0;
*return_type = TYPE_VOID;
}
else if ((*env)->IsInstanceOf(env, value, classBoolean)) {
result.i = (*env)->GetBooleanField(env, value, FID_Boolean_value);
*return_type = TYPE_INT32;
}
else if ((*env)->IsInstanceOf(env, value, classByte)) {
result.i = (*env)->GetByteField(env, value, FID_Byte_value);
*return_type = TYPE_INT32;
}
else if ((*env)->IsInstanceOf(env, value, classShort)) {
result.i = (*env)->GetShortField(env, value, FID_Short_value);
*return_type = TYPE_INT32;
}
else if ((*env)->IsInstanceOf(env, value, classCharacter)) {
result.i = (*env)->GetCharField(env, value, FID_Character_value);
*return_type = TYPE_INT32;
}
else if ((*env)->IsInstanceOf(env, value, classInteger)) {
result.i = (*env)->GetIntField(env, value, FID_Integer_value);
*return_type = TYPE_INT32;
}
else if ((*env)->IsInstanceOf(env, value, classLong)) {
result.j = (*env)->GetLongField(env, value, FID_Long_value);
*return_type = TYPE_INT64;
}
else if ((*env)->IsInstanceOf(env, value, classFloat)) {
result.f = (*env)->GetFloatField(env, value, FID_Float_value);
*return_type = TYPE_FP32;
}
else if ((*env)->IsInstanceOf(env, value, classDouble)) {
result.d = (*env)->GetDoubleField(env, value, FID_Double_value);
*return_type = TYPE_FP64;
}
else if ((*env)->IsInstanceOf(env, value, classPointer)) {
result.l = getNativeAddress(env, value);
*return_type = TYPE_PTR;
}
else {
result.l = value;
*return_type = TYPE_PTR;
}
return result;
}
jobject
new_object(JNIEnv* env, char jtype, void* ap, int* sizep) {
switch(jtype) {
case 'L':
*sizep = sizeof(void*);
return newJavaPointer(env, *(void**)ap);
case 'J':
*sizep = sizeof(jlong);
return (*env)->NewObject(env, classLong, MID_Long_init,
*(jlong *)ap);
case 'F':
*sizep = sizeof(float);
return (*env)->NewObject(env, classFloat, MID_Float_init,
*(float *)ap);
case 'D':
*sizep = sizeof(double);
return (*env)->NewObject(env, classDouble, MID_Double_init,
*(double *)ap);
case 'Z':
*sizep = sizeof(int);
return (*env)->NewObject(env, classBoolean, MID_Boolean_init,
(*(int *)ap ? JNI_TRUE : JNI_FALSE));
case 'B':
*sizep = sizeof(int);
return (*env)->NewObject(env, classByte, MID_Byte_init,
*(int *)ap & 0xFF);
case 'C':
*sizep = sizeof(int);
return (*env)->NewObject(env, classCharacter, MID_Character_init,
*(wchar_t *)ap & 0xFFFF);
case 'S':
*sizep = sizeof(int);
return (*env)->NewObject(env, classShort, MID_Short_init,
*(int *)ap & 0xFFFF);
case 'I':
default:
*sizep = sizeof(int);
return (*env)->NewObject(env, classInteger, MID_Integer_init,
*(int *)ap);
}
}
#ifdef __cplusplus
}
#endif
+3 -4
Ver Arquivo
@@ -45,8 +45,6 @@ typedef struct _callback {
jmethodID methodID;
jsize param_count;
char param_jtypes[MAX_NARGS];
type_t return_type;
char return_jtype;
} callback;
#if defined(SOLARIS2) || defined(__GNUC__)
@@ -90,8 +88,9 @@ extern void throwByName(JNIEnv *env, const char *name, const char *msg);
extern jobject newJavaPointer(JNIEnv *, void *);
extern char get_jtype(JNIEnv*, jclass);
extern callback* create_callback(JNIEnv*, jobject, jobject,
jobjectArray, jclass, callconv_t);
jobjectArray, callconv_t);
extern jvalue extract_value(JNIEnv*, jobject, type_t*);
extern jobject new_object(JNIEnv*, char, void*, int*);
#ifdef __cplusplus
}
#endif
+44
Ver Arquivo
@@ -90,6 +90,11 @@ returnInt8Argument(int8 arg) {
return NOP(arg);
}
EXPORT wchar_t
returnWideCharArgument(wchar_t arg) {
return arg;
}
EXPORT int16
returnInt16Argument(int16 arg) {
nonleaf();
@@ -408,6 +413,16 @@ testStructureAlignment(void* s, unsigned index, int* offsetp, int64* valuep) {
return -2;
}
EXPORT int32
testStructureArrayInitialization(struct CheckFieldAlignment arg[], int len) {
int i;
for (i=0;i < len;i++) {
if (arg[i].int32Field != i)
return i;
}
return -1;
}
EXPORT void
modifyStructureArray(struct CheckFieldAlignment arg[], int length) {
int i;
@@ -425,6 +440,13 @@ callVoidCallback(void (*func)()) {
(*func)();
}
EXPORT int
callBooleanCallback(int (*func)(int arg, int arg2),
int arg, int arg2) {
nonleaf();
return (*func)(NOP(arg), NOP(arg2));
}
EXPORT int32
callInt32Callback(int32 (*func)(int32 arg, int32 arg2),
int32 arg, int32 arg2) {
@@ -432,6 +454,13 @@ callInt32Callback(int32 (*func)(int32 arg, int32 arg2),
return (*func)(NOP(arg), NOP(arg2));
}
EXPORT long
callNativeLongCallback(long (*func)(long arg, long arg2),
long arg, long arg2) {
nonleaf();
return (*func)(NOP(arg), NOP(arg2));
}
EXPORT int64
callInt64Callback(int64 (*func)(int64 arg, int64 arg2),
int64 arg, int64 arg2) {
@@ -453,6 +482,21 @@ callDoubleCallback(double (*func)(double arg, double arg2),
return (*func)(NOP(arg), NOP(arg2));
}
EXPORT TestStructure*
callStructureCallback(TestStructure* (*func)(TestStructure*), TestStructure* arg) {
return (*func)(arg);
}
EXPORT char*
callStringCallback(char* (*func)(char* arg), char* arg) {
return (*func)(arg);
}
EXPORT wchar_t*
callWideStringCallback(wchar_t* (*func)(wchar_t* arg), wchar_t* arg) {
return (*func)(arg);
}
struct cbstruct {
void (*func)();
};
+19
Ver Arquivo
@@ -1,3 +1,22 @@
Release 2.5
Features
* Unions
* Optimized shaped windows (chris deckers & olivier chafik); instantiation time
improved by about 2-3 orders of magnitude for large, mostly contiguous shapes
* Provide type mapping in callback arguments/results
* Provide access to ByteBuffer direct address as a Pointer
* Provide customization of native string encoding with jna.encoding system property
Bug Fixes
* Properly handle VMs with reversed Structure member storage
* Avoid making window undecorated when clearing window mask on X11
* Fix structure alignment bug on OSX/PPC when first element is > 4 bytes in size
* Clearing OSX window mask by setting to MASK_NONE now works properly
* Avoid index exceptions if native buffers are not NUL-terminated on string conversions
* Write initialized Structure[] argument memory prior to function calls
* Fix IllegalArgumentException reading WString into a Structure
* Clear memory when allocating a structure block (fixes VM crash)
Release 2.4
Features
* Explicitly support unaligned structures
+3 -1
Ver Arquivo
@@ -19,7 +19,9 @@ package com.sun.jna;
* a callback which has been GC'd, you will likely crash the VM. If
* there is no method to deregister the callback (e.g. <code>atexit</code>
* in the C library), you must ensure that you always keep a live reference
* to the callback object.
* to the callback object.<p>
* A callback should generally never throw an exception, since it doesn't
* necessarily have an encompassing Java environment to catch it.
*/
public interface Callback {
String METHOD_NAME = "callback";
@@ -0,0 +1,28 @@
/* Copyright (c) 2007 Timothy Wall, All Rights Reserved
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package com.sun.jna;
import java.lang.reflect.Method;
/** Provide argument conversion context for a callback. */
public class CallbackInvocationContext extends FromNativeContext {
private Method method;
private Object[] args;
public CallbackInvocationContext(Class javaType, Method m, Object[] args) {
super(javaType);
this.method = m;
this.args = args;
}
public Method getMethod() { return method; }
public Object[] getArguments() { return args; }
}
@@ -4,17 +4,21 @@
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* <p/>
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package com.sun.jna;
/** Define conversion from a Java type to its corresponding native type. */
public interface ArgumentConverter {
/** Convert a Java type to an appropriate native type. */
public Object toNative(Object value);
}
/** Placeholder proxy interface to allow an InvocationHandler to convert
* arguments/return values on callback methods. This is a special sub-interface
* of {@link Callback} which expects its arguments in a single Object array
* passed to its {@link #callback} method.
*/
public interface CallbackProxy extends Callback {
Object callback(Object[] args);
Class[] getParameterTypes();
Class getReturnType();
}
+257 -26
Ver Arquivo
@@ -13,6 +13,7 @@
package com.sun.jna;
import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.WeakHashMap;
@@ -21,31 +22,11 @@ import java.util.WeakHashMap;
* and a Java {@link Callback} closure.
*/
public class CallbackReference extends WeakReference {
class CallbackReference extends WeakReference {
static final Map callbackMap = new WeakHashMap();
static final Map altCallbackMap = new WeakHashMap();
private static Pointer createCallback(Callback callback, int callingConvention) {
Method[] mlist = callback.getClass().getMethods();
for (int i=0;i < mlist.length;i++) {
if (Callback.METHOD_NAME.equals(mlist[i].getName())) {
Method m = mlist[i];
Class[] paramTypes = m.getParameterTypes();
Class rtype = m.getReturnType();
if (paramTypes.length > Function.MAX_NARGS) {
String msg = "Method signature exceeds the maximum "
+ "parameter count: " + m;
throw new IllegalArgumentException(msg);
}
return Function.createCallback(callback, m, paramTypes, rtype, callingConvention);
}
}
String msg = "Callback must implement method named '"
+ Callback.METHOD_NAME + "'";
throw new IllegalArgumentException(msg);
}
/** Return a CallbackReference associated with the given callback, using
* the calling convention appropriate to the given callback.
*/
@@ -64,24 +45,274 @@ public class CallbackReference extends WeakReference {
synchronized(map) {
CallbackReference cbref = (CallbackReference)map.get(callback);
if (cbref == null) {
Pointer cbstruct = createCallback(callback, callingConvention);
cbref = new CallbackReference(callback, cbstruct);
cbref = new CallbackReference(callback, callingConvention);
map.put(callback, cbref);
}
return cbref;
}
}
Pointer cbstruct;
public CallbackReference(Callback callback, Pointer cbstruct) {
// Keep a reference to avoid premature GC
CallbackProxy proxy;
private CallbackReference(Callback callback, int callingConvention) {
super(callback);
this.cbstruct = cbstruct;
Class type = callback.getClass();
Class[] ifaces = type.getInterfaces();
for (int i=0;i < ifaces.length;i++) {
if (Callback.class.isAssignableFrom(ifaces[i])) {
type = ifaces[i];
break;
}
}
TypeMapper mapper = null;
Class declaring = type.getDeclaringClass();
if (declaring != null) {
mapper = Native.getTypeMapper(declaring);
}
Method m = getCallbackMethod(callback);
proxy = new DefaultCallbackProxy(m, mapper);
// Generate a list of parameter types that the native code can
// handle. Let the CallbackProxy to do any further conversion
// to match the true callback signature
Class[] nativeParamTypes = proxy.getParameterTypes();
if (mapper != null) {
for (int i=0;i < nativeParamTypes.length;i++) {
FromNativeConverter rc = mapper.getFromNativeConverter(nativeParamTypes[i]);
if (rc != null) {
nativeParamTypes[i] = rc.nativeType();
}
}
}
for (int i=0;i < nativeParamTypes.length;i++) {
Class cls = nativeParamTypes[i];
if (Structure.class.isAssignableFrom(cls)) {
// Make sure we can instantiate an argument of this type
try {
cls.newInstance();
}
catch (InstantiationException e) {
throw new IllegalArgumentException("Can't instantiate " + cls + ": " + e);
}
catch (IllegalAccessException e) {
throw new IllegalArgumentException("Instantiation of " + cls
+ " not allowed (is it public?): " + e);
}
nativeParamTypes[i] = Pointer.class;
}
else if (NativeLong.class.isAssignableFrom(cls)) {
nativeParamTypes[i] = NativeLong.SIZE == 4 ? Integer.class : Long.class;
}
else if (cls == String.class || cls == WString.class) {
nativeParamTypes[i] = Pointer.class;
}
else if (!isAllowableNativeType(cls)) {
throw new IllegalArgumentException("Callback argument " + cls + " requires custom type conversion");
}
}
try {
Method proxyMethod =
CallbackProxy.class.getMethod("callback", new Class[] { Object[].class });
cbstruct = createCallback(proxy, proxyMethod,
nativeParamTypes, callingConvention);
}
catch (NoSuchMethodException e) {
throw new Error("Unexpectedly missing CallbackProxy.callback(Object[])");
}
}
private Method getCallbackMethod(Callback callback) {
Method[] mlist = callback.getClass().getMethods();
for (int mi=0;mi < mlist.length;mi++) {
Method m = mlist[mi];
if (Callback.METHOD_NAME.equals(m.getName())) {
if (m.getParameterTypes().length > Function.MAX_NARGS) {
String msg = "Method signature exceeds the maximum "
+ "parameter count: " + m;
throw new IllegalArgumentException(msg);
}
return m;
}
}
String msg = "Callback must implement method named '"
+ Callback.METHOD_NAME + "'";
throw new IllegalArgumentException(msg);
}
public Pointer getTrampoline() {
return cbstruct.getPointer(0);
}
protected void finalize() {
Function.freeCallback(cbstruct.peer);
freeCallback(cbstruct.peer);
cbstruct.peer = 0;
}
private Callback getCallback() {
return (Callback)get();
}
private class DefaultCallbackProxy implements CallbackProxy {
private Method callbackMethod;
private ToNativeConverter toNative;
private FromNativeConverter[] fromNative;
public DefaultCallbackProxy(Method callbackMethod, TypeMapper mapper) {
this.callbackMethod = callbackMethod;
Class[] argTypes = callbackMethod.getParameterTypes();
fromNative = new FromNativeConverter[argTypes.length];
if (mapper != null) {
toNative = mapper.getToNativeConverter(callbackMethod.getReturnType());
for (int i=0;i < fromNative.length;i++) {
fromNative[i] = mapper.getFromNativeConverter(argTypes[i]);
}
}
if (!callbackMethod.isAccessible()) {
try {
callbackMethod.setAccessible(true);
}
catch(SecurityException e) {
throw new IllegalArgumentException("Callback method is inaccessible, make sure the interface is public: " + callbackMethod);
}
}
}
/** Called from native code. All arguments are in an array of
* Object as the first argument. Converts all arguments to types
* required by the actual callback method signature, and converts
* the result back into an appropriate native type.
* This method <em>must not</em> throw exceptions.
*/
public Object callback(Object[] args) {
Class[] paramTypes = callbackMethod.getParameterTypes();
Object[] callbackArgs = new Object[args.length];
// convert basic supported types to appropriate Java parameter types
for (int i=0;i < args.length;i++) {
if (fromNative[i] != null) {
FromNativeContext context =
new CallbackInvocationContext(paramTypes[i], callbackMethod, args);
args[i] = fromNative[i].fromNative(args[i], context);
}
callbackArgs[i] = convertArgument(args[i], paramTypes[i]);
}
Object result = null;
Callback cb = getCallback();
if (cb != null) {
try {
result = convertResult(callbackMethod.invoke(cb, callbackArgs));
}
catch (IllegalArgumentException e) {
e.printStackTrace();
}
catch (IllegalAccessException e) {
e.printStackTrace();
}
catch (InvocationTargetException e) {
e.printStackTrace();
}
}
return result;
}
/** Convert argument from its basic native type to the given
* Java parameter type.
*/
private Object convertArgument(Object value, Class dstType) {
if (value instanceof Pointer) {
if (dstType == String.class) {
value = ((Pointer)value).getString(0);
}
else if (dstType == WString.class) {
value = new WString(((Pointer)value).getString(0, true));
}
else if (Structure.class.isAssignableFrom(dstType)) {
Pointer p = (Pointer)value;
try {
Structure s = (Structure)dstType.newInstance();
s.useMemory(p);
s.read();
value = s;
}
catch(InstantiationException e) {
// can't happen, already checked for
}
catch(IllegalAccessException e) {
// can't happen, already checked for
}
}
}
else if (NativeLong.class.isAssignableFrom(dstType)
&& (value instanceof Integer || value instanceof Long)) {
value = new NativeLong(NativeLong.SIZE == 4
? ((Integer)value).intValue()
: ((Long)value).longValue());
}
else if ((boolean.class == dstType || Boolean.class == dstType)
&& value instanceof Number) {
value = Boolean.valueOf(((Number)value).intValue() != 0);
}
return value;
}
private Object convertResult(Object value) {
if (toNative != null) {
value = toNative.toNative(value);
}
if (value == null)
return null;
Class cls = value.getClass();
if (Structure.class.isAssignableFrom(cls)) {
return ((Structure)value).getPointer();
}
else if (NativeLong.class.isAssignableFrom(cls)) {
return ((NativeLong)value).asNativeValue();
}
else if (cls == boolean.class || cls == Boolean.class) {
return new Integer(Boolean.TRUE.equals(value)?-1:0);
}
else if (cls == String.class) {
// FIXME: need to prevent GC, but how and for how long?
return new NativeString(value.toString()).getPointer();
}
else if (cls == WString.class) {
// FIXME: need to prevent GC, but how and for how long?
return new NativeString(value.toString(), true).getPointer();
}
else if (!isAllowableNativeType(cls)) {
throw new IllegalArgumentException("Return type " + cls + " will be ignored");
}
return value;
}
public Class[] getParameterTypes() {
return callbackMethod.getParameterTypes();
}
public Class getReturnType() {
return callbackMethod.getReturnType();
}
}
/** Returns whether the given class is supported in native code.
* Other types (String, WString, Structure, arrays, NativeLong,
* etc) are supported in the Java library.
*/
static boolean isAllowableNativeType(Class cls) {
return cls == boolean.class || cls == Boolean.class
|| cls == byte.class || cls == Byte.class
|| cls == short.class || cls == Short.class
|| cls == char.class || cls == Character.class
|| cls == int.class || cls == Integer.class
|| cls == long.class || cls == Long.class
|| cls == float.class || cls == Float.class
|| cls == double.class || cls == Double.class
|| Pointer.class.isAssignableFrom(cls);
}
/** Create a callback function pointer. */
private static native Pointer createCallback(CallbackProxy callback,
Method method,
Class[] parameterTypes,
int callingConvention);
/** Free the given callback function pointer. */
private static native void freeCallback(long ptr);
}
+41 -27
Ver Arquivo
@@ -13,27 +13,35 @@
package com.sun.jna;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.List;
/** Provide custom mappings to and from native types. The default lookup
* checks classes corresponding to converters in the order added; if the
* class to be converted is an instance of the converter's registered class,
* the converter will be used.<p>
* Derived classes should install additional converters using
* {@link #addArgumentConverter}
* and/or {@link #addResultConverter} in the default constructor. Classes
* {@link #addToNativeConverter}
* and/or {@link #addFromNativeConverter} in the default constructor. Classes
* for primitive types will automatically register for the corresponding
* Object type and vice versa (i.e. you don't have to register both
* <code>int.class</code> and <code>Integer.class</code>).
* If you want different mapping behavior than the default, simply override
* {@link #getArgumentConverter} and {@link #getResultConverter}.
* {@link #getToNativeConverter} and {@link #getFromNativeConverter}.
* @see Library#OPTION_TYPE_MAPPER
*/
public class DefaultTypeMapper implements TypeMapper {
private Map argumentConverters = new LinkedHashMap();
private Map resultConverters = new LinkedHashMap();
private static class Entry {
public Class type;
public Object converter;
public Entry(Class type, Object converter) {
this.type = type;
this.converter = converter;
}
}
private List toNativeConverters = new ArrayList();
private List fromNativeConverters = new ArrayList();
private Class getAltClass(Class cls) {
if (cls == Boolean.class) {
return boolean.class;
@@ -85,48 +93,54 @@ public class DefaultTypeMapper implements TypeMapper {
}
return null;
}
/** Add a {@link ArgumentConverter} to define the conversion into a native
/** Add a {@link ToNativeConverter} to define the conversion into a native
* type from arguments of the given Java type. Converters are
* checked for in the order added.
*/
protected void addArgumentConverter(Class cls, ArgumentConverter converter) {
argumentConverters.put(cls, converter);
public void addToNativeConverter(Class cls, ToNativeConverter converter) {
toNativeConverters.add(new Entry(cls, converter));
Class alt = getAltClass(cls);
if (alt != null) {
argumentConverters.put(alt, converter);
toNativeConverters.add(new Entry(alt, converter));
}
}
/** Add a {@link ResultConverter} to convert a native result type into the
/** Add a {@link FromNativeConverter} to convert a native result type into the
* given Java type. Converters are checked for in the order added.
*/
protected void addResultConverter(Class cls, ResultConverter converter) {
resultConverters.put(cls, converter);
public void addFromNativeConverter(Class cls, FromNativeConverter converter) {
fromNativeConverters.add(new Entry(cls, converter));
Class alt = getAltClass(cls);
if (alt != null) {
resultConverters.put(alt, converter);
fromNativeConverters.add(new Entry(alt, converter));
}
}
/** Add a {@link TypeConverter} to provide bidirectional mapping between
* a native and Java type.
*/
protected void addTypeConverter(Class cls, TypeConverter converter) {
addFromNativeConverter(cls, converter);
addToNativeConverter(cls, converter);
}
private Object lookupConverter(Class javaClass, Map map) {
for (Iterator i=map.entrySet().iterator();i.hasNext();) {
Map.Entry entry = (Map.Entry)i.next();
Class cls = (Class)entry.getKey();
if (cls.isAssignableFrom(javaClass)) {
return entry.getValue();
private Object lookupConverter(Class javaClass, List converters) {
for (Iterator i=converters.iterator();i.hasNext();) {
Entry entry = (Entry)i.next();
if (entry.type.isAssignableFrom(javaClass)) {
return entry.converter;
}
}
return null;
}
/* (non-Javadoc)
* @see com.sun.jna.TypeMapper#getResultConverter(java.lang.Class)
* @see com.sun.jna.TypeMapper#getFromNativeConverter(java.lang.Class)
*/
public ResultConverter getResultConverter(Class javaType) {
return (ResultConverter)lookupConverter(javaType, resultConverters);
public FromNativeConverter getFromNativeConverter(Class javaType) {
return (FromNativeConverter)lookupConverter(javaType, fromNativeConverters);
}
/* (non-Javadoc)
* @see com.sun.jna.TypeMapper#getArgumentConverter(java.lang.Class)
* @see com.sun.jna.TypeMapper#getToNativeConverter(java.lang.Class)
*/
public ArgumentConverter getArgumentConverter(Class javaType) {
return (ArgumentConverter)lookupConverter(javaType, argumentConverters);
public ToNativeConverter getToNativeConverter(Class javaType) {
return (ToNativeConverter)lookupConverter(javaType, toNativeConverters);
}
}
@@ -13,13 +13,13 @@
package com.sun.jna;
/** Provides context for converting a native value into a Java type. */
public class ResultContext {
public class FromNativeContext {
private Class type;
public ResultContext(Class javaType) {
public FromNativeContext(Class javaType) {
this.type = javaType;
}
/** The desired Java type of the result. */
public Class getType() {
public Class getTargetType() {
return type;
}
}
@@ -14,11 +14,11 @@
package com.sun.jna;
/** Define conversion from a native type to the appropriate Java type. */
public interface ResultConverter {
public interface FromNativeConverter {
/** Convert the given native object into its Java representation using
* the given context.
*/
public Object fromNative(Object value, ResultContext context);
public Object fromNative(Object value, FromNativeContext context);
/** Indicate the native type used by this converter. */
public Class nativeType();
}
+300 -226
Ver Arquivo
@@ -10,17 +10,12 @@
*/
package com.sun.jna;
import java.io.File;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.List;
import java.util.ArrayList;
import com.sun.jna.ptr.ByReference;
/**
@@ -148,29 +143,12 @@ public class Function extends Pointer {
* native result as an Object.
*/
public Object invoke(Class returnType, Object[] inArgs, Map options) {
Object result = null;
// If the final argument is an array of Object, treat it as
// varargs and concatenate the previous arguments with the varargs
// elements.
if (inArgs != null && inArgs.length > 0) {
Object lastArg = inArgs[inArgs.length-1];
if (lastArg != null && Object[].class == lastArg.getClass()) {
Object[] varArgs = (Object[])lastArg;
Object[] fullArgs = new Object[inArgs.length+varArgs.length];
System.arraycopy(inArgs, 0, fullArgs, 0, inArgs.length-1);
System.arraycopy(varArgs, 0, fullArgs, inArgs.length-1, varArgs.length);
// For convenience, always append a NULL argument to the end
// of varargs, whether the called API requires it or not. If
// it is not needed, it will be ignored, but if it *is*
// required, it avoids forcing the Java client to always
// explicitly add it.
fullArgs[fullArgs.length-1] = null;
inArgs = fullArgs;
}
}
// Make sure all args are in a single array
inArgs = concatenateVarArgs(inArgs);
// Clone the argument array
// Clone the argument array to obtain a scratch space for modified
// types/values
Object[] args = { };
if (inArgs != null) {
if (inArgs.length > MAX_NARGS) {
@@ -184,199 +162,26 @@ public class Function extends Pointer {
(TypeMapper)options.get(Library.OPTION_TYPE_MAPPER);
for (int i=0; i < args.length; i++) {
Object arg = args[i];
if (arg != null && mapper != null) {
ArgumentConverter converter = mapper.getArgumentConverter(arg.getClass());
if (converter != null) {
args[i] = arg = converter.toNative(arg);
}
}
// Convert Structures to native pointers
if (arg == null || isPrimitiveArray(arg.getClass())) {
continue;
}
Class argClass = arg.getClass();
if (arg instanceof Structure) {
Structure struct = (Structure)arg;
struct.write();
args[i] = struct.getPointer();
}
// Convert reference class to pointer
else if (arg instanceof ByReference) {
args[i] = ((ByReference)arg).getPointer();
}
// Convert Callback to Pointer
else if (arg instanceof Callback) {
CallbackReference cbref = CallbackReference.getInstance((Callback)arg, callingConvention);
// Use pointer to trampoline (callback->insns, see dispatch.h)
args[i] = cbref.getTrampoline();
}
// String arguments are converted to native pointers here rather
// than in native code so that the values will be valid until
// this method returns. At one point the conversion was in native
// code, which left the pointer values invalid before this method
// returned (so you couldn't do something like strstr).
// Convert String to native pointer (const)
else if (arg instanceof String) {
args[i] = new NativeString((String)arg, false).getPointer();
}
// Convert WString to native pointer (const)
else if (arg instanceof WString) {
args[i] = new NativeString(arg.toString(), true).getPointer();
}
else if (arg instanceof NativeLong) {
args[i] = ((NativeLong)arg).asNativeValue();
}
// Default conversion of boolean to int; if you want something
// different, use an ArgumentConverter
else if (arg instanceof Boolean) {
args[i] = new Integer(Boolean.TRUE.equals(arg) ? -1 : 0);
}
else if (String[].class.equals(argClass)) {
args[i] = new StringArray((String[])arg);
}
else if (isStructureArray(argClass)) {
// Initialize uninitialized arrays of Structure to point
// to a single block of memory
Structure[] ss = (Structure[])arg;
if (ss.length == 0) {
args[i] = null;
}
else if (ss[0] == null) {
Class type = argClass.getComponentType();
try {
Structure struct = (Structure)type.newInstance();
int size = struct.size();
Memory m = new Memory(size * ss.length);
struct.useMemory(m);
Structure[] tmp = struct.toArray(ss.length);
for (int si=0;si < ss.length;si++) {
ss[si] = tmp[si];
}
}
catch(InstantiationException e) {
throw new IllegalArgumentException("Instantiation of "
+ type + " failed: "
+ e);
}
catch(IllegalAccessException e) {
throw new IllegalArgumentException("Not allowed to instantiate "
+ type + ": " + e);
}
args[i] = ss[0].getPointer();
}
else {
Pointer base = ss[0].getPointer();
int size = ss[0].size();
for (int si=1;si < ss.length;si++) {
try {
Pointer p = base.share(size*si, size);
if (ss[si].getPointer().peer != p.peer) {
throw new RuntimeException();
}
}
catch(RuntimeException e) {
String msg = "Structure array elements must use"
+ " contiguous memory: " + si;
throw new IllegalArgumentException(msg);
}
}
args[i] = base;
}
}
else if (arg instanceof ByteBuffer && !((ByteBuffer)arg).isDirect()) {
ByteBuffer buf = (ByteBuffer)arg;
if (buf.hasArray()) {
args[i] = buf.array();
}
else {
throw new IllegalArgumentException("Unsupported non-direct ByteBuffer with no array");
}
}
else if (argClass.isArray()){
throw new IllegalArgumentException("Unsupported array argument type: "
+ argClass.getComponentType());
}
args[i] = convertArgument(args[i], mapper);
}
Class nativeType = returnType;
ResultConverter resultConverter = null;
FromNativeConverter resultConverter = null;
if (mapper != null) {
resultConverter = mapper.getResultConverter(returnType);
resultConverter = mapper.getFromNativeConverter(returnType);
if (resultConverter != null) {
nativeType = resultConverter.nativeType();
}
}
if (nativeType == null || nativeType==void.class || nativeType==Void.class) {
invokeVoid(callingConvention, args);
}
else if (nativeType==boolean.class || nativeType==Boolean.class) {
result = new Boolean(invokeInt(callingConvention, args) != 0);
}
else if (nativeType==byte.class || nativeType==Byte.class) {
result = new Byte((byte)invokeInt(callingConvention, args));
}
else if (nativeType==short.class || nativeType==Short.class) {
result = new Short((short)invokeInt(callingConvention, args));
}
else if (nativeType==int.class || nativeType==Integer.class) {
result = new Integer(invokeInt(callingConvention, args));
}
else if (nativeType==long.class || nativeType==Long.class) {
result = new Long(invokeLong(callingConvention, args));
}
else if (nativeType==NativeLong.class) {
result = new NativeLong(NativeLong.SIZE == 8
? invokeLong(callingConvention, args)
: invokeInt(callingConvention, args));
}
else if (nativeType==float.class || nativeType==Float.class) {
result = new Float(invokeFloat(callingConvention, args));
}
else if (nativeType==double.class || nativeType==Double.class) {
result = new Double(invokeDouble(callingConvention, args));
}
else if (nativeType==String.class) {
result = invokeString(args, false);
}
else if (nativeType==WString.class) {
result = new WString(invokeString(args, true));
}
else if (Pointer.class.isAssignableFrom(nativeType)) {
result = invokePointer(callingConvention, args);
}
else if (Structure.class.isAssignableFrom(nativeType)) {
result = invokePointer(callingConvention, args);
if (result != null) {
try {
Structure s = (Structure)nativeType.newInstance();
s.useMemory((Pointer)result);
s.read();
result = s;
}
catch(InstantiationException e) {
throw new IllegalArgumentException("Instantiation of "
+ nativeType + " failed: "
+ e);
}
catch(IllegalAccessException e) {
throw new IllegalArgumentException("Not allowed to instantiate "
+ nativeType + ": " + e);
}
}
}
else {
throw new IllegalArgumentException("Unsupported return type "
+ nativeType);
}
Object result = invoke(args, nativeType);
// Convert the result to a custom value/type if appropriate
if (resultConverter != null) {
ResultContext context = new FunctionResultContext(returnType, this, inArgs);
FromNativeContext context = new FunctionResultContext(returnType, this, inArgs);
result = resultConverter.fromNative(result, context);
}
// Sync java fields in structures to native memory after invocation
// Sync all memory which might have been modified by the native call
if (inArgs != null) {
for (int i=0; i < inArgs.length; i++) {
Object arg = inArgs[i];
@@ -391,7 +196,7 @@ public class Function extends Pointer {
StringArray buf = (StringArray)args[i];
String[] array = (String[])arg;
for (int si=0;si < array.length;si++) {
array[si] = buf.getPointer(si * Pointer.SIZE).getString(0, false);
array[si] = buf.getPointer(si * Pointer.SIZE).getString(0);
}
}
else if (isStructureArray(arg.getClass())) {
@@ -406,6 +211,219 @@ public class Function extends Pointer {
return result;
}
/** Concatenate varargs with normal args to obtain a simple argument array.
*/
private Object[] concatenateVarArgs(Object[] inArgs) {
// If the final argument is an array of something other than
// primitives, Structure, or String, treat it as varargs and
// concatenate the previous arguments with the varargs elements.
if (inArgs != null && inArgs.length > 0) {
Object lastArg = inArgs[inArgs.length-1];
Class argType = lastArg != null ? lastArg.getClass() : null;
if (argType != null && argType.isArray()
&& !isPrimitiveArray(argType)
&& !isStructureArray(argType)
&& argType != String[].class) {
Object[] varArgs = (Object[])lastArg;
Object[] fullArgs = new Object[inArgs.length+varArgs.length];
System.arraycopy(inArgs, 0, fullArgs, 0, inArgs.length-1);
System.arraycopy(varArgs, 0, fullArgs, inArgs.length-1, varArgs.length);
// For convenience, always append a NULL argument to the end
// of varargs, whether the called API requires it or not. If
// it is not needed, it will be ignored, but if it *is*
// required, it avoids forcing the Java client to always
// explicitly add it.
fullArgs[fullArgs.length-1] = null;
inArgs = fullArgs;
}
}
return inArgs;
}
private Object invoke(Object[] args, Class returnType) {
if (returnType == null || returnType==void.class || returnType==Void.class) {
invokeVoid(callingConvention, args);
return null;
}
else if (returnType==boolean.class || returnType==Boolean.class) {
return new Boolean(invokeInt(callingConvention, args) != 0);
}
else if (returnType==byte.class || returnType==Byte.class) {
return new Byte((byte)invokeInt(callingConvention, args));
}
else if (returnType==short.class || returnType==Short.class) {
return new Short((short)invokeInt(callingConvention, args));
}
else if (returnType==char.class || returnType==Character.class) {
return new Character((char)invokeInt(callingConvention, args));
}
else if (returnType==int.class || returnType==Integer.class) {
return new Integer(invokeInt(callingConvention, args));
}
else if (returnType==long.class || returnType==Long.class) {
return new Long(invokeLong(callingConvention, args));
}
else if (returnType==NativeLong.class) {
return new NativeLong(NativeLong.SIZE == 8
? invokeLong(callingConvention, args)
: invokeInt(callingConvention, args));
}
else if (returnType==float.class || returnType==Float.class) {
return new Float(invokeFloat(callingConvention, args));
}
else if (returnType==double.class || returnType==Double.class) {
return new Double(invokeDouble(callingConvention, args));
}
else if (returnType==String.class) {
return invokeString(callingConvention, args, false);
}
else if (returnType==WString.class) {
return new WString(invokeString(callingConvention, args, true));
}
else if (Pointer.class.isAssignableFrom(returnType)) {
return invokePointer(callingConvention, args);
}
else if (Structure.class.isAssignableFrom(returnType)) {
Object result = invokePointer(callingConvention, args);
if (result != null) {
try {
Structure s = (Structure)returnType.newInstance();
s.useMemory((Pointer)result);
s.read();
result = s;
}
catch(InstantiationException e) {
throw new IllegalArgumentException("Instantiation of "
+ returnType + " failed: "
+ e);
}
catch(IllegalAccessException e) {
throw new IllegalArgumentException("Not allowed to instantiate "
+ returnType + ": " + e);
}
}
return result;
}
throw new IllegalArgumentException("Unsupported return type "
+ returnType);
}
private Object convertArgument(Object arg, TypeMapper mapper) {
if (arg != null && mapper != null) {
ToNativeConverter converter = mapper.getToNativeConverter(arg.getClass());
if (converter != null) {
arg = converter.toNative(arg);
}
}
if (arg == null || isPrimitiveArray(arg.getClass())) {
return arg;
}
Class argClass = arg.getClass();
// Convert Structures to native pointers
if (arg instanceof Structure) {
Structure struct = (Structure)arg;
struct.write();
return struct.getPointer();
}
// Convert reference class to pointer
else if (arg instanceof ByReference) {
return ((ByReference)arg).getPointer();
}
// Convert Callback to Pointer
else if (arg instanceof Callback) {
CallbackReference cbref = CallbackReference.getInstance((Callback)arg);
// Use pointer to trampoline (callback->insns, see dispatch.h)
return cbref.getTrampoline();
}
// String arguments are converted to native pointers here rather
// than in native code so that the values will be valid until
// this method returns. At one point the conversion was in native
// code, which left the pointer values invalid before this method
// returned (so you couldn't do something like strstr).
// Convert String to native pointer (const)
else if (arg instanceof String) {
return new NativeString((String)arg, false).getPointer();
}
// Convert WString to native pointer (const)
else if (arg instanceof WString) {
return new NativeString(arg.toString(), true).getPointer();
}
else if (arg instanceof NativeLong) {
return ((NativeLong)arg).asNativeValue();
}
// Default conversion of boolean to int; if you want something
// different, use a ToNativeConverter
else if (arg instanceof Boolean) {
return new Integer(Boolean.TRUE.equals(arg) ? -1 : 0);
}
else if (String[].class == argClass) {
return new StringArray((String[])arg);
}
else if (isStructureArray(argClass)) {
// Initialize uninitialized arrays of Structure to point
// to a single block of memory
Structure[] ss = (Structure[])arg;
if (ss.length == 0) {
return null;
}
else if (ss[0] == null) {
Class type = argClass.getComponentType();
try {
Structure struct = (Structure)type.newInstance();
int size = struct.size();
Memory m = new Memory(size * ss.length);
struct.useMemory(m);
Structure[] tmp = struct.toArray(ss.length);
for (int si=0;si < ss.length;si++) {
ss[si] = tmp[si];
}
}
catch(InstantiationException e) {
throw new IllegalArgumentException("Instantiation of "
+ type + " failed: "
+ e);
}
catch(IllegalAccessException e) {
throw new IllegalArgumentException("Not allowed to instantiate "
+ type + ": " + e);
}
return ss[0].getPointer();
}
else {
Pointer base = ss[0].getPointer();
int size = ss[0].size();
ss[0].write();
for (int si=1;si < ss.length;si++) {
try {
Pointer p = base.share(size*si, size);
if (ss[si].getPointer().peer != p.peer) {
throw new RuntimeException();
}
ss[si].write();
}
catch(RuntimeException e) {
String msg = "Structure array elements must use"
+ " contiguous memory: " + si;
throw new IllegalArgumentException(msg);
}
}
return base;
}
}
else if (arg instanceof ByteBuffer && !((ByteBuffer)arg).isDirect()) {
ByteBuffer buf = (ByteBuffer)arg;
if (buf.hasArray()) {
return buf.array();
}
throw new IllegalArgumentException("Unsupported non-direct ByteBuffer with no array");
}
else if (argClass.isArray()){
throw new IllegalArgumentException("Unsupported array argument type: "
+ argClass.getComponentType());
}
return arg;
}
private boolean isStructureArray(Class argClass) {
return argClass.isArray()
&& Structure.class.isAssignableFrom(argClass.getComponentType());
@@ -420,20 +438,22 @@ public class Function extends Pointer {
/**
* Call the native function being represented by this object
*
* @param callingConvention calling convention to be used
* @param args
* Arguments to pass to the native function
* @return The value returned by the target native function
*/
public native int invokeInt(int callingConvention, Object[] args);
private native int invokeInt(int callingConvention, Object[] args);
/**
* Call the native function being represented by this object
*
* @param callingConvention calling convention to be used
* @param args
* Arguments to pass to the native function
* @return The value returned by the target native function
*/
public native long invokeLong(int callingConvention, Object[] args);
private native long invokeLong(int callingConvention, Object[] args);
/**
* Call the native function being represented by this object
@@ -449,41 +469,50 @@ public class Function extends Pointer {
/**
* Call the native function being represented by this object
*
* @param callingConvention calling convention to be used
* @param args
* Arguments to pass to the native function
*/
public native void invokeVoid(int callingConvention, Object[] args);
private native void invokeVoid(int callingConvention, Object[] args);
/**
* Call the native function being represented by this object
*
* @param callingConvention calling convention to be used
* @param args
* Arguments to pass to the native function
* @return The value returned by the target native function
*/
public native float invokeFloat(int callingConvention, Object[] args);
private native float invokeFloat(int callingConvention, Object[] args);
/**
* Call the native function being represented by this object
*
* @param callingConvention calling convention to be used
* @param args
* Arguments to pass to the native function
* @return The value returned by the target native function
*/
public native double invokeDouble(int callingConvention, Object[] args);
private native double invokeDouble(int callingConvention, Object[] args);
/**
* Call the native function being represented by this object
*
* @param callingConvention calling convention to be used
* @param args
* Arguments to pass to the native function
* @return The value returned by the target native function
* @param wide whether the native string uses <code>wchar_t</code>;
* if false, <code>char</code> is assumed
* @return The value returned by the target native function, as a String
*/
public String invokeString(Object[] args, boolean wide) {
private String invokeString(int callingConvention, Object[] args, boolean wide) {
Pointer ptr = invokePointer(callingConvention, args);
String s = null;
if (ptr != null) {
s = ptr.getString(0, wide);
if (wide)
s = ptr.getString(0, wide);
else
s = ptr.getString(0);
}
return s;
}
@@ -491,20 +520,13 @@ public class Function extends Pointer {
/**
* Call the native function being represented by this object
*
* @param callingConvention calling convention to be used
* @param args
* Arguments to pass to the native function
* @return The native pointer returned by the target native function
*/
public native Pointer invokePointer(int callingConvention, Object[] args);
private native Pointer invokePointer(int callingConvention, Object[] args);
/** Create a callback function pointer. */
static native Pointer createCallback(Callback callback, Method method,
Class[] parameterTypes,
Class returnType,
int callingConvention);
/** Free the given callback function pointer. */
static native void freeCallback(long ptr);
/** Provide a human-readable representation of this object. */
public String toString() {
return "native function " + functionName + "(" + library.getName()
@@ -517,7 +539,7 @@ public class Function extends Pointer {
*/
private class StringArray extends Memory {
private List natives = new ArrayList();
public StringArray(String[] strings) {
public StringArray(String[] strings) {
super((strings.length + 1) * Pointer.SIZE);
for (int i=0;i < strings.length;i++) {
NativeString ns = new NativeString(strings[i]);
@@ -527,4 +549,56 @@ public class Function extends Pointer {
setPointer(Pointer.SIZE * strings.length, null);
}
}
// The following convenience methods are provided for using a Function
// instance directly
/** Convenience method for
* {@link #invoke(Class,Object[]) invoke(Pointer.class, args)}.
*/
public Pointer invokePointer(Object[] args) {
return (Pointer)invoke(Pointer.class, args);
}
/** Convenience method for
* {@link #invoke(Class,Object[]) invoke(String.class, args)}
* or {@link #invoke(Class,Object[]) invoke(WString.class, args)}
* @param args Arguments passed to native function
* @param wide Whether the return value is of type <code>wchar_t*</code>;
* if false, the return value is of type <code>char*</code>.
*/
public String invokeString(Object[] args, boolean wide) {
Object o = invoke(wide ? WString.class : String.class, args);
return o != null ? o.toString() : null;
}
/** Convenience method for
* {@link #invoke(Class,Object[]) invoke(Integer.class, args)}.
*/
public int invokeInt(Object[] args) {
return ((Integer)invoke(Integer.class, args)).intValue();
}
/** Convenience method for
* {@link #invoke(Class,Object[]) invoke(Long.class, args)}.
*/
public long invokeLong(Object[] args) {
return ((Long)invoke(Long.class, args)).longValue();
}
/** Convenience method for
* {@link #invoke(Class,Object[]) invoke(Float.class, args)}.
*/
public float invokeFloat(Object[] args) {
return ((Float)invoke(Float.class, args)).floatValue();
}
/** Convenience method for
* {@link #invoke(Class,Object[]) invoke(Double.class, args)}.
*/
public double invokeDouble(Object[] args) {
return ((Double)invoke(Double.class, args)).doubleValue();
}
/** Convenience method for
* {@link #invoke(Class,Object[]) invoke(Void.class, args)}.
*/
public void invokeVoid(Object[] args) {
invoke(Void.class, args);
}
}
@@ -13,7 +13,7 @@
package com.sun.jna;
/** Provide result conversion context for a function call. */
public class FunctionResultContext extends ResultContext {
public class FunctionResultContext extends FromNativeContext {
private Function function;
private Object[] args;
+1 -5
Ver Arquivo
@@ -10,15 +10,11 @@
*/
package com.sun.jna;
import java.lang.ref.ReferenceQueue;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import com.sun.jna.ptr.ByReference;
/** Derive from this interface for all native library definitions.
*
@@ -58,7 +54,7 @@ public interface Library {
String OPTION_FUNCTION_MAPPER = "function-mapper";
/** Option key for structure alignment type ({@link Integer}). */
String OPTION_STRUCTURE_ALIGNMENT = "structure-alignment";
static class Handler implements InvocationHandler {
private static final Method OBJECT_TOSTRING;
+21 -7
Ver Arquivo
@@ -455,13 +455,11 @@ public class Memory extends Pointer {
* @see Pointer#getString(int, boolean)
*/
public String getString(int offset, boolean wide) {
boundsCheck(offset, 0);
// NOTE: we only make sure the start of the string is within bounds
boundsCheck(offset, 0);
return super.getString(offset, wide);
}
//////////////////////////////////////////////////////////////////////////
// Java type write methods
//////////////////////////////////////////////////////////////////////////
@@ -480,6 +478,20 @@ public class Memory extends Pointer {
}
/**
* Indirect the native pointer to <code>malloc</code> space, a la
* <code>Pointer.setChar</code>. But this method performs a bounds
* checks to ensure that the indirection does not cause memory outside the
* <code>malloc</code>ed space to be accessed.
*
* @see Pointer#setChar
*/
public void setChar(int offset, char value) {
boundsCheck(offset, Pointer.WCHAR_SIZE);
super.setChar(offset, value);
}
/**
* Indirect the native pointer to <code>malloc</code> space, a la
* <code>Pointer.setShort</code>. But this method performs a bounds
@@ -570,14 +582,16 @@ public class Memory extends Pointer {
* bounds checks to ensure that the indirection does not cause memory
* outside the <code>malloc</code>ed space to be accessed.
*
* @see Pointer#setString
* @see Pointer#setString(int,String,boolean)
*/
public void setString(int offset, String value, boolean wide) {
boundsCheck(offset, (value.length() + 1) * (wide ? Pointer.WCHAR_SIZE : 1));
if (wide)
boundsCheck(offset, (value.length() + 1) * Pointer.WCHAR_SIZE);
else
boundsCheck(offset, value.getBytes().length + 1);
super.setString(offset, value, wide);
}
/**
* Call the real native malloc
*/
+43 -6
Ver Arquivo
@@ -13,14 +13,13 @@
package com.sun.jna;
import java.awt.Window;
import java.io.ObjectInputStream.GetField;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
@@ -75,16 +74,38 @@ public class Native {
private static native long getWindowHandle0(Window w);
/** Obtain a Java String from the given native char array. */
/** Convert a direct {@link ByteBuffer} into a {@link Pointer}.
* @throws IllegalArgumentException if the byte buffer is not direct.
*/
public static native Pointer getByteBufferPointer(ByteBuffer b);
/** Obtain a Java String from the given native byte array. If there is
* no NUL terminator, the String will comprise the entire array.
*/
public static String toString(byte[] buf) {
String encoding = System.getProperty("jna.encoding");
if (encoding != null) {
try {
return new String(buf, encoding);
}
catch(UnsupportedEncodingException e) { }
}
String s = new String(buf);
return s.substring(0, s.indexOf(0));
int term = s.indexOf(0);
if (term != -1)
s = s.substring(0, term);
return s;
}
/** Obtain a Java String from the given native wchar_t array. */
/** Obtain a Java String from the given native wchar_t array. If there is
* no NUL terminator, the String will comprise the entire array.
*/
public static String toString(char[] buf) {
String s = new String(buf);
return s.substring(0, s.indexOf(0));
int term = s.indexOf(0);
if (term != -1)
s = s.substring(0, term);
return s;
}
/** Load a library interface from the given shared library, providing
@@ -181,4 +202,20 @@ public class Native {
Integer value = (Integer)alignments.get(interfaceClass);
return value != null ? value.intValue() : Structure.ALIGN_DEFAULT;
}
/** Return an byte array corresponding to the given String. If the
* system property <code>jna.encoding</code> is set, it will override
* the default platform encoding (if supported).
*/
static byte[] getBytes(String s) {
String encoding = System.getProperty("jna.encoding");
if (encoding != null) {
try {
return s.getBytes(encoding);
}
catch (UnsupportedEncodingException e) {
}
}
return s.getBytes();
}
}
+1 -3
Ver Arquivo
@@ -23,7 +23,6 @@ import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.regex.Pattern;
/**
@@ -35,7 +34,6 @@ import java.util.regex.Pattern;
* <ol>
* <li><code>jna.library.path</code> User-customizable path
* <li><code>jna.platform.library.path</code> Platform-specific paths
* <li><code>java.library.path</code> Default Java library search path
* </ol>
* @author Wayne Meissner, split library loading from Function.java
*/
@@ -317,6 +315,7 @@ public class NativeLibrary {
librarySearchPath.addAll(initPaths("jna.library.path"));
if (System.getProperty("jna.platform.library.path") == null) {
// Add default path lookups for unix-like systems
if (new File("/lib").exists()
|| new File("/usr/lib").exists()
|| new File("/lib64").exists()
@@ -329,6 +328,5 @@ public class NativeLibrary {
}
}
librarySearchPath.addAll(initPaths("jna.platform.library.path"));
librarySearchPath.addAll(initPaths("java.library.path"));
}
}
+40 -76
Ver Arquivo
@@ -10,6 +10,7 @@
*/
package com.sun.jna;
/** Provides a temporary allocation of an immutable C string
* (<code>const char*</code> or <code>const wchar_t*</code>) for use when
* converting a Java String into a native memory function argument.
@@ -19,76 +20,62 @@ package com.sun.jna;
*/
class NativeString implements CharSequence, Comparable {
private String value;
private Pointer pointer;
private boolean wide;
protected NativeString(Pointer pointer) {
this(pointer, false);
}
protected NativeString(Pointer pointer, boolean wide) {
this.pointer = pointer;
this.wide = wide;
}
/** Create a native string (NUL-terminated array of <code>char</code>).<p>
* If the system property <code>jna.encoding</code> is set, its value will
* be used to encode the native string. If not set or if the encoding
* is unavailable, the default platform encoding will be used.
*/
public NativeString(String string) {
this(string, false);
}
/** Create a native string as a NUL-terminated array of <code>wchar_t</code>
* (if <code>wide</code> is true) or <code>char</code>.<p>
* If the system property <code>jna.encoding</code> is set, its value will
* be used to encode the native <code>char</code>string.
* If not set or if the encoding is unavailable, the default platform
* encoding will be used.
*
* @param string value to write to native memory
* @param wide whether to store the String as <code>wchar_t</code>
*/
public NativeString(String string, boolean wide) {
this.wide = wide;
this.value = string;
if (string == null) {
pointer = null;
throw new NullPointerException("String must not be null");
}
// Allocate the memory to hold the string. Note, we have to
// make this 1 element longer in order to accomodate the terminating
// NUL (which is generated in Pointer.setString()).
if (wide) {
int len = (string.length() + 1 ) * Pointer.WCHAR_SIZE;
pointer = new Memory(len);
pointer.setString(0, string, true);
}
else {
// Allocate the memory to hold the string. Note, we have to
// make this 1 byte longer in order to accomodate the terminating
// NUL (which is generated in Pointer.setString()).
pointer = new Memory((string.length() + 1) * (wide ? Pointer.WCHAR_SIZE : 1));
pointer.setString(0, string, wide);
byte[] data = Native.getBytes(string);
pointer = new Memory(data.length + 1);
pointer.setString(0, string);
}
}
public boolean isValid() {
return getPointer() != null && getPointer().peer != 0;
}
public int hashCode() {
if (isValid())
return toString().hashCode();
else
return super.hashCode();
return value.hashCode();
}
public boolean equals(Object other) {
if (!isValid())
return false;
String s1 = null;
if (other instanceof NativeString) {
NativeString cs = (NativeString)other;
if (!cs.isValid() || cs.wide != wide)
return false;
else
s1 = cs.toString();
if (other instanceof CharSequence) {
return compareTo(other) == 0;
}
else if (other instanceof String) {
s1 = (String)other;
}
else {
return false;
}
return s1.equals(toString());
return false;
}
public String toString() {
if (!isValid()) {
throw new IllegalStateException("String memory has already been freed");
}
return getPointer().getString(0, wide);
return value;
}
public Pointer getPointer() {
@@ -96,45 +83,22 @@ class NativeString implements CharSequence, Comparable {
}
public char charAt(int index) {
return toString().charAt(index);
return value.charAt(index);
}
public int length() {
return toString().length();
return value.length();
}
public CharSequence subSequence(int start, int end) {
return toString().subSequence(start, end);
return value.subSequence(start, end);
}
public int compareTo(Object other) {
if (!isValid()) {
if (other instanceof NativeString) {
if (!((NativeString)other).isValid())
return 0;
}
else {
return -1;
}
}
if (other == null)
return 1;
String s1=null;
if (other instanceof NativeString) {
if (!((NativeString)other).isValid())
return 1;
else
s1 = ((NativeString)other).toString();
}
else if (other instanceof String) {
s1 = (String)other;
}
else {
s1 = other.toString();
}
return toString().compareTo(s1);
return value.compareTo(other.toString());
}
}
+3 -2
Ver Arquivo
@@ -10,7 +10,8 @@
package com.sun.jna;
/** Provide simplified platform information. */
final class Platform {
public final class Platform {
private static final int UNSPECIFIED = -1;
private static final int MAC = 0;
private static final int LINUX = 1;
private static final int WINDOWS = 2;
@@ -32,7 +33,7 @@ final class Platform {
osType = SOLARIS;
}
else {
osType = ~0;
osType = UNSPECIFIED;
}
}
private Platform() { }
+67 -4
Ver Arquivo
@@ -188,7 +188,7 @@ public class Pointer {
public boolean equals(Object o) {
if (o == null)
return peer == 0;
return o.getClass().equals(Pointer.class) && ((Pointer)o).peer == peer;
return (o instanceof Pointer) && ((Pointer)o).peer == peer;
}
/**
@@ -213,6 +213,11 @@ public class Pointer {
// Raw read methods
//////////////////////////////////////////////////////////////////////////
/** Returns the offset of the given value in memory from the given offset,
* or -1 if the value is not found.
*/
public native int indexOf(int bOff, byte value);
/**
* Indirect the native pointer, copying <em>from</em> memory pointed to by
* native pointer, into the specified array.
@@ -519,7 +524,7 @@ public class Pointer {
/**
* Copy native memory to a Java String. If <code>wide</code> is true,
* access the memory as an array of <code>wchar_t</code>, otherwise
* as an array of <code>char</code>, using the native encoding.
* as an array of <code>char</code>, using the default platform encoding.
*
* @param offset byte offset from pointer to obtain the native string
* @param wide whether to convert from a wide or standard C string
@@ -527,12 +532,37 @@ public class Pointer {
*/
public native String getString(int offset, boolean wide);
/**
* Copy native memory to a Java String. If the system property
* <code>jna.encoding</code> is set, uses it as the native charset
* when decoding the value, otherwise falls back to the default platform
* encoding.
*
* @param offset byte offset from pointer to obtain the native string
* @return the <code>String</code> value being pointed to
*/
public String getString(int offset) {
String encoding = System.getProperty("jna.encoding");
if (encoding != null) {
int len = indexOf(offset, (byte)0);
if (len != -1) {
byte[] data = getByteArray(offset, len);
try {
return new String(data, encoding);
}
catch(UnsupportedEncodingException e) {
}
}
}
return getString(offset, false);
}
public byte[] getByteArray(int offset, int arraySize) {
byte[] buf = new byte[arraySize];
read(offset, buf, 0, arraySize);
return buf;
}
public char[] getCharArray(int offset, int arraySize) {
char[] buf = new char[arraySize];
read(offset, buf, 0, arraySize);
@@ -605,6 +635,18 @@ public class Pointer {
public native void setShort(int offset, short value);
/**
* Set <code>value</code> at location being pointed to. This is equivalent
* to the expression
* <code>*((wchar_t *)((char *)Pointer + offset)) = value</code>.
*
* @param offset byte offset from pointer at which <code>value</code>
* must be set
* @param value <code>char</code> value to set
*/
public native void setChar(int offset, char value);
/**
* Set <code>value</code> at location being pointed to. This is equivalent
* to the expression
@@ -690,10 +732,31 @@ public class Pointer {
*
* @param offset byte offset from pointer at which characters in
* <code>value</code> must be set
* @param value <code>java.lang.String</code> value to set
* @param value <code>java.lang.String</code> value to set
* @param wide whether to write the native string as an array of
* <code>wchar_t</code>. If false, writes as a NUL-terminated array of
* <code>char</code> using the default encoding.
*/
public native void setString(int offset, String value, boolean wide);
/**
* Copy string <code>value</code> to the location being pointed to. Copy
* each element in <code>value</code>, converted to native encoding, at an
* <code>offset</code>from the location pointed to by this pointer.
* Uses the value of the system property <code>jna.encoding</code>, if set,
* to determine the appropriate native charset in which to encode the value.
* If the property is not set, uses the default platform encoding.
*
* @param offset byte offset from pointer at which characters in
* <code>value</code> must be set
* @param value <code>java.lang.String</code> value to set
*/
public void setString(int offset, String value) {
byte[] data = Native.getBytes(value);
write(offset, data, 0, data.length);
setByte(offset + data.length, (byte)0);
}
public String toString() {
return "native@0x" + Long.toHexString(peer);
}
+149 -82
Ver Arquivo
@@ -13,8 +13,6 @@ package com.sun.jna;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.nio.ByteBuffer;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
@@ -25,23 +23,40 @@ import java.util.Map;
* <p>
* See the <a href=overview.html>overview</a> for supported type mappings.
* <p>
* Note: this class
* and its methods are not threadsafe! You must ensure that this class is
* used in a safe manner.<p>
* Note: Strings are used to represent native C strings because usage of
* <code>char *</code> is generally more common than <code>wchar_t *</code>.
* NOTE: Strings are used to represent native C strings because usage of
* <code>char *</code> is generally more common than <code>wchar_t *</code>.<p>
* NOTE: This class assumes that fields are returned in {@link Class#getFields}
* in the same or reverse order as declared. If your VM returns them in
* no particular order, you're out of luck.
*
* @author Todd Fast, todd.fast@sun.com
* @author twall@users.sf.net
*/
public abstract class Structure {
private static class MemberOrder {
public int first;
public int middle;
public int last;
}
private static final boolean REVERSE_FIELDS;
static {
// IBM and JRockit store fields in reverse order; check for it
Field[] fields = MemberOrder.class.getFields();
REVERSE_FIELDS = "last".equals(fields[0].getName());
if (!"middle".equals(fields[1].getName())) {
throw new Error("This VM does not store fields in a predictable order");
}
}
public static final int ALIGN_DEFAULT = 0;
// No alignment, place all fields on nearest 1-byte boundary
/** No alignment, place all fields on nearest 1-byte boundary */
public static final int ALIGN_NONE = 1;
// validated for 32-bit linux/gcc; align on minimum of 32-bits or field size
/** validated for 32-bit x86 linux/gcc; align field size, max 4 bytes */
public static final int ALIGN_GNUC = 2;
// validated for w32/msvc; align on field size boundary
/** validated for w32/msvc; align on field size */
public static final int ALIGN_MSVC = 3;
protected static final int CALCULATE_SIZE = -1;
@@ -64,11 +79,16 @@ public abstract class Structure {
}
protected Structure(int size, int alignment) {
setAlignment(alignment);
setAlignType(alignment);
setTypeMapper(null);
allocateMemory(size);
}
/** Return all fields in this structure (ordered). */
Map fields() {
return structFields;
}
/** Change the type mapping for this structure. May cause the structure
* to be resized and any existing memory to be reallocated.
* If <code>null</code>, the default mapper for the
@@ -81,30 +101,30 @@ public abstract class Structure {
mapper = Native.getTypeMapper(declaring);
}
}
typeMapper = mapper;
size = CALCULATE_SIZE;
memory = null;
this.typeMapper = mapper;
this.size = CALCULATE_SIZE;
this.memory = null;
}
/** Change the alignment of this structure. Re-allocates memory if
* necessary. If alignment is {@link #ALIGN_DEFAULT}, the default
* alignment for the defining class will be used.
*/
protected void setAlignment(int alignment) {
if (alignment == ALIGN_DEFAULT) {
protected void setAlignType(int alignType) {
if (alignType == ALIGN_DEFAULT) {
Class declaring = getClass().getDeclaringClass();
if (declaring != null)
alignment = Native.getStructureAlignment(declaring);
if (alignment == ALIGN_DEFAULT) {
alignType = Native.getStructureAlignment(declaring);
if (alignType == ALIGN_DEFAULT) {
if (Platform.isWindows())
alignment = ALIGN_MSVC;
alignType = ALIGN_MSVC;
else
alignment = ALIGN_GNUC;
alignType = ALIGN_GNUC;
}
}
alignType = alignment;
size = CALCULATE_SIZE;
memory = null;
this.alignType = alignType;
this.size = CALCULATE_SIZE;
this.memory = null;
}
protected void allocateMemory() {
@@ -180,38 +200,36 @@ public abstract class Structure {
public void read() {
// Read all fields
for (Iterator i=structFields.values().iterator();i.hasNext();) {
StructField f = (StructField)i.next();
if (Structure.class.isAssignableFrom(f.type)) {
try {
Structure s = (Structure)f.field.get(this);
s.useMemory(memory, f.offset);
s.read();
}
catch (IllegalAccessException e) {
}
}
else {
readField(f);
}
readField((StructField)i.next());
}
}
private void readField(StructField structField) {
void readField(StructField structField) {
// Get the offset of the field
int offset = structField.offset;
// Determine the type of the field
Class nativeType = structField.type;
ResultConverter resultConverter = structField.readConverter;
if (resultConverter != null) {
nativeType = resultConverter.nativeType();
FromNativeConverter readConverter = structField.readConverter;
if (readConverter != null) {
nativeType = readConverter.nativeType();
}
// Get the value at the offset according to its type
Object result = null;
if (nativeType == byte.class || nativeType == Byte.class) {
if (Structure.class.isAssignableFrom(nativeType)) {
Structure s = null;
try {
s = (Structure)structField.field.get(this);
s.useMemory(memory, offset);
s.read();
}
catch (IllegalAccessException e) {
}
result = s;
}
else if (nativeType == byte.class || nativeType == Byte.class) {
result = new Byte(memory.getByte(offset));
}
else if (nativeType == short.class || nativeType == Short.class) {
@@ -240,16 +258,17 @@ public abstract class Structure {
}
else if (nativeType == String.class) {
Pointer p = memory.getPointer(offset);
result = p != null ? new NativeString(p, false).toString() : null;
result = p != null ? p.getString(0) : null;
}
else if (nativeType == WString.class) {
Pointer p = memory.getPointer(offset);
result = p != null ? new NativeString(p, true).toString() : null;
result = p != null ? new WString(p.getString(0, true)) : null;
}
else if (Callback.class.isAssignableFrom(nativeType)) {
// ignore; Callback members are write-only (don't try to convert
// a native function pointer to a Java Callback)
// TODO: may want to warn if the value is different
// TODO: may want to warn if the value has been changed by
// native code
return;
}
else if (nativeType.isArray()) {
@@ -270,12 +289,12 @@ public abstract class Structure {
if (cls == byte.class) {
result = memory.getByteArray(offset, length);
}
else if (cls == char.class) {
result = memory.getCharArray(offset, length);
}
else if (cls == short.class) {
result = memory.getShortArray(offset, length);
}
else if (cls == char.class) {
result = memory.getCharArray(offset, length);
}
else if (cls == int.class) {
result = memory.getIntArray(offset, length);
}
@@ -298,8 +317,8 @@ public abstract class Structure {
+ nativeType + "\"");
}
if (resultConverter != null) {
result = resultConverter.fromNative(result, structField.context);
if (readConverter != null) {
result = readConverter.fromNative(result, structField.context);
}
// Set the value on the field
@@ -329,7 +348,7 @@ public abstract class Structure {
}
}
private void writeField(Structure.StructField structField) {
void writeField(StructField structField) {
// Get the offset of the field
int offset = structField.offset;
@@ -344,7 +363,7 @@ public abstract class Structure {
}
// Determine the type of the field
Class nativeType = structField.type;
ArgumentConverter converter = structField.writeConverter;
ToNativeConverter converter = structField.writeConverter;
if (converter != null) {
value = converter.toNative(value);
// Assume any null values are pointers
@@ -376,6 +395,9 @@ public abstract class Structure {
else if (nativeType == short.class || nativeType == Short.class) {
memory.setShort(offset, ((Short)value).shortValue());
}
else if (nativeType == char.class || nativeType == Character.class) {
memory.setChar(offset, ((Character)value).charValue());
}
else if (nativeType == int.class || nativeType == Integer.class) {
memory.setInt(offset, ((Integer)value).intValue());
}
@@ -406,14 +428,14 @@ public abstract class Structure {
byte[] buf = (byte[])value;
memory.write(offset, buf, 0, buf.length);
}
else if (cls == char.class) {
char[] buf = (char[])value;
memory.write(offset, buf, 0, buf.length);
}
else if (cls == short.class) {
short[] buf = (short[])value;
memory.write(offset, buf, 0, buf.length);
}
else if (cls == char.class) {
char[] buf = (char[])value;
memory.write(offset, buf, 0, buf.length);
}
else if (cls == int.class) {
int[] buf = (int[])value;
memory.write(offset, buf, 0, buf.length);
@@ -462,7 +484,7 @@ public abstract class Structure {
* determined (usually due to fields in the derived class not yet
* being initialized).
*/
private int calculateSize() {
int calculateSize() {
// TODO: maybe cache this information on a per-class basis
// so that we don't have to re-analyze this static information each
// time a struct is allocated.
@@ -473,6 +495,14 @@ public abstract class Structure {
structAlignment = 1;
int calculatedSize = 0;
Field[] fields = getClass().getFields();
if (REVERSE_FIELDS) {
for (int i=0;i < fields.length/2;i++) {
int idx = fields.length-1-i;
Field tmp = fields[i];
fields[i] = fields[idx];
fields[idx] = tmp;
}
}
for (int i=0; i<fields.length; i++) {
Field field = fields[i];
if ((field.getModifiers() & Modifier.STATIC) != 0)
@@ -509,17 +539,22 @@ public abstract class Structure {
}
Class nativeType = type;
if (typeMapper != null) {
ArgumentConverter converter = typeMapper.getArgumentConverter(type);
if (converter != null) {
value = converter.toNative(value);
ToNativeConverter writeConverter = typeMapper.getToNativeConverter(type);
FromNativeConverter readConverter = typeMapper.getFromNativeConverter(type);
if (writeConverter != null && readConverter != null) {
value = writeConverter.toNative(value);
nativeType = value != null ? value.getClass() : Pointer.class;
structField.writeConverter = converter;
structField.writeConverter = writeConverter;
structField.readConverter = readConverter;
structField.context = new StructureReadContext(type, this);
}
else if (writeConverter != null || readConverter != null) {
String msg = "Structures require bidirectional type conversion for " + type;
throw new IllegalArgumentException(msg);
}
structField.readConverter = typeMapper.getResultConverter(type);
structField.context = new StructureReadContext(type, this);
}
structField.size = getNativeSize(nativeType, value);
fieldAlignment = getNativeAlignment(nativeType, value);
fieldAlignment = getNativeAlignment(nativeType, value, i==0);
}
catch (IllegalAccessException e) {
// ignore non-public fields
@@ -537,6 +572,16 @@ public abstract class Structure {
structFields.put(structField.name, structField);
}
if (calculatedSize > 0) {
return calculateAlignedSize(calculatedSize);
}
throw new IllegalArgumentException("Structure " + getClass()
+ " has unknown size (ensure "
+ "all fields are public)");
}
int calculateAlignedSize(int calculatedSize) {
// Structure size must be an integral multiple of its alignment,
// add padding if necessary.
if (alignType != ALIGN_NONE) {
@@ -544,17 +589,14 @@ public abstract class Structure {
calculatedSize += structAlignment - (calculatedSize % structAlignment);
}
}
if (calculatedSize > 0) {
return calculatedSize;
}
throw new IllegalArgumentException("Structure " + getClass()
+ " has invalid size (ensure "
+ "all fields are public)");
return calculatedSize;
}
/** Overridable in subclasses. */
protected int getNativeAlignment(Class type, Object value) {
// TODO: write getNaturalAlignment(stack/alloc) + getEmbeddedAlignment(structs)
// TODO: move this into a native call which detects default alignment
// automatically
protected int getNativeAlignment(Class type, Object value, boolean firstElement) {
int alignment = 1;
int size = getNativeSize(type, value);
if (type.isPrimitive() || Long.class == type || Integer.class == type
@@ -574,7 +616,7 @@ public abstract class Structure {
alignment = ((Structure)value).structAlignment;
}
else if (type.isArray()) {
alignment = getNativeAlignment(type.getComponentType(), null);
alignment = getNativeAlignment(type.getComponentType(), null, firstElement);
}
else {
throw new IllegalArgumentException("Type " + type + " has unknown "
@@ -584,8 +626,13 @@ public abstract class Structure {
return 1;
if (alignType == ALIGN_MSVC)
return Math.min(8, alignment);
// 32-bit GNUC maximum alignment is 4 bytes
return Math.min(4, alignment);
if (alignType == ALIGN_GNUC) {
// NOTE this is published ABI for 32-bit gcc/linux/x86, osx/x86,
// and osx/ppc. osx/ppc special-cases the first element
if (!firstElement || !"ppc".equals(System.getProperty("os.arch")))
return Math.min(4, alignment);
}
return alignment;
}
/** Returns the native size for classes which don't need an object instance
@@ -593,8 +640,8 @@ public abstract class Structure {
*/
protected int getNativeSize(Class cls) {
if (cls == byte.class || cls == Byte.class) return 1;
if (cls == char.class || cls == Character.class) return Pointer.WCHAR_SIZE;
if (cls == short.class || cls == Short.class) return 2;
if (cls == char.class || cls == Character.class) return Pointer.WCHAR_SIZE;
if (cls == int.class || cls == Integer.class) return 4;
if (cls == long.class || cls == Long.class) return 8;
if (cls == float.class || cls == Float.class) return 4;
@@ -622,6 +669,7 @@ public abstract class Structure {
return len * getNativeSize(type.getComponentType(), o);
}
// Don't process zero-length arrays
throw new IllegalArgumentException("Arrays of length zero not allowed in structure: " + this);
}
return getNativeSize(type);
}
@@ -661,7 +709,9 @@ public abstract class Structure {
Memory m = (Memory)memory;
int requiredSize = array.length * size();
if (m.getSize() < requiredSize) {
useMemory(new Memory(requiredSize));
m = new Memory(requiredSize);
m.clear();
useMemory(m);
}
}
array[0] = this;
@@ -693,15 +743,32 @@ public abstract class Structure {
return toArray(new Structure[size]);
}
private class StructField extends Object {
/** This structure is only equal to another based on the same native
* memory address and data type.
*/
public boolean equals(Object o) {
return o == this
|| (o != null
&& o.getClass() == getClass()
&& ((Structure)o).getPointer().equals(getPointer()));
}
/** Since {@link #equals} depends on the native address, use that
* as the hashcode.
*/
public int hashCode() {
return getPointer().hashCode();
}
class StructField extends Object {
public String name;
public Class type;
public Field field;
public int size = -1;
public int offset = -1;
public ResultConverter readConverter;
public ArgumentConverter writeConverter;
public ResultContext context;
public FromNativeConverter readConverter;
public ToNativeConverter writeConverter;
public FromNativeContext context;
public String toString() {
Object value = "<unavailable>";
try {
@@ -15,7 +15,7 @@ package com.sun.jna;
/** Provide native to Java type conversion context for a {@link Structure}
* read.
*/
public class StructureReadContext extends ResultContext {
public class StructureReadContext extends FromNativeContext {
private Structure structure;
public StructureReadContext(Class resultClass, Structure struct) {
@@ -0,0 +1,40 @@
/*
* Copyright (c) 2007 Wayne Meissner, All Rights Reserved This library
* is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the
* Free Software Foundation; either version 2.1 of the License, or (at
* your option) any later version. <p/> This library is distributed in
* the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for
* more details.
*/
package com.sun.jna;
/**
* Define conversion from a Java type to its corresponding native type.
*/
public interface ToNativeConverter {
/**
* Convert a Java type to an appropriate native type. The new type
* must be one of the following classes:
* <ul>
* <li>{@link Pointer}
* <li>Boolean
* <li>Byte
* <li>Short
* <li>Character
* <li>Integer
* <li>{@link NativeLong}
* <li>Long
* <li>Float
* <li>Double
* <li>{@link Structure}
* <li>String
* <li>{@link WString}
* <li>{@link java.nio.ByteBuffer}
* <li>primitive array
* </ul>
*/
public Object toNative(Object value);
}
+1 -1
Ver Arquivo
@@ -16,4 +16,4 @@ package com.sun.jna;
/** Convenience interface for bidirectional conversion.
* @author Wayne Meissner
*/
public interface TypeConverter extends ResultConverter, ArgumentConverter {}
public interface TypeConverter extends FromNativeConverter, ToNativeConverter {}
+4 -4
Ver Arquivo
@@ -14,11 +14,11 @@ package com.sun.jna;
/** Provides converters for conversion to and from native types. */
public interface TypeMapper {
/** Return the {@link ResultConverter} appropriate for the given Java class.
/** Return the {@link FromNativeConverter} appropriate for the given Java class.
*/
ResultConverter getResultConverter(Class javaType);
FromNativeConverter getFromNativeConverter(Class javaType);
/** Return the {@link ArgumentConverter} appropriate for the given Java class.
/** Return the {@link ToNativeConverter} appropriate for the given Java class.
*/
ArgumentConverter getArgumentConverter(Class javaType);
ToNativeConverter getToNativeConverter(Class javaType);
}
+95
Ver Arquivo
@@ -0,0 +1,95 @@
/* Copyright (c) 2007 Timothy Wall, All Rights Reserved
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package com.sun.jna;
import java.util.Iterator;
/** Represents a native union. When writing to native memory, the field
* corresponding to the type passed to {@link #setType} will be written
* to native memory. Upon reading from native memory, Structure, String,
* or WString fields will <em>not</em> be initialized unless they are
* the current field as identified by a call to {@link #setType}. The current
* field is always unset by default to avoid accidentally attempting to read
* a field that is not valid. In the case of a String, for instance, an
* invalid pointer may result in a memory fault when attempting to initialize
* the String.
*/
public abstract class Union extends Structure {
private StructField writeField;
/** Create a Union whose size and alignment will be calculated
* automatically.
*/
protected Union() { }
/** Create a Union of the given size, using default alignment. */
protected Union(int size) {
super(size);
}
/** Create a Union of the given size and alignment type. */
protected Union(int size, int alignType) {
super(size, alignType);
}
/** Indicates which field will be used to write to native memory.
* @throws IllegalArgumentException if the type does not correspond to
* any declared union field.
*/
public void setType(Class type) {
for (Iterator i=fields().values().iterator();i.hasNext();) {
StructField f = (StructField)i.next();
if (f.type == type) {
writeField = f;
return;
}
}
throw new IllegalArgumentException("No field of type " + type + " in " + this);
}
/** Only the currently selected field will be written. */
void writeField(StructField field) {
if (field == writeField) {
super.writeField(field);
}
}
/** Avoid reading pointer-based fields and structures unless explicitly
* selected. Structures may contain pointer-based fields which can
* crash the VM if not properly initialized.
*/
void readField(StructField field) {
if (field == writeField
|| (!Structure.class.isAssignableFrom(field.type)
&& !String.class.isAssignableFrom(field.type)
&& !WString.class.isAssignableFrom(field.type))) {
super.readField(field);
}
}
/** Adjust the size to be the size of the largest element, and ensure
* all fields begin at offset zero.
*/
int calculateSize() {
int size = super.calculateSize();
if (size != CALCULATE_SIZE) {
int fsize = 0;
for (Iterator i=fields().values().iterator();i.hasNext();) {
StructField f = (StructField)i.next();
f.offset = 0;
fsize = Math.max(fsize, f.size);
}
size = calculateAlignedSize(fsize);
}
return size;
}
/** All fields are considered the "first" element. */
protected int getNativeAlignment(Class type, Object value, boolean firstElement) {
return super.getNativeAlignment(type, value, true);
}
}
@@ -56,9 +56,9 @@ public class BalloonManager {
private static class DropShadow extends JWindow {
private static final float ALPHA = .5f;
private static final float YSCALE = .90f;
private static final double ANGLE = 2*Math.PI/48;
private static final float SHADOW_ALPHA = .25f;
private static final float YSCALE = .80f;
private static final double ANGLE = 2*Math.PI/24;
private static final Point OFFSET = new Point(8, 8);
private static final Color COLOR = new Color(0, 0, 0, 50);
@@ -69,7 +69,8 @@ public class BalloonManager {
setFocusableWindowState(false);
setName("###overrideRedirect###");
Point where = parent.getLocation();
Point where = parent.isShowing()
? parent.getLocationOnScreen() : parent.getLocation();
setLocation(where.x + OFFSET.x, where.y + OFFSET.y);
setBackground(COLOR);
getContentPane().setBackground(COLOR);
@@ -77,12 +78,15 @@ public class BalloonManager {
parentMask = mask;
parent.addComponentListener(listener = new ComponentAdapter() {
public void componentMoved(ComponentEvent e) {
Point where = e.getComponent().getLocationOnScreen();
Point where = getOwner().isShowing()
? getOwner().getLocationOnScreen()
: getOwner().getLocation();
setLocation(where.x + OFFSET.x, where.y + OFFSET.y);
}
public void componentResized(ComponentEvent e) {
Component c = e.getComponent();
setSize(c.getWidth(), c.getHeight());
int extra = c.getWidth() + (int)Math.sin(ANGLE)*c.getHeight();
setSize(c.getWidth() + extra, c.getHeight());
WindowUtils.setWindowMask(DropShadow.this, getMask());
}
public void componentShown(ComponentEvent e) {
@@ -101,7 +105,7 @@ public class BalloonManager {
}
});
WindowUtils.setWindowMask(DropShadow.this, getMask());
WindowUtils.setWindowAlpha(DropShadow.this, ALPHA);
WindowUtils.setWindowAlpha(DropShadow.this, SHADOW_ALPHA);
if (parent.isVisible()) {
pack();
setVisible(true);
@@ -125,13 +129,14 @@ public class BalloonManager {
private Shape getMask() {
Area area = new Area(parentMask);
Area clip = new Area(parentMask);
// TODO: shear right and shrink height
//AffineTransform tx = new AffineTransform();
//tx.shear(-Math.tan(ANGLE), 0);
//tx.translate(Math.sin(ANGLE)*getHeight(), getHeight()-getHeight()*YSCALE);
//tx.scale(1, YSCALE);
//area.transform(tx);
AffineTransform tx = new AffineTransform();
tx.translate(Math.sin(ANGLE)*getOwner().getHeight(), 0);
tx.shear(-Math.tan(ANGLE), 0);
tx.scale(1, YSCALE);
tx.translate(0, (1-YSCALE)*getOwner().getHeight());
area.transform(tx);
tx = new AffineTransform();
tx.translate(-OFFSET.x, -OFFSET.y);
clip.transform(tx);
area.subtract(clip);
@@ -148,7 +153,10 @@ public class BalloonManager {
private Dimension maskSize;
private ComponentListener moveTracker = new ComponentAdapter() {
public void componentMoved(ComponentEvent e) {
Point where = e.getComponent().getLocationOnScreen();
Point where =
e.getComponent().isShowing()
? e.getComponent().getLocationOnScreen()
: e.getComponent().getLocation();
setLocation(where.x - offset.x, where.y - offset.y);
// TODO preserve stacking order (linux)
}
@@ -185,7 +193,8 @@ public class BalloonManager {
super.setLocation(x, y);
Window owner = getOwner();
if (owner != null) {
Point ref = owner.getLocationOnScreen();
Point ref = owner.isShowing()
? owner.getLocationOnScreen() : owner.getLocation();
offset = new Point(ref.x - x, ref.y - y);
}
}
@@ -223,7 +232,9 @@ public class BalloonManager {
// Simulate PopupFactory, ensuring we get a heavyweight "popup"
final Point origin =
owner == null ? new Point(0, 0) : owner.getLocationOnScreen();
owner == null ? new Point(0, 0)
: (owner.isShowing()
? owner.getLocationOnScreen() : owner.getLocation());
final Window parent = owner != null
? SwingUtilities.getWindowAncestor(owner) : null;
origin.translate(x, y);
@@ -105,6 +105,7 @@ public class BalloonManagerDemo {
f.setSize(new Dimension(300, 300));
f.setLocation(100, 100);
try {
// Force a load of JNA
WindowUtils.setWindowMask(f, WindowUtils.MASK_NONE);
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
@@ -113,7 +114,7 @@ public class BalloonManagerDemo {
e.printStackTrace();
String msg = e.getMessage()
+ "\nError loading the JNA library after looking in "
+ System.getProperty("java.library.path");
+ System.getProperty("jna.library.path");
JTextArea area = new JTextArea(msg);
area.setOpaque(false);
area.setFont(UIManager.getFont("Label.font"));
@@ -0,0 +1,202 @@
/* Copyright (c) 2007 Olivier Chafik, All Rights Reserved
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package com.sun.jna.examples;
import java.awt.Rectangle;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferInt;
import java.awt.image.MultiPixelPackedSampleModel;
import java.awt.image.Raster;
import java.awt.image.SampleModel;
import java.awt.image.SinglePixelPackedSampleModel;
/**
* Methods that are useful to decompose a raster in ranges of contiguous unoccupied pixels.
* An occupied pixel has two possible meanings, depending on the raster :
* <ul>
* <li>if the raster has an alpha layer, occupied means with alpha not null</li>
* <li>if the raster doesn't have any alpha layer, occupied means not completely black</li>
* </ul>
* @author Olivier Chafik
*/
public class RasterRangesUtils {
/// Masks used to isolate the current column in a set of 8 binary columns packed in a byte
private static final int[] subColMasks = new int[] {
0x0080, 0x0040, 0x0020, 0x0010,
0x0008, 0x0004, 0x0002, 0x0001
};
/**
* Abstraction of a sink for ranges.
*/
public static interface RangesOutput {
/**
* Output a rectangular range.
* @param x x coordinate of the top-left corner of the range
* @param y y coordinate of the top-left corner of the range
* @param w witdh of the range
* @param h height of the range
* @return true if the output succeeded, false otherwise
*/
public boolean outputRange(int x, int y, int w, int h);
}
/**
* Outputs ranges of occupied pixels.
* In a raster that has an alpha layer, a pixel is occupied if its alpha value is not null.
* In a raster without alpha layer, a pixel is occupied if it is not completely black.
* @param raster image to be segmented in non black or non-transparent ranges
* @param out destination of the non null ranges
* @return true if the output succeeded, false otherwise
*/
public static boolean outputOccupiedRanges(Raster raster, RangesOutput out) {
Rectangle bounds = raster.getBounds();
SampleModel sampleModel = raster.getSampleModel();
boolean hasAlpha = sampleModel.getNumBands() == 4;
// Try to use the underlying data array directly for a few common raster formats
if (raster.getParent() == null && bounds.x == 0 && bounds.y == 0) {
// No support for subraster (as obtained with Image.getSubimage(...))
DataBuffer data = raster.getDataBuffer();
if (data.getNumBanks() == 1) {
// There is always a single bank for all BufferedImage types, except maybe TYPE_CUSTOM
if (sampleModel instanceof MultiPixelPackedSampleModel) {
MultiPixelPackedSampleModel packedSampleModel = (MultiPixelPackedSampleModel)sampleModel;
if (packedSampleModel.getPixelBitStride() == 1) {
// TYPE_BYTE_BINARY
return outputOccupiedRangesOfBinaryPixels(((DataBufferByte)data).getData(), bounds.width, bounds.height, out);
}
} else if (sampleModel instanceof SinglePixelPackedSampleModel) {
if (sampleModel.getDataType() == DataBuffer.TYPE_INT) {
// TYPE_INT_ARGB, TYPE_INT_ARGB_PRE, TYPE_INT_BGR or TYPE_INT_RGB
return outputOccupiedRanges(((DataBufferInt)data).getData(), bounds.width, bounds.height, hasAlpha ? 0xff000000 : 0xffffff, out);
}
// TODO could easily handle cases of TYPE_USHORT_GRAY and TYPE_BYTE_GRAY.
}
}
}
// Fallback behaviour : copy pixels of raster
int[] pixels = raster.getPixels(0, 0, bounds.width, bounds.height, (int[])null);
return outputOccupiedRanges(pixels, bounds.width, bounds.height, hasAlpha ? 0xff000000 : 0xffffff, out);
}
/**
* Output the non-null values of a binary image as ranges of contiguous values.
* @param binaryBits byte-packed binary bits of an image
* @param w width of the image (in pixels)
* @param h height of the image
* @param output
* @return true if the output succeeded, false otherwise
*/
public static boolean outputOccupiedRangesOfBinaryPixels(byte[] binaryBits, int w, int h, RangesOutput output) {
int scanlineBytes = binaryBits.length / h;
for (int row = 0; row < h; row++) {
int rowOffsetBytes = row * scanlineBytes;
int startCol = -1;
// Look at each batch of 8 columns in this row
for (int byteCol = 0; byteCol < scanlineBytes; byteCol++) {
int firstByteCol = byteCol << 3;
byte byteColBits = binaryBits[rowOffsetBytes + byteCol];
if (byteColBits == 0) {
// all 8 bits are zeroes
if (startCol >= 0) {
// end of current region
if (!output.outputRange(startCol, row, firstByteCol - startCol, 1)) {
return false;
}
startCol = -1;
}
} else if (byteColBits == 0xff) {
// all 8 bits are ones
if (startCol < 0) {
// start of new region
startCol = firstByteCol;
}
} else {
// mixed case : some bits are ones, others are zeroes
for (int subCol = 0; subCol < 8; subCol++) {
int col = firstByteCol | subCol;
if ((byteColBits & subColMasks[subCol]) != 0) {
if (startCol < 0) {
// start of new region
startCol = col;
}
} else {
if (startCol >= 0) {
// end of current region
if (!output.outputRange(startCol, row, col - startCol, 1)) {
return false;
}
startCol = -1;
}
}
}
}
}
if (startCol >= 0) {
// end of last region
if (!output.outputRange(startCol, row, w - startCol, 1)) {
return false;
}
startCol = -1;
}
}
return true;
}
/**
* Output the occupied values of an integer-pixels image as ranges of contiguous values.
* A pixel is considered occupied if the bitwise AND of its integer value with the provided occupationMask is not null.
* @param pixels integer values of the pixels of an image
* @param w width of the image (in pixels)
* @param h height of the image
* @param occupationMask mask used to select which bits are used in a pixel to check its occupied status. 0xff000000 would only take the alpha layer into account, for instance.
* @param out where to output all the contiguous ranges of non occupied pixels
* @return true if the output succeeded, false otherwise
*/
public static boolean outputOccupiedRanges(int[] pixels, int w, int h, int occupationMask, RangesOutput out) {
for (int row = 0; row < h; row++) {
int idxOffset = row * w;
int startCol = -1;
for (int col = 0; col < w; col++) {
if ((pixels[idxOffset + col] & occupationMask) != 0) {
if (startCol < 0) {
startCol = col;
}
} else {
if (startCol >= 0) {
// end of current region
if (!out.outputRange(startCol, row, col - startCol, 1)) {
return false;
}
startCol = -1;
}
}
}
if (startCol >= 0) {
// end of last region of current row
if (!out.outputRange(startCol, row, w - startCol, 1)) {
return false;
}
startCol = -1;
}
}
return true;
}
}
@@ -255,7 +255,7 @@ public class ShapedWindowDemo {
e.printStackTrace();
String msg = e.getMessage()
+ "\nError loading the JNA library after looking in "
+ System.getProperty("java.library.path");
+ System.getProperty("jna.library.path");
JTextArea area = new JTextArea(msg);
area.setOpaque(false);
area.setFont(UIManager.getFont("Label.font"));
+88 -94
Ver Arquivo
@@ -18,13 +18,11 @@ import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
@@ -40,6 +38,7 @@ import java.awt.image.BufferedImage;
import java.awt.image.Raster;
import java.util.ArrayList;
import java.util.List;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JLayeredPane;
@@ -48,6 +47,7 @@ import javax.swing.JRootPane;
import javax.swing.PopupFactory;
import javax.swing.RootPaneContainer;
import javax.swing.SwingUtilities;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.examples.unix.X11;
@@ -67,9 +67,11 @@ import com.sun.jna.ptr.PointerByReference;
/**
* Provides additional features on a Java {@link Window}.
* <ul>
* <li>Non-rectangular shape
* <li>Non-rectangular shape (bitmap mask, no antialiasing)
* <li>Transparency (constant alpha applied to window contents or
* transparent background)
* <li>Fully transparent window (the transparency of all painted pixels is
* applied to the window).
* </ul>
* NOTE: since there is no explicit way to force PopupFactory to use a
* heavyweight popup, and anything but a heavyweight popup will be
@@ -77,7 +79,7 @@ import com.sun.jna.ptr.PointerByReference;
* masked windows to implicitly force PopupFactory to use a heavyweight
* window and avoid clipping.
* <p>
* NOTE: {@link #setWindowTransparent} on X11 doesn't seem to composite
* NOTE: {@link #setWindowTransparent} on X11 doesn't composite
* entirely correctly; depending on what's drawn in the window it mey be
* more or less noticable.
* <p>
@@ -215,6 +217,9 @@ public class WindowUtils {
e.getWindow().removeWindowListener(this);
action.run();
}
public void windowClosed(WindowEvent e) {
e.getWindow().removeWindowListener(this);
}
});
}
else {
@@ -223,7 +228,8 @@ public class WindowUtils {
// changes
w.addHierarchyListener(new HierarchyListener() {
public void hierarchyChanged(HierarchyEvent e) {
if ((e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0) {
if ((e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0
&& e.getComponent().isDisplayable()) {
e.getComponent().removeHierarchyListener(this);
action.run();
}
@@ -311,7 +317,7 @@ public class WindowUtils {
/** Set the window mask based on a {@link Shape}. */
public void setWindowMask(Window w, Shape mask) {
Raster raster = null;
if (mask != null) {
if (mask != MASK_NONE) {
Rectangle bounds = mask.getBounds();
if (bounds.width > 0 && bounds.height > 0) {
BufferedImage bitmap =
@@ -338,8 +344,7 @@ public class WindowUtils {
if (mask != null) {
Rectangle bounds = new Rectangle(0, 0, mask.getIconWidth(),
mask.getIconHeight());
BufferedImage clip = new BufferedImage(
bounds.width,
BufferedImage clip = new BufferedImage(bounds.width,
bounds.height,
BufferedImage.TYPE_INT_ARGB);
Graphics2D g = clip.createGraphics();
@@ -404,34 +409,6 @@ public class WindowUtils {
}
private static class W32WindowUtils extends NativeWindowUtils {
private Pointer createRegion(Raster raster) {
GDI32 gdi = GDI32.INSTANCE;
// Brute force creation of region from bitmap; really slow
Pointer result = gdi.CreateRectRgn(0, 0, 0, 0);
Rectangle bounds = new Rectangle(0, 0, raster.getWidth(),
raster.getHeight());
int[] bits = new int[bounds.width * bounds.height];
raster.getPixels(0, 0, bounds.width, bounds.height, bits);
for (int row = 0; row < bounds.height; row++) {
for (int col = 0; col < bounds.width; col++) {
int idx = row * bounds.width + col;
if (bits[idx] != 0) {
Pointer bit = gdi.CreateRectRgn(bounds.x + col,
bounds.y + row,
bounds.x + col + 1,
bounds.y + row + 1);
int status = gdi.CombineRgn(result, result, bit,
GDI32.RGN_OR);
if (status == GDI32.ERROR) {
System.err.println("Error combining regions");
}
gdi.DeleteObject(bit);
}
}
}
return result;
}
public Pointer getHWnd(Window w) {
return Native.getWindowPointer(w);
/*
@@ -637,8 +614,7 @@ public class WindowUtils {
if (transparent && !isTransparent(w)) {
flags |= User32.WS_EX_LAYERED;
user.SetWindowLong(hWnd, User32.GWL_EXSTYLE, flags);
lp
.add(new W32RepaintTrigger(), JLayeredPane.DRAG_LAYER);
lp.add(new W32RepaintTrigger(), JLayeredPane.DRAG_LAYER);
}
else if (!transparent && isTransparent(w)) {
flags &= ~User32.WS_EX_LAYERED;
@@ -657,14 +633,30 @@ public class WindowUtils {
GDI32 gdi = GDI32.INSTANCE;
User32 user = User32.INSTANCE;
Pointer hWnd = getHWnd(w);
Pointer p = raster == null
? gdi.CreateRectRgn(0, 0, w.getWidth(), w.getHeight())
: createRegion(raster);
final Pointer result = gdi.CreateRectRgn(0, 0, 0, 0);
try {
user.SetWindowRgn(hWnd, p, true);
if (raster == null) {
gdi.SetRectRgn(result, 0, 0, w.getWidth(), w.getHeight());
}
else {
final Pointer tempRgn = gdi.CreateRectRgn(0, 0, 0, 0);
try {
RasterRangesUtils.outputOccupiedRanges(raster, new RasterRangesUtils.RangesOutput() {
public boolean outputRange(int x, int y, int w, int h) {
GDI32 gdi = GDI32.INSTANCE;
gdi.SetRectRgn(tempRgn, x, y, x + w, y + h);
return gdi.CombineRgn(result, result, tempRgn, GDI32.RGN_OR) != GDI32.ERROR;
}
});
}
finally {
gdi.DeleteObject(tempRgn);
}
}
user.SetWindowRgn(hWnd, result, true);
}
finally {
gdi.DeleteObject(p);
gdi.DeleteObject(result);
}
setForceHeavyweightPopups(w, raster != null);
}
@@ -673,20 +665,13 @@ public class WindowUtils {
}
private static class MacWindowUtils extends NativeWindowUtils {
private Shape shapeFromRaster(Raster raster) {
Area area = new Area(new Rectangle(0, 0, 0, 0));
Rectangle bounds = new Rectangle(0, 0, raster.getWidth(),
raster.getHeight());
// brute-force conversion from raster to area
int[] bits = new int[bounds.width * bounds.height];
raster.getPixels(0, 0, bounds.width, bounds.height, bits);
for (int row = 0; row < bounds.height; row++) {
for (int col = 0; col < bounds.width; col++) {
int idx = row * bounds.width + col;
if (bits[idx] != 0) {
area.add(new Area(new Rectangle(col, row, 1, 1)));
}
final Area area = new Area(new Rectangle(0, 0, 0, 0));
RasterRangesUtils.outputOccupiedRanges(raster, new RasterRangesUtils.RangesOutput() {
public boolean outputRange(int x, int y, int w, int h) {
area.add(new Area(new Rectangle(x, y, w, h)));
return true;
}
}
});
return area;
}
@@ -719,7 +704,6 @@ public class WindowUtils {
w.add(content);
}
}
w.setBackground(new Color(0, 0, 0, 0));
return content;
}
@@ -729,6 +713,7 @@ public class WindowUtils {
if (!(transparent ^ isTransparent))
return;
installTransparentContent(w);
setBackgroundTransparent(w, transparent);
setLayersTransparent(w, transparent);
}
@@ -797,50 +782,52 @@ public class WindowUtils {
}
}
}
private void setBackgroundTransparent(Window w, boolean transparent) {
if (transparent) {
w.setBackground(new Color(0,0,0,0));
}
else {
// FIXME restore background
w.setBackground(new Window(w.getOwner()).getBackground());
}
}
public void setWindowMask(Window w, final Shape shape) {
OSXTransparentContent content = installTransparentContent(w);
content.setMask(shape);
setBackgroundTransparent(w, shape != MASK_NONE);
}
}
private static class X11WindowUtils extends NativeWindowUtils {
private int createBitmap(Pointer dpy, int win, Window w, Raster raster) {
X11 x11 = X11.INSTANCE;
if (raster == null) {
int pm = x11.XCreatePixmap(dpy, win, w.getWidth(),
w.getHeight(), 1);
Pointer gc = x11.XCreateGC(dpy, pm, 0, null);
if (gc == null) {
return 0;
}
x11.XSetForeground(dpy, gc, 1);
x11.XFillRectangle(dpy, pm, gc, 0, 0, w.getWidth(),
w.getHeight());
return pm;
}
private int createBitmap(final Pointer dpy, int win, Window w, Raster raster) {
final X11 x11 = X11.INSTANCE;
Rectangle bounds = raster.getBounds();
int width = bounds.x + bounds.width;
int height = bounds.y + bounds.height;
int pm = x11.XCreatePixmap(dpy, win, width, height, 1);
Pointer gc = x11.XCreateGC(dpy, pm, 0, null);
final int pm = x11.XCreatePixmap(dpy, win, width, height, 1);
final Pointer gc = x11.XCreateGC(dpy, pm, 0, null);
if (gc == null) {
return 0;
return X11.None;
}
x11.XSetForeground(dpy, gc, 0);
x11.XFillRectangle(dpy, pm, gc, 0, 0, width, height);
final int UNMASKED = 1;
x11.XSetForeground(dpy, gc, UNMASKED);
X11.XWindowAttributes atts = new X11.XWindowAttributes();
int status = x11.XGetWindowAttributes(dpy, win, atts);
if (status == 0) {
return 0;
return X11.None;
}
// Brute force creation of bitmap from image data; kinda
// slow
int[] bits = new int[bounds.width * bounds.height];
raster.getPixels(0, 0, bounds.width, bounds.height, bits);
for (int row = 0; row < bounds.height; row++) {
for (int col = 0; col < bounds.width; col++) {
int idx = row * bounds.width + col;
x11.XSetForeground(dpy, gc, bits[idx]);
x11.XFillRectangle(dpy, pm, gc, col, row, 1, 1);
}
try {
RasterRangesUtils.outputOccupiedRanges(raster, new RasterRangesUtils.RangesOutput() {
public boolean outputRange(int x, int y, int w, int h) {
return x11.XFillRectangle(dpy, pm, gc, x, y, w, h) != 0;
}
});
}
finally {
x11.XFreeGC(dpy, gc);
}
return pm;
}
@@ -1079,14 +1066,19 @@ public class WindowUtils {
int pm = X11.None;
try {
int win = getDrawable(w);
pm = createBitmap(dpy, win, w, raster);
if (pm == X11.None) {
return;
if (raster == null
|| ((pm = createBitmap(dpy, win, w, raster))
== X11.None)) {
ext.XShapeCombineMask(dpy, win,
X11.Xext.ShapeBounding,
0, 0, X11.None,
X11.Xext.ShapeSet);
}
else {
ext.XShapeCombineMask(dpy, win,
X11.Xext.ShapeBounding, 0, 0,
pm, X11.Xext.ShapeSet);
}
int ShapeBounding = 0;
int ShapeSet = 0;
ext.XShapeCombineMask(dpy, win, ShapeBounding, 0, 0,
pm, ShapeSet);
}
finally {
if (pm != X11.None) {
@@ -1103,7 +1095,8 @@ public class WindowUtils {
/**
* Applies the given mask to the given window. Does nothing if the
* operation is not supported.
* operation is not supported. The mask is treated as a bitmap and
* ignores transparency.
*/
public static void setWindowMask(Window w, Shape mask) {
getInstance().setWindowMask(w, mask);
@@ -1111,7 +1104,8 @@ public class WindowUtils {
/**
* Applies the given mask to the given window. Does nothing if the
* operation is not supported.
* operation is not supported. The mask is treated as a bitmap and
* ignores transparency.
*/
public static void setWindowMask(Window w, Icon mask) {
getInstance().setWindowMask(w, mask);
@@ -19,20 +19,16 @@ import java.awt.GraphicsConfiguration;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragSource;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Area;
import java.io.IOException;
import javax.swing.Icon;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import com.sun.jna.examples.WindowUtils;
/** Provide a ghosted drag image for use during drags where
@@ -25,11 +25,11 @@ import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.io.IOException;
import java.net.URL;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
/** Demonstrate ghosted drag images. Unfortunately, Swing drag support hides
@@ -25,6 +25,16 @@ public interface X11 extends Library {
/** Definition (incomplete) of the Xext library. */
public interface Xext extends Library {
Xext INSTANCE = (Xext)Native.loadLibrary("Xext", Xext.class);
// Shape Kinds
int ShapeBounding = 0;
int ShapeClip = 1;
int ShapeInput = 2;
// Operations
int ShapeSet = 0;
int ShapeUnion = 1;
int ShapeIntersect = 2;
int ShapeSubtract = 3;
int ShapeInvert = 4;
void XShapeCombineMask(Pointer display, int window, int dest_kind,
int x_off, int y_off, int src, int op);
@@ -13,12 +13,11 @@
package com.sun.jna.examples.win32;
import java.awt.Rectangle;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.ptr.PointerByReference;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APITypeMapper;
/** Definition (incomplete) of <code>gdi32.dll</code>. */
public interface GDI32 extends W32API {
@@ -78,6 +77,8 @@ public interface GDI32 extends W32API {
int nWidthEllipse,
int nHeightEllipse);
boolean SetRectRgn(Pointer p, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect);
int SetPixel(Pointer hDC, int x, int y, int crColor);
Pointer CreateCompatibleDC(Pointer hDC);
@@ -17,15 +17,13 @@ import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.PointerByReference;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APITypeMapper;
/** Definition (incomplete) of <code>kernel32.dll</code>. */
public interface Kernel32 extends W32API {
Kernel32 INSTANCE = (Kernel32)
Native.loadLibrary("kernel32", Kernel32.class, DEFAULT_OPTIONS);
public static class SYSTEMTIME extends Structure {
public short wYear;
public short wMonth;
@@ -41,11 +39,13 @@ public interface Kernel32 extends W32API {
int GetCurrentThreadId();
int GetCurrentProcessId();
int GetLastError();
void SetLastError(int dwErrCode);
int FORMAT_MESSAGE_FROM_SYSTEM = 0x1000;
int FORMAT_MESSAGE_IGNORE_INSERTS = 0x200;
int FormatMessage(int dwFlags, Pointer lpSource, int dwMessageId,
int dwLanguageId, Pointer lpBuffer, int nSize,
Pointer va_list);
int dwLanguageId, PointerByReference lpBuffer,
int nSize, Pointer va_list);
int FILE_LIST_DIRECTORY = 0x00000001;
@@ -190,4 +190,6 @@ public interface Kernel32 extends W32API {
IntByReference bytesReturned,
OVERLAPPED overlapped,
OVERLAPPED_COMPLETION_ROUTINE completionRoutine);
int GetProcessId(Pointer process);
}
@@ -12,16 +12,9 @@
*/
package com.sun.jna.examples.win32;
import java.util.HashMap;
import java.util.Map;
import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.DefaultTypeMapper;
import com.sun.jna.WString;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APITypeMapper;
/** shellapi.h includes pshpack1.h, which disables automatic alignment
* of structure fields.
@@ -12,15 +12,12 @@
*/
package com.sun.jna.examples.win32;
import java.util.HashMap;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.examples.win32.GDI32.RECT;
import com.sun.jna.ptr.ByteByReference;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APITypeMapper;
/** Provides access to the w32 user32 library.
* Incomplete implementation to support demos.
@@ -14,8 +14,8 @@ package com.sun.jna.examples.win32;
import java.util.HashMap;
import java.util.Map;
import com.sun.jna.Pointer;
import com.sun.jna.DefaultTypeMapper;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIFunctionMapper;
import com.sun.jna.win32.W32APITypeMapper;
+74 -47
Ver Arquivo
@@ -20,6 +20,7 @@ library for simplified native library access for Java.
<a href=index.html target=_top>API w/FRAMES</a>&nbsp;
<p>
<a name="overview"></a>
<h1>Java Native Access (JNA)</h1>
JNA provides simplified access to native library methods without requiring any
additional JNI or native code.
@@ -29,20 +30,20 @@ additional JNI or native code.
When you've determined which shared library holds the methods to which you
need access, create an interface class corresponding to that library. For
example, a mapping for the C library itself would look like this:<br>
<code><pre>
<blockquote><code><pre>
public interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary)Native.loadLibrary("c", CLibrary.class);
}
</pre></code>
</pre></code></blockquote>
The <code>String</code> passed to the <code>Native.loadLibrary</code> method
is the undecorated name of the shared library file. Here are some examples of
library name mappings.
<table>
library name mappings.<p>
<center><table style="background-color: #EAEAEA;" width="50%">
<tr><td><b>OS</b></td><td><b>Library Name</b></td><td><b>String</b></td></tr>
<tr><td>Windows</td><td>user32.dll</td><td>user32</td></tr>
<tr><td>Linux</td><td>libX11.so</td><td>X11</td></tr>
<tr><td>Mac OS X</td><td>libm.dylib</td><td>m</td></tr>
</table>
</table></center>
<p>
Any given native library with a unique filesystem path is represented by a single instance of {@link com.sun.jna.NativeLibrary} and obtained via {@link com.sun.jna.NativeLibrary#getInstance(String)}. The native library will be unloaded when no longer referenced by any Java code.
@@ -50,41 +51,50 @@ Any given native library with a unique filesystem path is represented by a singl
Function names are mapped directly from their Java interface name to the
symbol exported by the native library. For instance, the function to convert
an ASCII string into an integer would look like this:<br>
<code><pre>
<blockquote><code><pre>
public interface CLibrary extends Library {
int atol(String s);
}
</pre></code>
If you prefer to rename the Java methods to conform to Java coding
conventions, then you can provide a <code>Map</code> to
<code>Native.loadLibrary</code> which maps the Java names to the native
names. While this keeps your Java code a little cleaner, the additional
mapping of names may make a little less obvious the native functions being called.<p>
</pre></code></blockquote>
If you prefer to rename the Java methods to conform to Java coding conventions, then you can provide an entry ({@link com.sun.jna.Library#OPTION_FUNCTION_MAPPER}/{@link com.sun.jna.FunctionMapper}) in the options <code>Map</code> passed to <code>Native.loadLibrary</code> which maps the Java names to the native names. While this keeps your Java code a little cleaner, the additional mapping of names may make it a little less obvious the native functions being called.<p>
An instance of the {@link com.sun.jna.Function} class is obtained through the {@link com.sun.jna.NativeLibrary} instance corresponding to the containing native library. This {@link com.sun.jna.Function} instance handles argument marshalling and delegation to the native function.
<a name="marshalling"></a>
<h2>Function Argument Mapping (Java to Native Type Conversions, or Marshalling/Unmarshalling)</h2>
Java types are chosen to match native types of the same size. These are the
default type mappings:<br>
<table>
default type mappings:<p>
<center><table style="background-color: #EAEAEA;">
<tr><td><b>Native Type</b></td><td><b>Java Type</b></td></tr>
<tr><td>char</td><td>byte</td>
<tr><td>char*</td><td>String</td>
<tr><td>wchar_t</td><td>char</td>
<tr><td>wchar_t*</td><td>{@link com.sun.jna.WString}</td>
<tr><td>short</td><td>short</td>
<tr><td>long</td><td>int</td>
<tr><td>long long</td><td>long</td>
<tr><td>float</td><td>float</td>
<tr><td>double</td><td>double</td>
<tr><td>pointer (to type or array as pointer)</td><td>{@link com.sun.jna.Pointer}</td>
<tr><td>struct* (pointer to struct)</td><td>{@link com.sun.jna.Structure}</td>
<tr><td>struct[] (array of contiguous structs)</td><td>{@link com.sun.jna.Structure}[]</td>
<tr><td>nested arrays</td><td>Array of type</td>
<tr><td>nested structures</td><td>{@link com.sun.jna.Structure}</td>
<tr><td><i>not yet implemented</i></td>
<tr><td>unions</td>
<tr><td>int (boolean)</td><td><i>boolean</i> (mapping can be customized)</td>
<tr><td>char</td><td><b>byte</b></td>
<tr><td>char*</td><td><i>String</i></td>
<tr><td>wchar_t</td><td><b>char</b></td>
<tr><td>wchar_t*</td><td><i>{@link com.sun.jna.WString}</i></td>
<tr><td>short</td><td><b>short</b></td>
<tr><td>int</td><td><b>int</b></td>
<tr><td>long</td><td><i>{@link com.sun.jna.NativeLong}</i></td>
<tr><td>long long</td><td><b>long</b></td>
<tr><td>float</td><td><b>float</b></td>
<tr><td>double</td><td><b>double</b></td>
<tr><td>pointer (array of primitive type as pointer)</td><td><b>&lt;T&gt;[]</b> or <b>{@link java.nio.ByteBuffer}</b></td>
<tr><td>pointer (to type)</td><td><i>{@link com.sun.jna.ptr.ByReference}</i></td>
<tr><td>struct* (pointer to struct)</td><td><i>{@link com.sun.jna.Structure}</i></td>
<tr><td>union*</td><td><i>{@link com.sun.jna.Union}</i></td>
<tr><td>struct[] (array of structs contiguous in memory)</td><td><i>{@link com.sun.jna.Structure}[]</i></td>
<tr><td>primitive arrays within a struct</td><td><b>&lt;T&gt;[]</b> (Array of primitive type)</td>
<tr><td>struct within a struct</td><td><i>{@link com.sun.jna.Structure}</i></td>
<tr><td colspan=2><i>not yet implemented</i></td>
<tr><td>bitfields</td>
<tr><td>struct by value (argument or return value)</td>
</table>
</center>
<p>
Only the Java types indicated in bold are handled directly in native code.
All other types must eventually be converted to one of these basic types.
Those Java types in italics are handled by the JNA Java library and converted
to or from one of the basic types.
<p>
Type mapping behavior may be customized by providing a {@link com.sun.jna.TypeMapper} for the {@link com.sun.jna.Library#OPTION_TYPE_MAPPER} option when initializing a library interface. See {@link com.sun.jna.win32.W32APITypeMapper} for an example which provides custom conversion of boolean and String types. You are free to use whatever types are convenient in your defined interfaces, but all custom types <em>must</em> provide a mapping to one of the basic or derived types listed above.
<p>
<h3>Pointers</h3>
@@ -143,7 +153,7 @@ the platform's native C <code>struct</code>s.
To pass an array of structures, simply use a Java array of the desired
structure type. If the array is uninitialized, it will be auto-initialized
prior to the function call.<p>
<code><pre>
<blockquote><code><pre>
// C code
void get_devices(struct Device[], int size);
@@ -151,16 +161,24 @@ void get_devices(struct Device[], int size);
int size = ...
Device[] devices = new Device[size];
lib.get_devices(devices, devices.length);
</pre></code>
</pre></code></blockquote>
<h4>Array of <code>struct</code>s Returned</h4>
Alternatively, you can reallocate a single Structure instance into an array as
follows:<br>
<blockquote><code><pre>
Device dev = new Device();
Structure[] structs = dev.toArray(size);
Device[] devices = (Device[])dev.toArray(new Device[size]);
</pre></code></blockquote>
<h4>Returning an Array of <code>struct</code></h4>
Declare the method as returning a {@link com.sun.jna.Structure} of the
appropriate type, then invoke {@link com.sun.jna.Structure#toArray(int)} to
convert to an array of initialized structures of the appropriate size. Note
that your {@link com.sun.jna.Structure} class must have a no-args constructor,
and you are responsible for freeing the returned memory if applicable in
whatever way is appropriate for the called function.<p>
<code><pre>
<blockquote><code><pre>
// C code
struct Display* get_displays(int* pcount);
void free_displays(struct Display* displays);
@@ -174,12 +192,12 @@ Display d = lib.get_displays(pcount);
Display[] displays = (Display[])d.toArray(new Display[pcount.getValue()]);
...
lib.free_displays(displays);
</pre></code>
</pre></code></blockquote>
<h4>Nested Structure Definitions</h4>
Nested structures are treated as consecutive memory (as opposed to pointers to
structures). For example:<br>
<code><pre>
<blockquote><code><pre>
// C code
typedef struct _Point {
int x, y;
@@ -199,14 +217,14 @@ class Line extends Structure {
public Point start;
public Point end;
}
</pre></code>
</pre></code></blockquote>
Explicit initialization of nested structures is not required; the objects will
be created as needed and properly mapped to the parent structure's memory.<p>
If you need a pointer to a structure, do this instead:<br>
If you need a pointer to a structure (or more generally, a pointer to a buffer), do this instead:<br>
<code><pre>
<blockquote><code><pre>
// C code
typedef struct _Line2 {
Point* p1;
@@ -224,12 +242,12 @@ Point p1, p2;
...
line2.p1 = p1.getPointer();
line2.p2 = p2.getPointer();
</pre></code>
</pre></code></blockquote>
<h4>Nested arrays</h4>
Structures with nested arrays require an explicit constructor to ensure the
structure size is properly calculated.
<code><pre>
<blockquote><code><pre>
typedef struct _Buffer {
char buf1[32];
char buf2[1024];
@@ -239,26 +257,26 @@ class Buffer extends Structure {
public byte[] buf1 = new byte[32];
public byte[] buf2 = new byte[1024];
}
</pre></code>
</pre></code></blockquote>
Calculation of the native size of the structure is deferred until the
structure is actually used.
<h4>Variable-sized structures</h4>
Structures with variable size, for example:<br>
<code><pre>
Structures with variable size, or with primitive array elements, for example:<br>
<blockquote><code><pre>
// C code
typedef struct _Header {
int flags;
int buf_length;
char buffer[1];
} Header;
</pre></code>
</pre></code></blockquote>
require a constructor which establishes the required size for the structure
and initializes things appropriately. For example:<br>
<code><pre>
<blockquote><code><pre>
// JNA code
class Header extends Structure {
public int flags;
@@ -270,7 +288,16 @@ class Header extends Structure {
allocateMemory();
}
}
</pre></code>
</pre></code></blockquote>
<h4>Unions</h4>
Unions are a special type of Structure. Each declared field within the union
overlays the same address in native memory. When writing a union to native
memory, you <em>must</em> specify which field is to be written by supplying
the desired field's class to the {@link com.sun.jna.Union#setType}
method. On read, all non-pointer-based fields will be initialized from native
memory. Structure, String, and WString members will <em>not</em> be
initialized unless they are selected via {@link com.sun.jna.Union#setType}.
<h3>Java Object arguments</h3>
In some cases, it would seem convenient to pass a Java object as an opaque
@@ -14,9 +14,9 @@ package com.sun.jna.win32;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import com.sun.jna.Callback;
import com.sun.jna.FunctionMapper;
import com.sun.jna.Native;
import com.sun.jna.NativeLibrary;
import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
@@ -13,7 +13,7 @@
package com.sun.jna.win32;
import java.lang.reflect.Method;
import com.sun.jna.Function;
import com.sun.jna.FunctionMapper;
import com.sun.jna.NativeLibrary;
@@ -12,11 +12,9 @@
*/
package com.sun.jna.win32;
import com.sun.jna.ArgumentConverter;
import com.sun.jna.Pointer;
import com.sun.jna.ResultContext;
import com.sun.jna.ResultConverter;
import com.sun.jna.DefaultTypeMapper;
import com.sun.jna.FromNativeContext;
import com.sun.jna.Pointer;
import com.sun.jna.TypeConverter;
import com.sun.jna.TypeMapper;
import com.sun.jna.WString;
@@ -42,7 +40,7 @@ public class W32APITypeMapper extends DefaultTypeMapper {
return null;
return new WString(value.toString());
}
public Object fromNative(Object value, ResultContext context) {
public Object fromNative(Object value, FromNativeContext context) {
if (value == null)
return null;
return ((Pointer)value).getString(0, true);
@@ -51,14 +49,14 @@ public class W32APITypeMapper extends DefaultTypeMapper {
return Pointer.class;
}
};
addArgumentConverter(String.class, stringConverter);
addResultConverter(String.class, stringConverter);
addToNativeConverter(String.class, stringConverter);
addFromNativeConverter(String.class, stringConverter);
}
TypeConverter booleanConverter = new TypeConverter() {
public Object toNative(Object value) {
return new Integer(Boolean.TRUE.equals(value) ? 1 : 0);
}
public Object fromNative(Object value, ResultContext context) {
public Object fromNative(Object value, FromNativeContext context) {
return Boolean.valueOf(((Integer)value).intValue() != 0);
}
public Class nativeType() {
@@ -66,7 +64,7 @@ public class W32APITypeMapper extends DefaultTypeMapper {
return Integer.class;
}
};
addArgumentConverter(Boolean.class, booleanConverter);
addResultConverter(Boolean.class, booleanConverter);
addToNativeConverter(Boolean.class, booleanConverter);
addFromNativeConverter(Boolean.class, booleanConverter);
}
}
@@ -27,8 +27,6 @@ import junit.framework.TestCase;
public class ArgumentsMarshalTest extends TestCase {
public static interface TestLibrary extends Library {
TestLibrary INSTANCE = (TestLibrary)
Native.loadLibrary("testlib", TestLibrary.class);
class CheckFieldAlignment extends Structure {
public byte int8Field = 1;
@@ -41,6 +39,7 @@ public class ArgumentsMarshalTest extends TestCase {
boolean returnBooleanArgument(boolean arg);
byte returnInt8Argument(byte arg);
char returnWideCharArgument(char arg);
short returnInt16Argument(short arg);
int returnInt32Argument(int i);
long returnInt64Argument(long l);
@@ -56,6 +55,7 @@ public class ArgumentsMarshalTest extends TestCase {
long checkInt64ArgumentAlignment(int i, long j, int i2, long j2);
double checkDoubleArgumentAlignment(float i, double j, float i2, double j2);
Pointer testSimpleStructurePointerArgument(CheckFieldAlignment p);
int testStructureArrayInitialization(CheckFieldAlignment[] p, int len);
void modifyStructureArray(CheckFieldAlignment[] p, int length);
int fillInt8Buffer(byte[] buf, int len, byte value);
@@ -75,7 +75,7 @@ public class ArgumentsMarshalTest extends TestCase {
TestLibrary lib;
protected void setUp() {
lib = TestLibrary.INSTANCE;
lib = (TestLibrary)Native.loadLibrary("testlib", TestLibrary.class);
}
protected void tearDown() {
@@ -100,6 +100,18 @@ public class ArgumentsMarshalTest extends TestCase {
assertEquals("Wrong value returned",
b, lib.returnInt8Argument(b));
}
public void testWideCharArgument() {
char c = 0;
assertEquals("Wrong value returned",
c, lib.returnWideCharArgument(c));
c = 0xFFFF;
assertEquals("Wrong value returned",
c, lib.returnWideCharArgument(c));
c = 0x7FFF;
assertEquals("Wrong value returned",
c, lib.returnWideCharArgument(c));
}
public void testInt16Argument() {
short v = 0;
@@ -203,6 +215,22 @@ public class ArgumentsMarshalTest extends TestCase {
struct.getPointer(),
lib.testSimpleStructurePointerArgument(struct));
}
public void testWriteStructureArrayArgumentMemory() {
final int LENGTH = 10;
TestLibrary.CheckFieldAlignment block = new TestLibrary.CheckFieldAlignment();
block.useMemory(new Memory(block.size() * LENGTH));
TestLibrary.CheckFieldAlignment[] array =
new TestLibrary.CheckFieldAlignment[LENGTH];
block.toArray(array);
for (int i=0;i < array.length;i++) {
array[i].int32Field = i;
}
assertEquals("Structure array memory not properly initialized",
-1, lib.testStructureArrayInitialization(array, array.length));
}
public void testUninitializedStructureArrayArgument() {
final int LENGTH = 10;
@@ -28,8 +28,6 @@ import com.sun.jna.ptr.ShortByReference;
public class ByReferenceArgumentsTest extends TestCase {
public static interface TestLibrary extends Library {
TestLibrary INSTANCE = (TestLibrary)
Native.loadLibrary("testlib", TestLibrary.class);
void incrementInt8ByReference(ByteByReference b);
void incrementInt16ByReference(ShortByReference s);
@@ -42,7 +40,7 @@ public class ByReferenceArgumentsTest extends TestCase {
TestLibrary lib;
protected void setUp() {
lib = TestLibrary.INSTANCE;
lib = (TestLibrary)Native.loadLibrary("testlib", TestLibrary.class);
}
protected void tearDown() {
+113 -5
Ver Arquivo
@@ -12,11 +12,11 @@
*/
package com.sun.jna;
import java.lang.ref.WeakReference;
import java.util.Map;
import junit.framework.TestCase;
/** Exercise a range of native methods.
/** Exercise callback-related functionality.
*
* @author twall@users.sf.net
*/
@@ -26,16 +26,22 @@ public class CallbacksTest extends TestCase {
private static final float FLOAT_MAGIC = -118.625f;
public static interface TestLibrary extends Library {
TestLibrary INSTANCE = (TestLibrary)
Native.loadLibrary("testlib", TestLibrary.class);
interface VoidCallback extends Callback {
void callback();
}
void callVoidCallback(VoidCallback c);
interface BooleanCallback extends Callback {
boolean callback(boolean arg, boolean arg2);
}
boolean callBooleanCallback(BooleanCallback c, boolean arg, boolean arg2);
interface Int32Callback extends Callback {
int callback(int arg, int arg2);
}
int callInt32Callback(Int32Callback c, int arg, int arg2);
interface NativeLongCallback extends Callback {
NativeLong callback(NativeLong arg, NativeLong arg2);
}
NativeLong callNativeLongCallback(NativeLongCallback c, NativeLong arg, NativeLong arg2);
interface Int64Callback extends Callback {
long callback(long arg, long arg2);
}
@@ -48,11 +54,26 @@ public class CallbacksTest extends TestCase {
double callback(double arg, double arg2);
}
double callDoubleCallback(DoubleCallback c, double arg, double arg2);
public static class TestStructure extends Structure {
public double value;
}
interface StructureCallback extends Callback {
TestStructure callback(TestStructure arg);
}
TestStructure callStructureCallback(StructureCallback c, TestStructure arg);
interface StringCallback extends Callback {
String callback(String arg);
}
String callStringCallback(StringCallback c, String arg);
interface WideStringCallback extends Callback {
WString callback(WString arg);
}
WString callWideStringCallback(WideStringCallback c, WString arg);
}
TestLibrary lib;
protected void setUp() {
lib = TestLibrary.INSTANCE;
lib = (TestLibrary)Native.loadLibrary("testlib", TestLibrary.class);
}
protected void tearDown() {
@@ -166,6 +187,93 @@ public class CallbacksTest extends TestCase {
assertEquals("Wrong callback return", -3d, value, 0);
}
public void testCallStructureCallback() {
final boolean[] called = {false};
final Structure[] cbarg = { null };
final TestLibrary.TestStructure s = new TestLibrary.TestStructure();
TestLibrary.StructureCallback cb = new TestLibrary.StructureCallback() {
public TestLibrary.TestStructure callback(TestLibrary.TestStructure arg) {
called[0] = true;
cbarg[0] = arg;
return arg;
}
};
TestLibrary.TestStructure value = lib.callStructureCallback(cb, s);
assertTrue("Callback not called", called[0]);
assertEquals("Wrong callback argument", s, cbarg[0]);
assertEquals("Wrong structure return", s, value);
}
public void testCallBooleanCallback() {
final boolean[] called = {false};
final boolean[] cbargs = { false, false };
TestLibrary.BooleanCallback cb = new TestLibrary.BooleanCallback() {
public boolean callback(boolean arg, boolean arg2) {
called[0] = true;
cbargs[0] = arg;
cbargs[1] = arg2;
return arg && arg2;
}
};
boolean value = lib.callBooleanCallback(cb, true, false);
assertTrue("Callback not called", called[0]);
assertEquals("Wrong callback argument 1", true, cbargs[0]);
assertEquals("Wrong callback argument 2", false, cbargs[1]);
assertFalse("Wrong boolean return", value);
}
public void testCallNativeLongCallback() {
final boolean[] called = {false};
final NativeLong[] cbargs = { null, null};
TestLibrary.NativeLongCallback cb = new TestLibrary.NativeLongCallback() {
public NativeLong callback(NativeLong arg, NativeLong arg2) {
called[0] = true;
cbargs[0] = arg;
cbargs[1] = arg2;
return new NativeLong(arg.intValue() + arg2.intValue());
}
};
NativeLong value = lib.callNativeLongCallback(cb, new NativeLong(1), new NativeLong(2));
assertTrue("Callback not called", called[0]);
assertEquals("Wrong callback argument 1", new NativeLong(1), cbargs[0]);
assertEquals("Wrong callback argument 2", new NativeLong(2), cbargs[1]);
assertEquals("Wrong boolean return", new NativeLong(3), value);
}
public void testCallStringCallback() {
final boolean[] called = {false};
final String[] cbargs = { null };
TestLibrary.StringCallback cb = new TestLibrary.StringCallback() {
public String callback(String arg) {
called[0] = true;
cbargs[0] = arg;
return arg;
}
};
final String VALUE = "value";
String value = lib.callStringCallback(cb, VALUE);
assertTrue("Callback not called", called[0]);
assertEquals("Wrong callback argument 1", VALUE, cbargs[0]);
assertEquals("Wrong String return", VALUE, value);
}
public void testCallWideStringCallback() {
final boolean[] called = {false};
final WString[] cbargs = { null };
TestLibrary.WideStringCallback cb = new TestLibrary.WideStringCallback() {
public WString callback(WString arg) {
called[0] = true;
cbargs[0] = arg;
return arg;
}
};
final WString VALUE = new WString("value");
WString value = lib.callWideStringCallback(cb, VALUE);
assertTrue("Callback not called", called[0]);
assertEquals("Wrong callback argument 1", VALUE, cbargs[0]);
assertEquals("Wrong wide string return", VALUE, value);
}
public static void main(java.lang.String[] argList) {
junit.textui.TestRunner.run(CallbacksTest.class);
}
+1 -2
Ver Arquivo
@@ -13,8 +13,7 @@
package com.sun.jna;
import java.awt.Toolkit;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import junit.framework.TestCase;
// TODO: verify load from jna.library.path
+33 -1
Ver Arquivo
@@ -15,8 +15,12 @@ package com.sun.jna;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.Map.Entry;
import junit.framework.TestCase;
import com.sun.jna.Memory;
public class PointerTest extends TestCase {
@@ -103,4 +107,32 @@ public class PointerTest extends TestCase {
assertEquals("Native long mismatch", MAGIC, m.getLong(0));
}
}
public void testSetStringWithEncoding() throws Exception {
String old = System.getProperty("jna.encoding");
String VALUE = "\u0444\u0438\u0441\u0432\u0443";
System.setProperty("jna.encoding", "UTF8");
try {
int size = VALUE.getBytes("UTF8").length+1;
Memory m = new Memory(size);
m.setString(0, VALUE);
assertEquals("UTF8 encoding should be double",
VALUE.length() * 2 + 1, size);
assertEquals("Wrong decoded value", VALUE, m.getString(0));
}
finally {
if (old != null) {
System.setProperty("jna.encoding", old);
}
else {
Map props = System.getProperties();
props.remove("jna.encoding");
Properties newProps = new Properties();
for (Iterator i = props.entrySet().iterator();i.hasNext();) {
Entry e = (Entry)i.next();
newProps.setProperty(e.getKey().toString(), e.getValue().toString());
}
System.setProperties(newProps);
}
}
}
}
+1 -3
Ver Arquivo
@@ -25,8 +25,6 @@ public class ReturnTypesTest extends TestCase {
private static final float FLOAT_MAGIC = -118.625f;
public static interface TestLibrary extends Library {
TestLibrary INSTANCE = (TestLibrary)
Native.loadLibrary("testlib", TestLibrary.class);
public static class TestStructure extends Structure {
public double value;
@@ -59,7 +57,7 @@ public class ReturnTypesTest extends TestCase {
TestLibrary lib;
protected void setUp() {
lib = TestLibrary.INSTANCE;
lib = (TestLibrary)Native.loadLibrary("testlib", TestLibrary.class);
}
protected void tearDown() {
+31 -9
Ver Arquivo
@@ -13,9 +13,11 @@
package com.sun.jna;
import java.util.Map;
import junit.framework.TestCase;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.LongByReference;
import junit.framework.TestCase;
/** TODO: need more alignment tests, especially platform-specific behavior
* @author twall@users.sf.net
@@ -33,7 +35,28 @@ public class StructureTest extends TestCase {
Structure s = new TestStructure();
assertEquals("Wrong size", 4, s.size());
}
public static class TestAllocStructure extends Structure {
public int f0;
public int f1;
public int f2;
public int f3;
}
public void testClearOnAllocate() {
TestAllocStructure s = new TestAllocStructure();
s.read();
assertEquals("Memory not cleared on structure init", 0, s.f0);
assertEquals("Memory not cleared on structure init", 0, s.f1);
assertEquals("Memory not cleared on structure init", 0, s.f2);
assertEquals("Memory not cleared on structure init", 0, s.f3);
s = (TestAllocStructure)s.toArray(2)[1];
assertEquals("Memory not cleared on array init", 0, s.f0);
assertEquals("Memory not cleared on array init", 0, s.f1);
assertEquals("Memory not cleared on array init", 0, s.f2);
assertEquals("Memory not cleared on array init", 0, s.f3);
}
// cross-platform smoke test
public void testGNUCAlignment() {
class TestStructure extends Structure {
@@ -45,7 +68,7 @@ public class StructureTest extends TestCase {
public double d;
}
TestStructure s = new TestStructure();
s.setAlignment(Structure.ALIGN_GNUC);
s.setAlignType(Structure.ALIGN_GNUC);
assertEquals("Wrong structure size", 28, s.size());
}
@@ -60,7 +83,7 @@ public class StructureTest extends TestCase {
public double d;
}
TestStructure s = new TestStructure();
s.setAlignment(Structure.ALIGN_MSVC);
s.setAlignType(Structure.ALIGN_MSVC);
assertEquals("Wrong structure size", 32, s.size());
}
@@ -233,7 +256,7 @@ public class StructureTest extends TestCase {
TestStructure s = new TestStructure();
if (NativeLong.SIZE == 8) {
final long MAGIC = 0x1234567887654321L;
s.getPointer().setLong(4, MAGIC);
s.getPointer().setLong(8, MAGIC);
s.read();
assertEquals("NativeLong field mismatch", MAGIC, s.l.longValue());
}
@@ -255,7 +278,7 @@ public class StructureTest extends TestCase {
final long MAGIC = 0x1234567887654321L;
s.l = new NativeLong(MAGIC);
s.write();
long l = s.getPointer().getLong(4);
long l = s.getPointer().getLong(8);
assertEquals("NativeLong field mismatch", MAGIC, l);
}
else {
@@ -283,8 +306,6 @@ public class StructureTest extends TestCase {
public Callback cb;
}
static interface CbTest extends Library {
CbTest INSTANCE = (CbTest)
Native.loadLibrary("testlib", CbTest.class);
public void callCallbackInStruct(CbStruct cbstruct);
}
public void testCallbackWrite() {
@@ -310,7 +331,8 @@ public class StructureTest extends TestCase {
flag[0] = true;
}
};
CbTest.INSTANCE.callCallbackInStruct(s);
CbTest lib = (CbTest)Native.loadLibrary("testlib", CbTest.class);
lib.callCallbackInStruct(s);
assertTrue("Callback not invoked", flag[0]);
}
}
+49 -10
Ver Arquivo
@@ -30,7 +30,7 @@ public class TypeMapperTest extends TestCase {
final int MAGIC = 0xABEDCF23;
Map options = new HashMap();
DefaultTypeMapper mapper = new DefaultTypeMapper();
mapper.addArgumentConverter(Boolean.class, new ArgumentConverter() {
mapper.addToNativeConverter(Boolean.class, new ToNativeConverter() {
public Object toNative(Object arg) {
return new Integer(Boolean.TRUE.equals(arg) ? MAGIC : 0);
}
@@ -43,7 +43,7 @@ public class TypeMapperTest extends TestCase {
}
public void testStringToIntArgumentConversion() {
DefaultTypeMapper mapper = new DefaultTypeMapper();
mapper.addArgumentConverter(String.class, new ArgumentConverter() {
mapper.addToNativeConverter(String.class, new ToNativeConverter() {
public Object toNative(Object arg) {
return Integer.valueOf((String) arg, 16);
}
@@ -58,7 +58,7 @@ public class TypeMapperTest extends TestCase {
}
public void testCharSequenceToIntArgumentConversion() {
DefaultTypeMapper mapper = new DefaultTypeMapper();
mapper.addArgumentConverter(CharSequence.class, new ArgumentConverter() {
mapper.addToNativeConverter(CharSequence.class, new ToNativeConverter() {
public Object toNative(Object arg) {
return Integer.valueOf(((CharSequence)arg).toString(), 16);
}
@@ -74,7 +74,7 @@ public class TypeMapperTest extends TestCase {
}
public void testNumberToIntArgumentConversion() {
DefaultTypeMapper mapper = new DefaultTypeMapper();
mapper.addArgumentConverter(Double.class, new ArgumentConverter() {
mapper.addToNativeConverter(Double.class, new ToNativeConverter() {
public Object toNative(Object arg) {
return new Integer(((Double)arg).intValue());
}
@@ -95,13 +95,13 @@ public class TypeMapperTest extends TestCase {
final int MAGIC = 0xABEDCF23;
Map options = new HashMap();
DefaultTypeMapper mapper = new DefaultTypeMapper();
mapper.addArgumentConverter(Boolean.class, new ArgumentConverter() {
mapper.addToNativeConverter(Boolean.class, new ToNativeConverter() {
public Object toNative(Object value) {
return new Integer(Boolean.TRUE.equals(value) ? MAGIC : 0);
}
});
mapper.addResultConverter(Boolean.class, new ResultConverter() {
public Object fromNative(Object value, ResultContext context) {
mapper.addFromNativeConverter(Boolean.class, new FromNativeConverter() {
public Object fromNative(Object value, FromNativeContext context) {
return Boolean.valueOf(((Integer) value).intValue() == MAGIC);
}
public Class nativeType() {
@@ -130,15 +130,15 @@ public class TypeMapperTest extends TestCase {
public Object toNative(Object value) {
return new Integer(Boolean.TRUE.equals(value) ? 1 : 0);
}
public Object fromNative(Object value, ResultContext context) {
public Object fromNative(Object value, FromNativeContext context) {
return new Boolean(((Integer)value).intValue() == 1);
}
public Class nativeType() {
return Integer.class;
}
};
mapper.addArgumentConverter(Boolean.class, converter);
mapper.addResultConverter(Boolean.class, converter);
mapper.addToNativeConverter(Boolean.class, converter);
mapper.addFromNativeConverter(Boolean.class, converter);
Map options = new HashMap();
options.put(Library.OPTION_TYPE_MAPPER, mapper);
StructureTestLibrary lib = (StructureTestLibrary)
@@ -154,4 +154,43 @@ public class TypeMapperTest extends TestCase {
s.read();
assertFalse("Wrong value read", s.data);
}
public static interface CallbackTestLibrary extends Library {
interface Int32Callback extends Callback {
float callback(float arg, float arg2);
}
float callInt32Callback(Int32Callback c, float arg, float arg2);
}
public void testCallbackArgumentConversion() throws Exception {
final DefaultTypeMapper mapper = new DefaultTypeMapper();
Map options = new HashMap() {
{ put(Library.OPTION_TYPE_MAPPER, mapper); }
};
CallbackTestLibrary lib = (CallbackTestLibrary)
Native.loadLibrary("testlib", CallbackTestLibrary.class, options);
// Convert java floats into native integers and back
TypeConverter converter = new TypeConverter() {
public Object fromNative(Object value, FromNativeContext context) {
return new Float(((Integer)value).intValue());
}
public Class nativeType() {
return Integer.class;
}
public Object toNative(Object value) {
return new Integer(Math.round(((Float)value).floatValue()));
}
};
mapper.addToNativeConverter(float.class, converter);
mapper.addFromNativeConverter(float.class, converter);
CallbackTestLibrary.Int32Callback cb = new CallbackTestLibrary.Int32Callback() {
public float callback(float arg, float arg2) {
return arg + arg2;
}
};
assertEquals("Wrong result", 0, lib.callInt32Callback(cb, 0, 0), 0);
assertEquals("Wrong result", 1, lib.callInt32Callback(cb, 0, 1), 0);
assertEquals("Wrong result", 2, lib.callInt32Callback(cb, 1, 1), 0);
assertEquals("Wrong result", -2, lib.callInt32Callback(cb, -1, -1), 0);
}
}
+64
Ver Arquivo
@@ -0,0 +1,64 @@
/* Copyright (c) 2007 Timothy Wall, All Rights Reserved
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package com.sun.jna;
import junit.framework.TestCase;
public class UnionTest extends TestCase {
public static class TestStructure extends Structure {
public String value;
}
public static class SizedUnion extends Union {
public byte byteField;
public short shortField;
public int intField;
public long longField;
public TestStructure structField;
public String string;
public WString wstring;
}
public void testCalculateSize() {
Union u = new SizedUnion();
assertEquals("Union should be size of largest field", 8, u.size());
}
public void testWriteUnion() {
SizedUnion u = new SizedUnion();
final int VALUE = 0x12345678;
u.intField = VALUE;
u.setType(int.class);
u.write();
assertEquals("Wrong value written", VALUE, u.getPointer().getInt(0));
}
public void testReadUnion() {
SizedUnion u = new SizedUnion();
final int VALUE = 0x12345678;
u.getPointer().setInt(0, VALUE);
u.read();
assertEquals("int field not read properly", VALUE, u.intField);
assertTrue("byte field not read", u.byteField != 0);
assertTrue("short field not read", u.shortField != 0);
assertTrue("long field not read", u.longField != 0);
assertNull("Unselected structure should not be read", u.structField.value);
assertNull("Unselected String should be null", u.string);
assertNull("Unselected WString should be null", u.wstring);
}
public static void main(String[] args) {
junit.textui.TestRunner.run(UnionTest.class);
}
}
+18 -13
Ver Arquivo
@@ -21,55 +21,60 @@ public class VarArgsTest extends TestCase {
public static class TestStructure extends Structure {
public int magic = 0;
}
TestLibrary INSTANCE = (TestLibrary)
Native.loadLibrary("testlib", TestLibrary.class);
public int addInt32VarArgs(String fmt, Object[] args);
public int addInt32VarArgs(String fmt, Number[] args);
public String returnStringVarArgs(String fmt, Object[] args);
public void modifyStructureVarArgs(String fmt, Object arg1, Object[] args);
}
TestLibrary lib;
protected void setUp() {
lib = (TestLibrary)Native.loadLibrary("testlib", TestLibrary.class);
}
protected void tearDown() {
lib = null;
}
public void testIntVarArgs() {
Object[] args = new Object[2];
Integer[] args = new Integer[2];
int arg1 = 1;
int arg2 = 2;
args[0] = new Integer(arg1);
args[1] = new Integer(arg2);
assertEquals("VarArgs not added correctly", arg1 + arg2,
TestLibrary.INSTANCE.addInt32VarArgs("dd", args));
lib.addInt32VarArgs("dd", args));
}
public void testShortVarArgs() {
Object[] args = new Object[2];
Short[] args = new Short[2];
short arg1 = 1;
short arg2 = 2;
args[0] = new Short(arg1);
args[1] = new Short(arg2);
assertEquals("VarArgs not added correctly", arg1 + arg2,
TestLibrary.INSTANCE.addInt32VarArgs("dd", args));
lib.addInt32VarArgs("dd", args));
}
public void testLongVarArgs() {
Object[] args = new Object[2];
Long[] args = new Long[2];
short arg1 = 1;
short arg2 = 2;
args[0] = new Long(arg1);
args[1] = new Long(arg2);
assertEquals("VarArgs not added correctly", arg1 + arg2,
TestLibrary.INSTANCE.addInt32VarArgs("ll", args));
lib.addInt32VarArgs("ll", args));
}
public void testStringVarArgs() {
Object[] args = new Object[] { "Test" };
assertEquals("Did not return correct string", args[0],
TestLibrary.INSTANCE.returnStringVarArgs("", args));
lib.returnStringVarArgs("", args));
}
public void testAppendNullToVarargs() {
Object[] args = new Object[] { new Integer(1) };
Number[] args = new Number[] { new Integer(1) };
assertEquals("No trailing NULL was appended to varargs list",
1, TestLibrary.INSTANCE.addInt32VarArgs("dd", args));
1, lib.addInt32VarArgs("dd", args));
}
public void testModifyStructureInVarargs() {
TestStructure arg1 = new TestStructure();
TestStructure[] varargs = new TestStructure[] { new TestStructure() };
TestLibrary.INSTANCE.modifyStructureVarArgs("ss", arg1, varargs);
lib.modifyStructureVarArgs("ss", arg1, varargs);
assertEquals("Structure memory not read in fixed arg w/varargs",
MAGIC32, arg1.magic);
assertEquals("Structure memory not read in varargs",
@@ -17,6 +17,7 @@ import java.io.FileOutputStream;
import java.util.HashMap;
import java.util.Map;
import junit.framework.TestCase;
import com.sun.jna.Platform;
import com.sun.jna.examples.FileMonitor.FileEvent;
import com.sun.jna.examples.FileMonitor.FileListener;
@@ -41,6 +42,8 @@ public class FileMonitorTest extends TestCase {
}
public void testNotifyOnFileCreation() throws Exception {
if (!Platform.isWindows()) return;
File file = File.createTempFile(getName(), ".tmp", dir);
file.deleteOnExit();
FileEvent event = (FileEvent)events.get(new Integer(FileMonitor.FILE_CREATED));
@@ -55,6 +58,8 @@ public class FileMonitorTest extends TestCase {
}
public void testNotifyOnFileDelete() throws Exception {
if (!Platform.isWindows()) return;
File file = File.createTempFile(getName(), ".tmp", dir);
file.delete();
FileEvent event = (FileEvent)events.get(new Integer(FileMonitor.FILE_DELETED));
@@ -69,6 +74,8 @@ public class FileMonitorTest extends TestCase {
}
public void testNotifyOnFileRename() throws Exception {
if (!Platform.isWindows()) return;
File file = File.createTempFile(getName(), ".tmp", dir);
File newFile = new File(file.getParentFile(), "newfile");
newFile.deleteOnExit();
@@ -90,6 +97,8 @@ public class FileMonitorTest extends TestCase {
}
public void testNotifyOnFileModification() throws Exception {
if (!Platform.isWindows()) return;
File file = File.createTempFile(getName(), ".tmp", dir);
file.deleteOnExit();
FileOutputStream os = new FileOutputStream(file);
@@ -15,13 +15,14 @@ package com.sun.jna.examples;
import java.awt.GraphicsEnvironment;
import java.awt.Robot;
import java.awt.event.KeyEvent;
import com.sun.jna.Platform;
import junit.framework.TestCase;
public class KeyboardUtilsTest extends TestCase {
public void testIsPressed() throws Exception {
// Can't run this test headless
if (GraphicsEnvironment.isHeadless())
// Can't run this test headless; not yet implemented on mac
if (GraphicsEnvironment.isHeadless() || Platform.isMac())
return;
Robot robot = new Robot();
@@ -16,7 +16,6 @@ import java.awt.Color;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.Point;
@@ -25,12 +24,13 @@ import java.awt.Robot;
import java.awt.Window;
import java.awt.event.MouseEvent;
import java.awt.geom.Area;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JWindow;
import javax.swing.SwingUtilities;
import javax.swing.event.MouseInputAdapter;
import junit.framework.TestCase;
// TODO: test method invocations before/after pack, before/after setvisible
@@ -0,0 +1,51 @@
/* Copyright (c) 2007 Timothy Wall, All Rights Reserved
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package com.sun.jna.examples.win32;
import java.util.Calendar;
import java.util.TimeZone;
import junit.framework.TestCase;
public class Kernel32Test extends TestCase {
public void testStructureOutArgument() {
Kernel32 kernel = Kernel32.INSTANCE;
Kernel32.SYSTEMTIME time = new Kernel32.SYSTEMTIME();
kernel.GetSystemTime(time);
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
assertEquals("Hour not properly set",
cal.get(Calendar.HOUR_OF_DAY), time.wHour);
assertEquals("Day not properly set",
cal.get(Calendar.DAY_OF_WEEK)-1,
time.wDayOfWeek);
assertEquals("Year not properly set",
cal.get(Calendar.YEAR), time.wYear);
}
public void testGetLastError() {
Kernel32 kernel = Kernel32.INSTANCE;
kernel.GetLastError();
if (kernel.GetProcessId(null) == 0) {
final int INVALID_HANDLE = 6;
int code = kernel.GetLastError();
assertEquals("GetLastError failed", INVALID_HANDLE, code);
// Unclear why this fails
//int ERRCODE = 8;
//kernel.SetLastError(ERRCODE);
//assertEquals("Wrong GetLastError value", ERRCODE, kernel.GetLastError());
}
else {
fail("GetProcessId(NULL) should fail");
}
}
}
@@ -10,7 +10,7 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package com.sun.jna.examples.win32;
package com.sun.jna.win32;
import com.sun.jna.Library;
import com.sun.jna.Native;
@@ -10,27 +10,16 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package com.sun.jna.examples.win32;
package com.sun.jna.win32;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Robot;
import java.awt.event.InputEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.lang.reflect.Method;
import java.util.Calendar;
import java.util.HashMap;
import java.util.TimeZone;
import javax.swing.JFrame;
import javax.swing.JLabel;
import junit.framework.TestCase;
import com.sun.jna.Callback;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.NativeLibrary;
import com.sun.jna.Pointer;
import com.sun.jna.win32.StdCallLibrary;
/**
* @author twall@users.sf.net
@@ -38,10 +27,6 @@ import com.sun.jna.win32.StdCallLibrary;
public class W32StdCallTest extends TestCase {
public static interface TestLibrary extends StdCallLibrary {
TestLibrary INSTANCE = (TestLibrary)
Native.loadLibrary("testlib", TestLibrary.class, new HashMap() {
{ put(OPTION_FUNCTION_MAPPER, FUNCTION_MAPPER); }
});
int returnInt32ArgumentStdCall(int arg);
interface Int32Callback extends StdCallCallback {
int callback(int arg, int arg2);
@@ -56,27 +41,16 @@ public class W32StdCallTest extends TestCase {
private TestLibrary testlib;
protected void setUp() {
testlib = TestLibrary.INSTANCE;
testlib = (TestLibrary)
Native.loadLibrary("testlib", TestLibrary.class, new HashMap() {
{ put(Library.OPTION_FUNCTION_MAPPER, StdCallLibrary.FUNCTION_MAPPER); }
});
}
protected void tearDown() {
testlib = null;
}
public void testStructureOutArgument() {
Kernel32 kernel = Kernel32.INSTANCE;
Kernel32.SYSTEMTIME time = new Kernel32.SYSTEMTIME();
kernel.GetSystemTime(time);
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
assertEquals("Hour not properly set",
cal.get(Calendar.HOUR_OF_DAY), time.wHour);
assertEquals("Day not properly set",
cal.get(Calendar.DAY_OF_WEEK)-1,
time.wDayOfWeek);
assertEquals("Year not properly set",
cal.get(Calendar.YEAR), time.wYear);
}
public void testFunctionMapper() throws Exception {
NativeLibrary lib = NativeLibrary.getInstance("testlib");
Method m = TestLibrary.class.getMethod("returnInt32ArgumentStdCall", new Class[] { int.class });
@@ -102,11 +76,11 @@ public class W32StdCallTest extends TestCase {
};
final int EXPECTED = MAGIC*3;
int value = testlib.callInt32StdCallCallback(cb, MAGIC, MAGIC*2);
assertTrue("__stdcall callback not called", called[0]);
assertEquals("Wrong __stdcall callback value", Integer.toHexString(EXPECTED),
assertTrue("stdcall callback not called", called[0]);
assertEquals("Wrong stdcall callback value", Integer.toHexString(EXPECTED),
Integer.toHexString(value));
value = testlib.callInt32StdCallCallback(cb, -1, -2);
assertEquals("Wrong __stdcall callback return", -3, value);
assertEquals("Wrong stdcall callback return", -3, value);
}
}
Arquivo binário não exibido.
Arquivo binário não exibido.
Arquivo binário não exibido.
Arquivo binário não exibido.
Arquivo binário não exibido.
Arquivo binário não exibido.
+45 -7
Ver Arquivo
@@ -3,7 +3,7 @@
<meta name="author" content="Timothy Wall">
<meta name="keywords" content="java,jna,jni,c/c++,native,method,function,call,ctypes,ffi,foreign function interface,jdirect,jinvoke,pinvoke,platform invoke,native library access,native access,call native from java,java c library,easy jni,call c code from java,avoid jni">
<meta name="description" content="Java Native Access (JNA): access native libraries with pure Java code.">
<meta name="date" content="2007-06-08">
<meta name="date" content="2007-06-15">
<title>Java Native Access (JNA): Pure Java access to native libraries</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
@@ -33,7 +33,9 @@ which includes an overview of specific usage.<p>
<li>Complete automated build and test of Java and native code
<li>JUnit test coverage
<li>Builds/runs on 1.4 VMs (annotations are no longer used)
<!--<li>Customizable argument and return value conversions-->
<li>Customizable argument and return value conversions
<li>Customizable mapping from Java method to native function name
<li>Support for automatic w32 ASCII/UNICODE mappings
</ul>
<h3>Community</h3>
@@ -51,10 +53,9 @@ which includes an overview of specific usage.<p>
<li>More comprehensive documentation on using JNA, including examples of Java to native conversions of data types, function usage, and proper memory management.</li>
<li>Native library definitions for the more useful libraries on various platforms; for example, <code>user32</code> on Windows. This is important not for having an exhaustive library definition but to illustrate all the different ways a native library may need to be mapped.</li>
<li>Peer review the design and suggest improvements and enhancements</li>
<li>Port the <code>jnidispatch</code> library to Solaris and any other desired platform (the v3 branch is using libffi from gcc, so it may work out of the box if we can just get access to the appropriate build platform).</li>
<li>Build the <code>jnidispatch</code> library backend on new platforms (the v3 branch is using libffi from gcc, so it should mostly work out of the box if we can just get access to the appropriate build platform).</li>
<li>Testing on various JDK versions and platforms (linux flavors!).</li>
<li>Documentation on multithreaded usage of JNA: Likely danger areas, failure modes, best practices.</li>
<li>Tests of JNA overhead compared to straight JNI calls (Todd Fast did some of this a long time ago and the results were quite favorable, but it would be nice to have some more recent quantitative data).</li>
<li>Tips and recommended usage of JNA: Likely danger areas, failure modes, best practices, multithreading, etc.</li>
</ul>
<h3>How To Get Started Using JNA</h3>
<p>Java Native Access (JNA) has a single component, <code>jna.jar</code>; the supporting native library (<code>jnidispatch</code>) is included in the jar file to avoid extra configuration steps. JNA is capable of extracting and loading the library on its own, so you don't need to reconfigure your native library path in any way. The native library is also available in a platform-specific jar file for use with Java Web Start.</p>
@@ -122,7 +123,9 @@ void fill_buffer(int[] buf, int len);
</textarea>
</blockquote>
When passing in an array of <code>Structure</code>, it is not necessary to initialize the array, unless the function is using the data as input. If you <em>do</em> initialize the array, all structure members must use the same <code>Memory</code> object at the appropriate corresponding offset (see Structure.useMemory()).
When passing in an array of <code>Structure</code>, it is not necessary to initialize the array, unless the function is using the data as input. If you <em>do</em> need to initialize the array, you should use the <code>Structure.toArray</code> method to obtain an array of elements continuous in memory.
<p>
Arrays of C strings (the <code>char* argv[]</code> to the C <code>main</code>, for example), may be represented by <code>String[]</code> in Java code.
<h3>By-reference Arguments</h3>
When a function accepts a pointer-to-type argument you can use one of the <a href="javadoc/com/sun/jna/ptr/ByReference.html"><code>ByReference</code></a> types to capture the returned value. For example:<br>
@@ -145,14 +148,48 @@ byte[] buffer = p.getByteArray(0, iref.getValue());
The <a href="javadoc/com/sun/jna/Pointer.html"><code>Pointer</code></a> class provides a number of accessor methods similar to <a href="javadoc/com/sun/jna/Pointer.html#getByteArray"><code>getByteArray</code></a> which effectively function as a typecast onto the memory.
<h3>Custom Type and Function Mapping</h3>
The <a href="javadoc/com/sun/jna/TypeMapper.html">TypeMapper</a> class and related interfaces provide for converting any Java type used as an argument, return value, or structure member to be converted to or from a native type. The example w32 API interfaces use a type mapper to convert Java boolean into the w32 BOOL type.
<p>
Java interface methods may also be arbitrarily mapped onto a native function. The <a href="javadoc/com/sun/jna/win32/StdCallFunctionMapper.html">StdCallFunctionMapper</a> is one implementation which automatically generates <code>stdcall</code>-decorated function names from a Java interface method signature.
<h3>Callbacks</h3>
Callback declarations consist of a simple interface that extends the Callback
Callback declarations consist of a simple interface that extends the <a href="javadoc/com/sun/jna/Callback.html">Callback</a>
interface and implements a <code>callback</code> method. Callbacks are
implemented by wrapping a Java object method in a little bit of C glue code.
The simplest usage resembles using anonymous inner classes to register event
listeners. Following is an example of callback usage:<br>
<blockquote>
<textarea name="textarea4" cols="80" rows="10" readonly="readonly">
// C code
typedef void (*FUNCTION)();
int atexit(FUNCTION);
// Java code
public interface CLibrary extends Library {
interface FUNCTION extends Callback {
void callback();
}
int atexit(FUNCTION fn);
}
...
CLibrary lib = CLibrary.INSTANCE;
lib.atexit(new FUNCTION() {
public void callback() {
System.out.println("exit was called");
}
});
</textarea>
</blockquote>
Here is a more involved example, using the w32 APIs:
<blockquote>
<textarea name="textarea4" cols="80" rows="17" readonly="readonly">
// C code
typedef int (__stdcall *WNDENUMPROC)(void*,void*);
int __stdcall EnumWindows(WNDENUMPROC,void*);
// Java code
public interface User32 extends StdCallLibrary {
interface WNDENUMPROC extends StdCallCallback {
/** Return whether to continue enumeration. */
@@ -172,6 +209,7 @@ user32.EnumWindows(new WNDENUMPROC() {
}, null);
</textarea>
</blockquote>
If your callback needs to live beyond the method invocation where it is used, make sure you keep a reference to it or the native code will call back to an empty stub after the callback object is garbage collected.<p>
See the <a href="javadoc/overview-summary.html">JavaDoc overview</a> for additional details.<p>
<h3>Invocation from Dynamically-Typed Languages</h3>
+1 -1
Ver Arquivo
@@ -2,7 +2,7 @@
<!--NewPage-->
<HTML>
<HEAD>
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 13:50:33 EDT 2007 -->
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 14:23:07 EDT 2007 -->
<TITLE>
All Classes (JNA API)
</TITLE>
+1 -1
Ver Arquivo
@@ -2,7 +2,7 @@
<!--NewPage-->
<HTML>
<HEAD>
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 13:50:33 EDT 2007 -->
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 14:23:07 EDT 2007 -->
<TITLE>
All Classes (JNA API)
</TITLE>
@@ -2,7 +2,7 @@
<!--NewPage-->
<HTML>
<HEAD>
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 13:50:35 EDT 2007 -->
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 14:23:08 EDT 2007 -->
<TITLE>
AltCallingConvention (JNA API)
</TITLE>
+1 -1
Ver Arquivo
@@ -2,7 +2,7 @@
<!--NewPage-->
<HTML>
<HEAD>
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 13:50:35 EDT 2007 -->
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 14:23:08 EDT 2007 -->
<TITLE>
ArgumentConverter (JNA API)
</TITLE>
+1 -1
Ver Arquivo
@@ -2,7 +2,7 @@
<!--NewPage-->
<HTML>
<HEAD>
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 13:50:35 EDT 2007 -->
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 14:23:08 EDT 2007 -->
<TITLE>
Callback (JNA API)
</TITLE>
+1 -1
Ver Arquivo
@@ -2,7 +2,7 @@
<!--NewPage-->
<HTML>
<HEAD>
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 13:50:35 EDT 2007 -->
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 14:23:09 EDT 2007 -->
<TITLE>
CallbackReference (JNA API)
</TITLE>
+1 -1
Ver Arquivo
@@ -2,7 +2,7 @@
<!--NewPage-->
<HTML>
<HEAD>
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 13:50:35 EDT 2007 -->
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 14:23:09 EDT 2007 -->
<TITLE>
DefaultTypeMapper (JNA API)
</TITLE>
+139 -1
Ver Arquivo
@@ -2,7 +2,7 @@
<!--NewPage-->
<HTML>
<HEAD>
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 13:50:35 EDT 2007 -->
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 14:23:09 EDT 2007 -->
<TITLE>
Function (JNA API)
</TITLE>
@@ -296,6 +296,15 @@ An abstraction for a native function pointer. An instance of
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
<CODE>&nbsp;double</CODE></FONT></TD>
<TD><CODE><B><A HREF="../../../com/sun/jna/Function.html#invokeDouble(java.lang.Object[])">invokeDouble</A></B>(<A HREF="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html" title="class or interface in java.lang">Object</A>[]&nbsp;args)</CODE>
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Convenience method for
<A HREF="../../../com/sun/jna/Function.html#invoke(java.lang.Class, java.lang.Object[])"><CODE>invoke(Double.class, args)</CODE></A>.</TD>
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
<CODE>&nbsp;float</CODE></FONT></TD>
<TD><CODE><B><A HREF="../../../com/sun/jna/Function.html#invokeFloat(int, java.lang.Object[])">invokeFloat</A></B>(int&nbsp;callingConvention,
<A HREF="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html" title="class or interface in java.lang">Object</A>[]&nbsp;args)</CODE>
@@ -305,6 +314,15 @@ An abstraction for a native function pointer. An instance of
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
<CODE>&nbsp;float</CODE></FONT></TD>
<TD><CODE><B><A HREF="../../../com/sun/jna/Function.html#invokeFloat(java.lang.Object[])">invokeFloat</A></B>(<A HREF="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html" title="class or interface in java.lang">Object</A>[]&nbsp;args)</CODE>
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Convenience method for
<A HREF="../../../com/sun/jna/Function.html#invoke(java.lang.Class, java.lang.Object[])"><CODE>invoke(Float.class, args)</CODE></A>.</TD>
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
<CODE>&nbsp;int</CODE></FONT></TD>
<TD><CODE><B><A HREF="../../../com/sun/jna/Function.html#invokeInt(int, java.lang.Object[])">invokeInt</A></B>(int&nbsp;callingConvention,
<A HREF="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html" title="class or interface in java.lang">Object</A>[]&nbsp;args)</CODE>
@@ -314,6 +332,15 @@ An abstraction for a native function pointer. An instance of
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
<CODE>&nbsp;int</CODE></FONT></TD>
<TD><CODE><B><A HREF="../../../com/sun/jna/Function.html#invokeInt(java.lang.Object[])">invokeInt</A></B>(<A HREF="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html" title="class or interface in java.lang">Object</A>[]&nbsp;args)</CODE>
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Convenience method for
<A HREF="../../../com/sun/jna/Function.html#invoke(java.lang.Class, java.lang.Object[])"><CODE>invoke(Integer.class, args)</CODE></A>.</TD>
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
<CODE>&nbsp;long</CODE></FONT></TD>
<TD><CODE><B><A HREF="../../../com/sun/jna/Function.html#invokeLong(int, java.lang.Object[])">invokeLong</A></B>(int&nbsp;callingConvention,
<A HREF="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html" title="class or interface in java.lang">Object</A>[]&nbsp;args)</CODE>
@@ -323,6 +350,15 @@ An abstraction for a native function pointer. An instance of
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
<CODE>&nbsp;long</CODE></FONT></TD>
<TD><CODE><B><A HREF="../../../com/sun/jna/Function.html#invokeLong(java.lang.Object[])">invokeLong</A></B>(<A HREF="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html" title="class or interface in java.lang">Object</A>[]&nbsp;args)</CODE>
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Convenience method for
<A HREF="../../../com/sun/jna/Function.html#invoke(java.lang.Class, java.lang.Object[])"><CODE>invoke(Long.class, args)</CODE></A>.</TD>
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
<CODE>&nbsp;<A HREF="../../../com/sun/jna/Pointer.html" title="class in com.sun.jna">Pointer</A></CODE></FONT></TD>
<TD><CODE><B><A HREF="../../../com/sun/jna/Function.html#invokePointer(int, java.lang.Object[])">invokePointer</A></B>(int&nbsp;callingConvention,
<A HREF="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html" title="class or interface in java.lang">Object</A>[]&nbsp;args)</CODE>
@@ -332,6 +368,15 @@ An abstraction for a native function pointer. An instance of
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
<CODE>&nbsp;<A HREF="../../../com/sun/jna/Pointer.html" title="class in com.sun.jna">Pointer</A></CODE></FONT></TD>
<TD><CODE><B><A HREF="../../../com/sun/jna/Function.html#invokePointer(java.lang.Object[])">invokePointer</A></B>(<A HREF="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html" title="class or interface in java.lang">Object</A>[]&nbsp;args)</CODE>
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Convenience method for
<A HREF="../../../com/sun/jna/Function.html#invoke(java.lang.Class, java.lang.Object[])"><CODE>invoke(Pointer.class, args)</CODE></A>.</TD>
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
<CODE>&nbsp;<A HREF="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/String.html" title="class or interface in java.lang">String</A></CODE></FONT></TD>
<TD><CODE><B><A HREF="../../../com/sun/jna/Function.html#invokeString(java.lang.Object[], boolean)">invokeString</A></B>(<A HREF="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html" title="class or interface in java.lang">Object</A>[]&nbsp;args,
boolean&nbsp;wide)</CODE>
@@ -350,6 +395,15 @@ An abstraction for a native function pointer. An instance of
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
<CODE>&nbsp;void</CODE></FONT></TD>
<TD><CODE><B><A HREF="../../../com/sun/jna/Function.html#invokeVoid(java.lang.Object[])">invokeVoid</A></B>(<A HREF="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html" title="class or interface in java.lang">Object</A>[]&nbsp;args)</CODE>
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Convenience method for
<A HREF="../../../com/sun/jna/Function.html#invoke(java.lang.Class, java.lang.Object[])"><CODE>invoke(Void.class, args)</CODE></A>.</TD>
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
<CODE>&nbsp;<A HREF="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/String.html" title="class or interface in java.lang">String</A></CODE></FONT></TD>
<TD><CODE><B><A HREF="../../../com/sun/jna/Function.html#toString()">toString</A></B>()</CODE>
@@ -728,6 +782,90 @@ public <A HREF="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/String.html" t
</DL>
</DD>
</DL>
<HR>
<A NAME="invokePointer(java.lang.Object[])"><!-- --></A><H3>
invokePointer</H3>
<PRE>
public <A HREF="../../../com/sun/jna/Pointer.html" title="class in com.sun.jna">Pointer</A> <B>invokePointer</B>(<A HREF="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html" title="class or interface in java.lang">Object</A>[]&nbsp;args)</PRE>
<DL>
<DD>Convenience method for
<A HREF="../../../com/sun/jna/Function.html#invoke(java.lang.Class, java.lang.Object[])"><CODE>invoke(Pointer.class, args)</CODE></A>.
<P>
<DD><DL>
</DL>
</DD>
</DL>
<HR>
<A NAME="invokeInt(java.lang.Object[])"><!-- --></A><H3>
invokeInt</H3>
<PRE>
public int <B>invokeInt</B>(<A HREF="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html" title="class or interface in java.lang">Object</A>[]&nbsp;args)</PRE>
<DL>
<DD>Convenience method for
<A HREF="../../../com/sun/jna/Function.html#invoke(java.lang.Class, java.lang.Object[])"><CODE>invoke(Integer.class, args)</CODE></A>.
<P>
<DD><DL>
</DL>
</DD>
</DL>
<HR>
<A NAME="invokeLong(java.lang.Object[])"><!-- --></A><H3>
invokeLong</H3>
<PRE>
public long <B>invokeLong</B>(<A HREF="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html" title="class or interface in java.lang">Object</A>[]&nbsp;args)</PRE>
<DL>
<DD>Convenience method for
<A HREF="../../../com/sun/jna/Function.html#invoke(java.lang.Class, java.lang.Object[])"><CODE>invoke(Long.class, args)</CODE></A>.
<P>
<DD><DL>
</DL>
</DD>
</DL>
<HR>
<A NAME="invokeFloat(java.lang.Object[])"><!-- --></A><H3>
invokeFloat</H3>
<PRE>
public float <B>invokeFloat</B>(<A HREF="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html" title="class or interface in java.lang">Object</A>[]&nbsp;args)</PRE>
<DL>
<DD>Convenience method for
<A HREF="../../../com/sun/jna/Function.html#invoke(java.lang.Class, java.lang.Object[])"><CODE>invoke(Float.class, args)</CODE></A>.
<P>
<DD><DL>
</DL>
</DD>
</DL>
<HR>
<A NAME="invokeDouble(java.lang.Object[])"><!-- --></A><H3>
invokeDouble</H3>
<PRE>
public double <B>invokeDouble</B>(<A HREF="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html" title="class or interface in java.lang">Object</A>[]&nbsp;args)</PRE>
<DL>
<DD>Convenience method for
<A HREF="../../../com/sun/jna/Function.html#invoke(java.lang.Class, java.lang.Object[])"><CODE>invoke(Double.class, args)</CODE></A>.
<P>
<DD><DL>
</DL>
</DD>
</DL>
<HR>
<A NAME="invokeVoid(java.lang.Object[])"><!-- --></A><H3>
invokeVoid</H3>
<PRE>
public void <B>invokeVoid</B>(<A HREF="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html" title="class or interface in java.lang">Object</A>[]&nbsp;args)</PRE>
<DL>
<DD>Convenience method for
<A HREF="../../../com/sun/jna/Function.html#invoke(java.lang.Class, java.lang.Object[])"><CODE>invoke(Void.class, args)</CODE></A>.
<P>
<DD><DL>
</DL>
</DD>
</DL>
<!-- ========= END OF CLASS DATA ========= -->
<HR>
+1 -1
Ver Arquivo
@@ -2,7 +2,7 @@
<!--NewPage-->
<HTML>
<HEAD>
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 13:50:35 EDT 2007 -->
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 14:23:08 EDT 2007 -->
<TITLE>
FunctionMapper (JNA API)
</TITLE>
@@ -2,7 +2,7 @@
<!--NewPage-->
<HTML>
<HEAD>
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 13:50:35 EDT 2007 -->
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 14:23:09 EDT 2007 -->
<TITLE>
FunctionResultContext (JNA API)
</TITLE>
+1 -1
Ver Arquivo
@@ -2,7 +2,7 @@
<!--NewPage-->
<HTML>
<HEAD>
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 13:50:35 EDT 2007 -->
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 14:23:09 EDT 2007 -->
<TITLE>
Library.Handler (JNA API)
</TITLE>
+1 -1
Ver Arquivo
@@ -2,7 +2,7 @@
<!--NewPage-->
<HTML>
<HEAD>
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 13:50:35 EDT 2007 -->
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 14:23:08 EDT 2007 -->
<TITLE>
Library (JNA API)
</TITLE>
+1 -1
Ver Arquivo
@@ -2,7 +2,7 @@
<!--NewPage-->
<HTML>
<HEAD>
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 13:50:35 EDT 2007 -->
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 14:23:09 EDT 2007 -->
<TITLE>
Memory (JNA API)
</TITLE>
+1 -1
Ver Arquivo
@@ -2,7 +2,7 @@
<!--NewPage-->
<HTML>
<HEAD>
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 13:50:35 EDT 2007 -->
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 14:23:09 EDT 2007 -->
<TITLE>
Native (JNA API)
</TITLE>
+1 -1
Ver Arquivo
@@ -2,7 +2,7 @@
<!--NewPage-->
<HTML>
<HEAD>
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 13:50:35 EDT 2007 -->
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 14:23:09 EDT 2007 -->
<TITLE>
NativeLibrary (JNA API)
</TITLE>
+1 -1
Ver Arquivo
@@ -2,7 +2,7 @@
<!--NewPage-->
<HTML>
<HEAD>
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 13:50:35 EDT 2007 -->
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 14:23:09 EDT 2007 -->
<TITLE>
NativeLong (JNA API)
</TITLE>
+1 -1
Ver Arquivo
@@ -2,7 +2,7 @@
<!--NewPage-->
<HTML>
<HEAD>
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 13:50:35 EDT 2007 -->
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 14:23:09 EDT 2007 -->
<TITLE>
NativeString (JNA API)
</TITLE>
+1 -1
Ver Arquivo
@@ -2,7 +2,7 @@
<!--NewPage-->
<HTML>
<HEAD>
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 13:50:35 EDT 2007 -->
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 14:23:09 EDT 2007 -->
<TITLE>
Platform (JNA API)
</TITLE>
+1 -1
Ver Arquivo
@@ -2,7 +2,7 @@
<!--NewPage-->
<HTML>
<HEAD>
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 13:50:35 EDT 2007 -->
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 14:23:09 EDT 2007 -->
<TITLE>
Pointer (JNA API)
</TITLE>
+1 -1
Ver Arquivo
@@ -2,7 +2,7 @@
<!--NewPage-->
<HTML>
<HEAD>
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 13:50:35 EDT 2007 -->
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 14:23:09 EDT 2007 -->
<TITLE>
ResultContext (JNA API)
</TITLE>
+1 -1
Ver Arquivo
@@ -2,7 +2,7 @@
<!--NewPage-->
<HTML>
<HEAD>
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 13:50:35 EDT 2007 -->
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 14:23:08 EDT 2007 -->
<TITLE>
ResultConverter (JNA API)
</TITLE>
+1 -1
Ver Arquivo
@@ -2,7 +2,7 @@
<!--NewPage-->
<HTML>
<HEAD>
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 13:50:35 EDT 2007 -->
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 14:23:09 EDT 2007 -->
<TITLE>
Structure (JNA API)
</TITLE>
@@ -2,7 +2,7 @@
<!--NewPage-->
<HTML>
<HEAD>
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 13:50:35 EDT 2007 -->
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 14:23:09 EDT 2007 -->
<TITLE>
StructureReadContext (JNA API)
</TITLE>
+1 -1
Ver Arquivo
@@ -2,7 +2,7 @@
<!--NewPage-->
<HTML>
<HEAD>
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 13:50:35 EDT 2007 -->
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 14:23:09 EDT 2007 -->
<TITLE>
TypeConverter (JNA API)
</TITLE>
+1 -1
Ver Arquivo
@@ -2,7 +2,7 @@
<!--NewPage-->
<HTML>
<HEAD>
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 13:50:35 EDT 2007 -->
<!-- Generated by javadoc (build 1.4.2_12) on Mon Jun 11 14:23:09 EDT 2007 -->
<TITLE>
TypeMapper (JNA API)
</TITLE>

Alguns arquivos não foram exibidos porque demasiados arquivos foram alterados neste diff Mostrar Mais