Comparar commits
122 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 9b7ba38dc2 | |||
| 08157deece | |||
| c7e7e2bcdc | |||
| 01ab778621 | |||
| 312de23e5e | |||
| 792c5374d7 | |||
| 34dea52d6c | |||
| 6f3703d00b | |||
| cbd4b46f9f | |||
| ff1109389c | |||
| c31e9cdebf | |||
| 97449288eb | |||
| 9c2aebcf3c | |||
| 54c1851db5 | |||
| f1d0a9b688 | |||
| d62a8abb24 | |||
| 6f362b53c3 | |||
| 617420eaf9 | |||
| e0d2079802 | |||
| 897b318324 | |||
| 1737d6addb | |||
| 418a53806c | |||
| 79272c76a5 | |||
| d0936b0189 | |||
| 8db46b4c1a | |||
| c6a88f3b7f | |||
| 3ba1fd0975 | |||
| a3cdb5a90d | |||
| c6c99b8b98 | |||
| fffe7926da | |||
| 285e5305cb | |||
| b9fa73ce7a | |||
| d5669d2ae4 | |||
| 3db7fc10ec | |||
| 2fb4c9b683 | |||
| 766db7a318 | |||
| e8d4a3e6c0 | |||
| 9ac8de0f5d | |||
| fed3b9f432 | |||
| 3e55136c6a | |||
| 2d7971a429 | |||
| acf06d725f | |||
| e5dcc56056 | |||
| ce96234b72 | |||
| 3b8fe3b011 | |||
| 82561550e8 | |||
| 631920d41e | |||
| 6021064040 | |||
| 0547a9c3e2 | |||
| a1fe8ce22c | |||
| 5e56b8565a | |||
| 16d4db1790 | |||
| 32442cd2c4 | |||
| 2ac6c86266 | |||
| 5664101490 | |||
| d2dda4abb6 | |||
| 1f878f01f7 | |||
| bf28737ebd | |||
| 7fb2c1b041 | |||
| 4f3dcfdf4b | |||
| 13b2d7c0c1 | |||
| 2239bdfdfd | |||
| c6151c3775 | |||
| 0387196f85 | |||
| c7e7798979 | |||
| aa80c8d19f | |||
| 02d5f47380 | |||
| 75f3ed2d5a | |||
| 4e5afb4940 | |||
| 85793114d4 | |||
| 708e76473a | |||
| 2b8773a8f0 | |||
| 962ae7998e | |||
| 8f199788a5 | |||
| caaddd1179 | |||
| 3704b23a71 | |||
| c596f9f7d5 | |||
| f6208e71f4 | |||
| 85a3cda5c8 | |||
| 6c591c38d9 | |||
| 15aac21e2b | |||
| e0441a356d | |||
| f3da8161aa | |||
| 609e3e459b | |||
| 8638bb57f9 | |||
| d11084ce0d | |||
| 1ae335c7da | |||
| 99529821b4 | |||
| d551e656cb | |||
| ba49b166fb | |||
| a3e002c1db | |||
| 02601e4f7c | |||
| e2349e4bf6 | |||
| 87afaf44f7 | |||
| bb913b171d | |||
| 975063a28f | |||
| 8e44c82096 | |||
| 7a33f0b43e | |||
| cfdf20f4b7 | |||
| 13207caab6 | |||
| 980b86e2c5 | |||
| c6afe5f73d | |||
| 5c48942bda | |||
| 82c032329a | |||
| 2a2bdbe60c | |||
| 9414757638 | |||
| 253dc5abae | |||
| 296185c0ba | |||
| 70cff3e17a | |||
| 78969b8050 | |||
| d90f6e3346 | |||
| 8f99db35dd | |||
| b5759955d5 | |||
| adafa3b2c4 | |||
| 55778824f3 | |||
| d2159d70e3 | |||
| 6a06656c16 | |||
| 3fa90d76f5 | |||
| bfea982d45 | |||
| 78d70e760e | |||
| b7a299f42a | |||
| 136653a644 |
+1
-1
@@ -6,6 +6,6 @@
|
||||
<classpathentry kind="src" output="build.eclipse/test-classes" path="test"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3"/>
|
||||
<classpathentry kind="lib" path="C:/GitHub/jna-3.5.1.jar"/>
|
||||
<classpathentry kind="lib" path="lib/test/reflections-0.9.8.jar"/>
|
||||
<classpathentry kind="output" path="build.eclipse/classes"/>
|
||||
</classpath>
|
||||
|
||||
@@ -18,3 +18,4 @@ dist/src-mvn.zip
|
||||
dist/out-of-date.jar
|
||||
perf*.txt
|
||||
native/libffi/doc/libffi.info
|
||||
junit-*
|
||||
+678
-666
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+1
-1
@@ -1,6 +1,6 @@
|
||||
JNA is dual-licensed under 2 alternative Open Source/Free
|
||||
licenses: LGPL 2.1 and Apache License 2.0. (starting with
|
||||
JNA version 3.6.0).
|
||||
JNA version 4.0.0).
|
||||
|
||||
What this means is that one can choose either one of these
|
||||
licenses (for purposes of re-distributing JNA; usually by
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
This copy of JNA is licensed under the
|
||||
Apache (Software) License, version 2.0 ("the License").
|
||||
See the License for details about distribution rights, and the
|
||||
specific rights regarding derivate works.
|
||||
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
A copy is also included in the downloadable source code package
|
||||
containing JNA, in file "ASL2.0", under the same directory
|
||||
as this file.
|
||||
@@ -0,0 +1,13 @@
|
||||
This copy of JNA is licensed under the
|
||||
Lesser General Public License (LGPL), version 2.1 ("the License").
|
||||
See the License for details about distribution rights, and the
|
||||
specific rights regarding derivate works.
|
||||
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.gnu.org/licenses/licenses.html
|
||||
|
||||
A copy is also included in the downloadable source code package
|
||||
containing JNA, in file "LGPL2.1", under the same directory
|
||||
as this file.
|
||||
|
||||
+7
-7
@@ -3,7 +3,7 @@
|
||||
Java Native Access (JNA)
|
||||
========================
|
||||
|
||||
The definitive JNA reference (including an overview and usage details) is in the [JavaDoc](http://twall.github.com/jna/3.5.2/javadoc/). Please read the [overview](http://twall.github.com/jna/3.5.2/javadoc/overview-summary.html#overview_description). Questions, comments, or exploratory conversations should begin on the [mailing list](http://groups.google.com/group/jna-users), although you may find it easier to find answers to already-solved problems on [StackOverflow](http://stackoverflow.com/questions/tagged/jna).
|
||||
The definitive JNA reference (including an overview and usage details) is in the [JavaDoc](http://twall.github.com/jna/4.0/javadoc/). Please read the [overview](http://twall.github.com/jna/4.0/javadoc/overview-summary.html#overview_description). Questions, comments, or exploratory conversations should begin on the [mailing list](http://groups.google.com/group/jna-users), although you may find it easier to find answers to already-solved problems on [StackOverflow](http://stackoverflow.com/questions/tagged/jna).
|
||||
|
||||
JNA provides Java programs easy access to native shared libraries (DLLs on Windows) without writing anything but Java code - no JNI or native code is required. This functionality is comparable to Windows' Platform/Invoke and Python's ctypes. Access is dynamic at runtime without code generation.
|
||||
|
||||
@@ -18,10 +18,10 @@ JNA includes a platform library with many native functions already mapped as wel
|
||||
Download
|
||||
========
|
||||
|
||||
Version 3.5.2
|
||||
Version 4.0
|
||||
|
||||
* [jna.jar](https://maven.java.net/content/repositories/releases/net/java/dev/jna/jna/3.5.2/jna-3.5.2.jar)
|
||||
* [platform.jar](https://maven.java.net/content/repositories/releases/net/java/dev/jna/platform/3.5.2/platform-3.5.2.jar)
|
||||
* [jna.jar](https://maven.java.net/content/repositories/releases/net/java/dev/jna/jna/4.0.0/jna-4.0.0.jar)
|
||||
* [jna-platform.jar](https://maven.java.net/content/repositories/releases/net/java/dev/jna/platform/4.0.0/jna-platform-4.0.0.jar)
|
||||
|
||||
Features
|
||||
========
|
||||
@@ -79,12 +79,12 @@ Using the Library
|
||||
* [Platform Library](https://github.com/twall/jna/blob/master/www/PlatformLibrary.md)
|
||||
* [Direct Method Mapping](https://github.com/twall/jna/blob/master/www/DirectMapping.md) (Optimization)
|
||||
* [Frequently Asked Questions (FAQ)](https://github.com/twall/jna/blob/master/www/FrequentlyAskedQuestions.md)
|
||||
* [Avoiding Crashes](http://twall.github.com/jna/3.5.2/javadoc/overview-summary.html#crash-protection)
|
||||
* [Avoiding Crashes](http://twall.github.com/jna/4.0.0/javadoc/overview-summary.html#crash-protection)
|
||||
|
||||
Primary Documentation (JavaDoc)
|
||||
===============================
|
||||
|
||||
The definitive JNA reference is in the [JavaDoc](http://twall.github.com/jna/3.5.2/javadoc/).
|
||||
The definitive JNA reference is in the [JavaDoc](http://twall.github.com/jna/4.0.0/javadoc/).
|
||||
|
||||
Developers
|
||||
==========
|
||||
@@ -108,7 +108,7 @@ License
|
||||
=======
|
||||
|
||||
This library is licensed under the LGPL, version 2.1 or later, and (from
|
||||
version 3.6 onward) the Apache Software License, version 2.0. Commercial
|
||||
version 4.0 onward) the Apache Software License, version 2.0. Commercial
|
||||
license arrangements are negotiable.
|
||||
|
||||
*NOTE: Oracle is not sponsoring this project, even though the package name (com.sun.jna) might imply otherwise.*
|
||||
|
||||
+3
-2
@@ -51,6 +51,9 @@
|
||||
referenced. (not really common)
|
||||
|
||||
|
||||
* eliminate type conversion contexts; these are almost entirely unused and
|
||||
more complicated than just wrapping a native mapping in a utility function
|
||||
* direct non-primitive array arguments (String[], Pointer[], NativeMapped[])
|
||||
|
||||
* auto-generate direct mappings/bindings on a per-method basis (perform a
|
||||
method register on first call to an interface-mapped function) with
|
||||
@@ -64,12 +67,10 @@
|
||||
and forth multiple times). This also makes it easer to perform conversions
|
||||
(no native changes required).
|
||||
|
||||
* direct/raw non-primitive array arguments (String[], Pointer[], NativeMapped[])
|
||||
* ppc64 direct/raw failures (multiple)
|
||||
* direct calls on ppc to varargs (callbacks) with FP args fail; avoid them for
|
||||
now
|
||||
* Callback.PostCallWrite.write() cf PostCallRead
|
||||
* eliminate type conversion contexts; these are almost entirely unused
|
||||
|
||||
* universal GCC build w/cross-compile (needs cross compilers...)
|
||||
* return Pointer.SIZE/LONG_SIZE/WCHAR_SIZE in bits (for consistency with 1.5)
|
||||
|
||||
+60
-27
@@ -12,7 +12,8 @@
|
||||
(cross-compile currently only configured/tested on w32ce-arm and
|
||||
android-arm/-x86)
|
||||
|
||||
Use ANT_OPTS=-Dskip-native to skip building native parts.
|
||||
Use ANT_OPTS=-Dskip-native=false to build native parts, or directly
|
||||
invoke the native or test targets
|
||||
Use ANT_OPTS=-Dheadless to run tests headless
|
||||
Use ANT_OPTS=-Drelease to stage a final, non-snapshot version
|
||||
-->
|
||||
@@ -71,16 +72,13 @@
|
||||
<property name="jni.revision" value="0"/>
|
||||
<property name="jni.build" value="${build.number}"/>
|
||||
<property name="jni.version" value="${jni.major}.${jni.minor}.${jni.revision}"/>
|
||||
<property name="jni.md5" value="059b6e5f0534df9b7f28dd7a87485721"/>
|
||||
<property name="jni.md5" value="1a6047467b59e8748f975e03016ce3d9"/>
|
||||
<property name="spec.title" value="Java Native Access (JNA)"/>
|
||||
<property name="spec.vendor" value="${vendor}"/>
|
||||
<property name="spec.version" value="${jna.major}"/>
|
||||
<property name="impl.title" value="com.sun.jna"/>
|
||||
<property name="impl.vendor" value="${spec.vendor}"/>
|
||||
<property name="impl.version" value="${jna.version} (b${jna.build})"/>
|
||||
<condition property="jni.valid" value="true">
|
||||
<isset property="skip-native"/>
|
||||
</condition>
|
||||
|
||||
<!-- Set up restrictions for w32ce, based on JavaME/CDC -->
|
||||
<condition property="compatibility" value="1.4">
|
||||
@@ -114,12 +112,12 @@
|
||||
<property name="maven-javadoc-jar" value="${dist}/${artifactId}-${jna.version}-javadoc.jar" />
|
||||
<property name="maven-sources-jar" value="${dist}/${artifactId}-${jna.version}-sources.jar" />
|
||||
|
||||
<property name="platform-jar" value="${dist}/platform.jar"/>
|
||||
<property name="platform-jar" value="${dist}/jna-platform.jar"/>
|
||||
<property name="platform-javadoc-jar" value="${dist}/platform-${jna.version}-javadoc.jar" />
|
||||
<property name="platform-sources-jar" value="${dist}/platform-${jna.version}-sources.jar" />
|
||||
|
||||
<property name="pom" value="pom-jna.xml" />
|
||||
<property name="pom-platform" value="pom-platform.xml" />
|
||||
<property name="pom-platform" value="pom-jna-platform.xml" />
|
||||
|
||||
<!-- defined maven snapshots and staging repository id and url -->
|
||||
<property name="maven-snapshots-repository-id" value="snapshots.java.net" />
|
||||
@@ -138,6 +136,13 @@
|
||||
|
||||
<target name="-dynamic-properties">
|
||||
|
||||
<condition property="-native" value="true">
|
||||
<not><isset property="build-native"/></not>
|
||||
</condition>
|
||||
<condition property="jni.valid" value="true">
|
||||
<isset property="-native"/>
|
||||
</condition>
|
||||
|
||||
<replaceregexp match="(<version>).*(</version>)"
|
||||
replace="\1${jna.version}\2"
|
||||
file="${pom}"/>
|
||||
@@ -225,12 +230,17 @@
|
||||
<condition property="os.prefix" value="sunos-${jre.arch}">
|
||||
<os name="SunOS"/>
|
||||
</condition>
|
||||
<condition property="os.prefix" value="bsd-${jre.arch}">
|
||||
<or>
|
||||
<os name="FreeBSD"/>
|
||||
<condition property="os.prefix" value="freebsd-${jre.arch}">
|
||||
<os name="FreeBSD"/>
|
||||
</condition>
|
||||
<condition property="os.prefix" value="openbsd-${jre.arch}">
|
||||
<os name="OpenBSD"/>
|
||||
<os name="NetBSD"/>
|
||||
</or>
|
||||
</condition>
|
||||
<condition property="os.prefix" value="netbsd-${jre.arch}">
|
||||
<os name="NetBSD"/>
|
||||
</condition>
|
||||
<condition property="os.prefix" value="kfreebsd-${jre.arch}">
|
||||
<os name="GNU/kFreeBSD"/>
|
||||
</condition>
|
||||
<fail unless="os.prefix" message="OS/arch not supported (${os.name}/${jre.arch}), edit build.xml and native/Makefile to add it."/>
|
||||
<!-- Keep all natives separate -->
|
||||
@@ -390,10 +400,14 @@ processor=arm;osname=linux,
|
||||
com/sun/jna/linux-ia64/libjnidispatch.so;
|
||||
processor=ia64;osname=linux,
|
||||
|
||||
com/sun/jna/bsd-x86/libjnidispatch.so;
|
||||
processor=x86;osname=openbsd;osname=freebsd;osname=netbsd,
|
||||
com/sun/jna/bsd-x86-64/libjnidispatch.so;
|
||||
processor=x86-64;osname=openbsd;osname=freebsd;osname=netbsd,
|
||||
com/sun/jna/freebsd-x86/libjnidispatch.so;
|
||||
processor=x86;osname=freebsd,
|
||||
com/sun/jna/freebsd-x86-64/libjnidispatch.so;
|
||||
processor=x86-64;osname=freebsd,
|
||||
com/sun/jna/openbsd-x86/libjnidispatch.so;
|
||||
processor=x86;osname=openbsd,
|
||||
com/sun/jna/openbsd-x86-64/libjnidispatch.so;
|
||||
processor=x86-64;osname=openbsd,
|
||||
|
||||
com/sun/jna/darwin/libjnidispatch.jnilib;
|
||||
osname=macosx;processor=x86;processor=x86-64;processor=ppc
|
||||
@@ -444,12 +458,18 @@ osname=macosx;processor=x86;processor=x86-64;processor=ppc
|
||||
<zipfileset src="${lib.native}/sunos-sparcv9.jar"
|
||||
includes="*jnidispatch*"
|
||||
prefix="com/sun/jna/sunos-sparcv9"/>
|
||||
<zipfileset src="${lib.native}/bsd-x86.jar"
|
||||
<zipfileset src="${lib.native}/freebsd-x86.jar"
|
||||
includes="*jnidispatch*"
|
||||
prefix="com/sun/jna/bsd-x86"/>
|
||||
<zipfileset src="${lib.native}/bsd-x86-64.jar"
|
||||
prefix="com/sun/jna/freebsd-x86"/>
|
||||
<zipfileset src="${lib.native}/freebsd-x86-64.jar"
|
||||
includes="*jnidispatch*"
|
||||
prefix="com/sun/jna/bsd-x86-64"/>
|
||||
prefix="com/sun/jna/freebsd-x86-64"/>
|
||||
<zipfileset src="${lib.native}/openbsd-x86.jar"
|
||||
includes="*jnidispatch*"
|
||||
prefix="com/sun/jna/openbsd-x86"/>
|
||||
<zipfileset src="${lib.native}/openbsd-x86-64.jar"
|
||||
includes="*jnidispatch*"
|
||||
prefix="com/sun/jna/openbsd-x86-64"/>
|
||||
<zipfileset src="${lib.native}/win32-x86-64.jar"
|
||||
includes="*jnidispatch*"
|
||||
prefix="com/sun/jna/win32-x86-64"/>
|
||||
@@ -486,7 +506,7 @@ osname=macosx;processor=x86;processor=x86-64;processor=ppc
|
||||
</subant>
|
||||
</target>
|
||||
|
||||
<target name="javah" depends="compile" unless="skip-native">
|
||||
<target name="javah" depends="compile" unless="-native">
|
||||
<javah classpath="${classes}" destdir="${build.native}" force="yes">
|
||||
<class name="com.sun.jna.Function"/>
|
||||
<class name="com.sun.jna.Native"/>
|
||||
@@ -543,8 +563,10 @@ osname=macosx;processor=x86;processor=x86-64;processor=ppc
|
||||
<copy file="${lib.native}/out-of-date.jar" tofile="${lib.native}/linux-ia64.jar" overwrite="true"/>
|
||||
<copy file="${lib.native}/out-of-date.jar" tofile="${lib.native}/linux-ppc.jar" overwrite="true"/>
|
||||
<copy file="${lib.native}/out-of-date.jar" tofile="${lib.native}/linux-ppc64.jar" overwrite="true"/>
|
||||
<copy file="${lib.native}/out-of-date.jar" tofile="${lib.native}/bsd-x86.jar" overwrite="true"/>
|
||||
<copy file="${lib.native}/out-of-date.jar" tofile="${lib.native}/bsd-x86-64.jar" overwrite="true"/>
|
||||
<copy file="${lib.native}/out-of-date.jar" tofile="${lib.native}/freebsd-x86.jar" overwrite="true"/>
|
||||
<copy file="${lib.native}/out-of-date.jar" tofile="${lib.native}/freebsd-x86-64.jar" overwrite="true"/>
|
||||
<copy file="${lib.native}/out-of-date.jar" tofile="${lib.native}/openbsd-x86.jar" overwrite="true"/>
|
||||
<copy file="${lib.native}/out-of-date.jar" tofile="${lib.native}/openbsd-x86-64.jar" overwrite="true"/>
|
||||
<copy file="${lib.native}/out-of-date.jar" tofile="${lib.native}/sunos-x86.jar" overwrite="true"/>
|
||||
<copy file="${lib.native}/out-of-date.jar" tofile="${lib.native}/sunos-x86-64.jar" overwrite="true"/>
|
||||
<copy file="${lib.native}/out-of-date.jar" tofile="${lib.native}/sunos-sparc.jar" overwrite="true"/>
|
||||
@@ -595,7 +617,7 @@ osname=macosx;processor=x86;processor=x86-64;processor=ppc
|
||||
file="${rsrc}" byline="true"/>
|
||||
</target>
|
||||
|
||||
<target name="native" depends="-setup,javah,-native-api-check,rsrc" unless="skip-native"
|
||||
<target name="native" depends="-enable-native,-setup,javah,-native-api-check,rsrc" unless="-native"
|
||||
description="Build native libraries. Use 'ant -DCC=xxx' to build using a compiler other than gcc">
|
||||
<property name="comment" value="# auto-generated by ant"/>
|
||||
<replaceregexp match="^JNA_JNI_VERSION=.*"
|
||||
@@ -750,11 +772,18 @@ osname=macosx;processor=x86;processor=x86-64;processor=ppc
|
||||
<src path="${test.src}"/>
|
||||
<exclude name="${tests.exclude}"/>
|
||||
</javac>
|
||||
<!-- Embed testlib-jar at root and at default resource path -->
|
||||
<mkdir dir="${test.classes}/${os.prefix}"/>
|
||||
<copy todir="${test.classes}">
|
||||
<fileset dir="${build.native}">
|
||||
<include name="*testlib-jar*"/>
|
||||
</fileset>
|
||||
</copy>
|
||||
<copy todir="${test.classes}/${os.prefix}">
|
||||
<fileset dir="${build.native}">
|
||||
<include name="*testlib-jar*"/>
|
||||
</fileset>
|
||||
</copy>
|
||||
<!-- Create a jar for easy movement of tests, and jar load test -->
|
||||
<jar jarfile="${build}/${testjar}">
|
||||
<fileset dir="${test.classes}">
|
||||
@@ -764,7 +793,7 @@ osname=macosx;processor=x86;processor=x86-64;processor=ppc
|
||||
</jar>
|
||||
<!-- Ensure jar-based library is unavailable on FS-based class path -->
|
||||
<delete>
|
||||
<fileset dir="${test.classes}">
|
||||
<fileset dir="${build}">
|
||||
<include name="**/*testlib-jar*"/>
|
||||
</fileset>
|
||||
</delete>
|
||||
@@ -808,9 +837,13 @@ osname=macosx;processor=x86;processor=x86-64;processor=ppc
|
||||
<chmod file="${shared}/*.dll" perm="+x"/>
|
||||
</target>
|
||||
|
||||
<target name="-enable-native" unless="-native">
|
||||
<property name="build-native" value="true"/>
|
||||
</target>
|
||||
|
||||
<!-- When running tests from an IDE, be sure to set jna.library.path -->
|
||||
<!-- to where the test library (testlib) is found. -->
|
||||
<target name="test" depends="jar,compile-tests" unless="cross-compile"
|
||||
<target name="test" depends="-enable-native,jar,compile-tests" unless="cross-compile"
|
||||
description="Run all unit tests">
|
||||
<property name="test.fork" value="yes"/>
|
||||
<property name="reports.junit" location="${reports}/junit"/>
|
||||
@@ -960,7 +993,7 @@ osname=macosx;processor=x86;processor=x86-64;processor=ppc
|
||||
description="Build distribution files">
|
||||
<copy todir="${dist}">
|
||||
<fileset dir="${build}" includes="${jar},${minjar}"/>
|
||||
<fileset dir="${contrib}/platform/dist" includes="platform.jar"/>
|
||||
<fileset dir="${contrib}/platform/dist" includes="jna-platform.jar"/>
|
||||
<fileset dir="${lib.native}">
|
||||
<include name="*.jar"/>
|
||||
<exclude name="out-of-date.jar"/>
|
||||
|
||||
@@ -1,66 +1,66 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="jnacontrib.alphamaskdemo" default="jar" basedir=".">
|
||||
<description>Builds, tests, and runs the project jnacontrib.alphamaskdemo.</description>
|
||||
<!-- Locations -->
|
||||
<property name="src" location="."/>
|
||||
<property name="build" location="build"/>
|
||||
<property name="jna-dist" location="../../dist"/>
|
||||
|
||||
<property name="classes" location="${build}/classes"/>
|
||||
<property name="jar" location="${build}/demo-alphamask.jar"/>
|
||||
<property name="file.reference.jna.jar" location="../../build/jna.jar"/>
|
||||
<property name="main-class" value="com.sun.jna.contrib.demo.AlphaMaskDemo" />
|
||||
|
||||
<path id="classpath">
|
||||
<fileset file="${file.reference.jna.jar}"/>
|
||||
<fileset dir="../platform/dist" includes="platform.jar"/>
|
||||
</path>
|
||||
|
||||
<!-- Run Demo. -->
|
||||
<target name="run" depends="compile">
|
||||
<java classname="${main-class}" fork="true">
|
||||
<classpath>
|
||||
<pathelement location="${classes}" />
|
||||
<path refid="classpath"/>
|
||||
</classpath>
|
||||
</java>
|
||||
</target>
|
||||
|
||||
<!-- Delete class and jar files. -->
|
||||
<target name="clean">
|
||||
<delete dir="${classes}"/>
|
||||
<delete file="${jar}"/>
|
||||
<delete dir="${build}"/>
|
||||
</target>
|
||||
|
||||
<!-- Compile all classes. -->
|
||||
<target name="compile">
|
||||
<mkdir dir="${classes}"/>
|
||||
<!-- Compile the project. -->
|
||||
<javac srcdir="${src}" destdir="${classes}" target="1.5" source="1.5"
|
||||
encoding="UTF-8" debug="on" includeantruntime="false">
|
||||
<classpath>
|
||||
<path refid="classpath"/>
|
||||
</classpath>
|
||||
</javac>
|
||||
</target>
|
||||
|
||||
<!-- Create jar-file. -->
|
||||
<target name="jar" depends="compile">
|
||||
<!-- Copy all non-java files to classes. -->
|
||||
<copy todir="${classes}/com">
|
||||
<fileset dir="${src}/com">
|
||||
<exclude name="**/*.java"/>
|
||||
</fileset>
|
||||
</copy>
|
||||
<jar jarfile="${jar}" basedir="${classes}">
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="${main-class}"/>
|
||||
</manifest>
|
||||
<!-- platform -->
|
||||
<fileset dir="../platform/build/classes/com"/>
|
||||
<!-- jna -->
|
||||
<zipfileset src="${file.reference.jna.jar}"/>
|
||||
</jar>
|
||||
</target>
|
||||
</project>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="jnacontrib.alphamaskdemo" default="jar" basedir=".">
|
||||
<description>Builds, tests, and runs the project jnacontrib.alphamaskdemo.</description>
|
||||
<!-- Locations -->
|
||||
<property name="src" location="."/>
|
||||
<property name="build" location="build"/>
|
||||
<property name="jna-dist" location="../../dist"/>
|
||||
|
||||
<property name="classes" location="${build}/classes"/>
|
||||
<property name="jar" location="${build}/demo-alphamask.jar"/>
|
||||
<property name="file.reference.jna.jar" location="../../build/jna.jar"/>
|
||||
<property name="main-class" value="com.sun.jna.contrib.demo.AlphaMaskDemo" />
|
||||
|
||||
<path id="classpath">
|
||||
<fileset file="${file.reference.jna.jar}"/>
|
||||
<fileset dir="../platform/dist" includes="jna-platform.jar"/>
|
||||
</path>
|
||||
|
||||
<!-- Run Demo. -->
|
||||
<target name="run" depends="compile">
|
||||
<java classname="${main-class}" fork="true">
|
||||
<classpath>
|
||||
<pathelement location="${classes}" />
|
||||
<path refid="classpath"/>
|
||||
</classpath>
|
||||
</java>
|
||||
</target>
|
||||
|
||||
<!-- Delete class and jar files. -->
|
||||
<target name="clean">
|
||||
<delete dir="${classes}"/>
|
||||
<delete file="${jar}"/>
|
||||
<delete dir="${build}"/>
|
||||
</target>
|
||||
|
||||
<!-- Compile all classes. -->
|
||||
<target name="compile">
|
||||
<mkdir dir="${classes}"/>
|
||||
<!-- Compile the project. -->
|
||||
<javac srcdir="${src}" destdir="${classes}" target="1.5" source="1.5"
|
||||
encoding="UTF-8" debug="on" includeantruntime="false">
|
||||
<classpath>
|
||||
<path refid="classpath"/>
|
||||
</classpath>
|
||||
</javac>
|
||||
</target>
|
||||
|
||||
<!-- Create jar-file. -->
|
||||
<target name="jar" depends="compile">
|
||||
<!-- Copy all non-java files to classes. -->
|
||||
<copy todir="${classes}/com">
|
||||
<fileset dir="${src}/com">
|
||||
<exclude name="**/*.java"/>
|
||||
</fileset>
|
||||
</copy>
|
||||
<jar jarfile="${jar}" basedir="${classes}">
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="${main-class}"/>
|
||||
</manifest>
|
||||
<!-- platform -->
|
||||
<fileset dir="../platform/build/classes/com"/>
|
||||
<!-- jna -->
|
||||
<zipfileset src="${file.reference.jna.jar}"/>
|
||||
</jar>
|
||||
</target>
|
||||
</project>
|
||||
|
||||
@@ -1,68 +1,68 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="jnacontrib.balloonmanagerdemo" default="jar" basedir=".">
|
||||
<description>Builds, tests, and runs the project jnacontrib.balloonmanagerdemo.</description>
|
||||
<!-- Locations -->
|
||||
<property name="src" location="."/>
|
||||
<property name="build" location="build"/>
|
||||
<property name="jna-dist" location="../../dist"/>
|
||||
|
||||
<property name="classes" location="${build}/classes"/>
|
||||
<property name="jar" location="${build}/demo-balloonmanager.jar"/>
|
||||
<property name="file.reference.jna.jar" location="../../build/jna.jar"/>
|
||||
<property name="main-class" value="com.sun.jna.contrib.demo.BalloonManagerDemo" />
|
||||
|
||||
<path id="classpath">
|
||||
<fileset file="${file.reference.jna.jar}"/>
|
||||
<fileset dir="../platform/dist" includes="platform.jar"/>
|
||||
</path>
|
||||
|
||||
<!-- Run Demo. -->
|
||||
<target name="run" depends="compile">
|
||||
<java classname="${main-class}" fork="true">
|
||||
<classpath>
|
||||
<pathelement location="${classes}" />
|
||||
<path refid="classpath"/>
|
||||
</classpath>
|
||||
</java>
|
||||
</target>
|
||||
|
||||
<!-- Delete class and jar files. -->
|
||||
<target name="clean">
|
||||
<delete dir="${classes}"/>
|
||||
<delete file="${jar}"/>
|
||||
<delete dir="${build}"/>
|
||||
</target>
|
||||
|
||||
<!-- Compile all classes. -->
|
||||
<target name="compile">
|
||||
<mkdir dir="${classes}"/>
|
||||
<!-- Compile the project. -->
|
||||
<javac srcdir="${src}" destdir="${classes}" target="1.5" source="1.5"
|
||||
encoding="UTF-8" debug="on" includeantruntime="false">
|
||||
<classpath>
|
||||
<path refid="classpath"/>
|
||||
</classpath>
|
||||
</javac>
|
||||
</target>
|
||||
|
||||
<!-- Create jar-file. -->
|
||||
<target name="jar" depends="compile">
|
||||
|
||||
<!-- Copy all non-java files to classes. -->
|
||||
<copy todir="${classes}/com">
|
||||
<fileset dir="${src}/com">
|
||||
<exclude name="**/*.java"/>
|
||||
</fileset>
|
||||
</copy>
|
||||
|
||||
<jar jarfile="${jar}" basedir="${classes}">
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="${main-class}"/>
|
||||
</manifest>
|
||||
<!-- platform -->
|
||||
<fileset dir="../platform/build/classes/com"/>
|
||||
<!-- jna -->
|
||||
<zipfileset src="${file.reference.jna.jar}"/>
|
||||
</jar>
|
||||
</target>
|
||||
</project>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="jnacontrib.balloonmanagerdemo" default="jar" basedir=".">
|
||||
<description>Builds, tests, and runs the project jnacontrib.balloonmanagerdemo.</description>
|
||||
<!-- Locations -->
|
||||
<property name="src" location="."/>
|
||||
<property name="build" location="build"/>
|
||||
<property name="jna-dist" location="../../dist"/>
|
||||
|
||||
<property name="classes" location="${build}/classes"/>
|
||||
<property name="jar" location="${build}/demo-balloonmanager.jar"/>
|
||||
<property name="file.reference.jna.jar" location="../../build/jna.jar"/>
|
||||
<property name="main-class" value="com.sun.jna.contrib.demo.BalloonManagerDemo" />
|
||||
|
||||
<path id="classpath">
|
||||
<fileset file="${file.reference.jna.jar}"/>
|
||||
<fileset dir="../platform/dist" includes="jna-platform.jar"/>
|
||||
</path>
|
||||
|
||||
<!-- Run Demo. -->
|
||||
<target name="run" depends="compile">
|
||||
<java classname="${main-class}" fork="true">
|
||||
<classpath>
|
||||
<pathelement location="${classes}" />
|
||||
<path refid="classpath"/>
|
||||
</classpath>
|
||||
</java>
|
||||
</target>
|
||||
|
||||
<!-- Delete class and jar files. -->
|
||||
<target name="clean">
|
||||
<delete dir="${classes}"/>
|
||||
<delete file="${jar}"/>
|
||||
<delete dir="${build}"/>
|
||||
</target>
|
||||
|
||||
<!-- Compile all classes. -->
|
||||
<target name="compile">
|
||||
<mkdir dir="${classes}"/>
|
||||
<!-- Compile the project. -->
|
||||
<javac srcdir="${src}" destdir="${classes}" target="1.5" source="1.5"
|
||||
encoding="UTF-8" debug="on" includeantruntime="false">
|
||||
<classpath>
|
||||
<path refid="classpath"/>
|
||||
</classpath>
|
||||
</javac>
|
||||
</target>
|
||||
|
||||
<!-- Create jar-file. -->
|
||||
<target name="jar" depends="compile">
|
||||
|
||||
<!-- Copy all non-java files to classes. -->
|
||||
<copy todir="${classes}/com">
|
||||
<fileset dir="${src}/com">
|
||||
<exclude name="**/*.java"/>
|
||||
</fileset>
|
||||
</copy>
|
||||
|
||||
<jar jarfile="${jar}" basedir="${classes}">
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="${main-class}"/>
|
||||
</manifest>
|
||||
<!-- platform -->
|
||||
<fileset dir="../platform/build/classes/com"/>
|
||||
<!-- jna -->
|
||||
<zipfileset src="${file.reference.jna.jar}"/>
|
||||
</jar>
|
||||
</target>
|
||||
</project>
|
||||
|
||||
@@ -1,68 +1,68 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="jnacontrib.balloontipsdemo" default="jar" basedir=".">
|
||||
<description>Builds, tests, and runs the project jnacontrib.balloontipsdemo.</description>
|
||||
<!-- Locations -->
|
||||
<property name="src" location="."/>
|
||||
<property name="build" location="build"/>
|
||||
<property name="jna-dist" location="../../dist"/>
|
||||
|
||||
<property name="classes" location="${build}/classes"/>
|
||||
<property name="jar" location="${build}/demo-balloontips.jar"/>
|
||||
<property name="file.reference.jna.jar" location="../../build/jna.jar"/>
|
||||
<property name="main-class" value="com.sun.jna.contrib.demo.FilteredTextField" />
|
||||
|
||||
<path id="classpath">
|
||||
<fileset file="${file.reference.jna.jar}"/>
|
||||
<fileset dir="../platform/dist" includes="platform.jar"/>
|
||||
</path>
|
||||
|
||||
<!-- Run Demo. -->
|
||||
<target name="run" depends="compile">
|
||||
<java classname="${main-class}" fork="true">
|
||||
<classpath>
|
||||
<pathelement location="${classes}" />
|
||||
<path refid="classpath"/>
|
||||
</classpath>
|
||||
</java>
|
||||
</target>
|
||||
|
||||
<!-- Delete class and jar files. -->
|
||||
<target name="clean">
|
||||
<delete dir="${classes}"/>
|
||||
<delete file="${jar}"/>
|
||||
<delete dir="${build}"/>
|
||||
</target>
|
||||
|
||||
<!-- Compile all classes. -->
|
||||
<target name="compile">
|
||||
<mkdir dir="${classes}"/>
|
||||
<!-- Compile the project. -->
|
||||
<javac srcdir="${src}" destdir="${classes}" target="1.5" source="1.5"
|
||||
encoding="UTF-8" debug="on" includeantruntime="false">
|
||||
<classpath>
|
||||
<path refid="classpath"/>
|
||||
</classpath>
|
||||
</javac>
|
||||
</target>
|
||||
|
||||
<!-- Create jar-file. -->
|
||||
<target name="jar" depends="compile">
|
||||
|
||||
<!-- Copy all non-java files to classes. -->
|
||||
<copy todir="${classes}/com">
|
||||
<fileset dir="${src}/com">
|
||||
<exclude name="**/*.java"/>
|
||||
</fileset>
|
||||
</copy>
|
||||
|
||||
<jar jarfile="${jar}" basedir="${classes}">
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="${main-class}"/>
|
||||
</manifest>
|
||||
<!-- platform -->
|
||||
<fileset dir="../platform/build/classes/com"/>
|
||||
<!-- jna -->
|
||||
<zipfileset src="${file.reference.jna.jar}"/>
|
||||
</jar>
|
||||
</target>
|
||||
</project>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="jnacontrib.balloontipsdemo" default="jar" basedir=".">
|
||||
<description>Builds, tests, and runs the project jnacontrib.balloontipsdemo.</description>
|
||||
<!-- Locations -->
|
||||
<property name="src" location="."/>
|
||||
<property name="build" location="build"/>
|
||||
<property name="jna-dist" location="../../dist"/>
|
||||
|
||||
<property name="classes" location="${build}/classes"/>
|
||||
<property name="jar" location="${build}/demo-balloontips.jar"/>
|
||||
<property name="file.reference.jna.jar" location="../../build/jna.jar"/>
|
||||
<property name="main-class" value="com.sun.jna.contrib.demo.FilteredTextField" />
|
||||
|
||||
<path id="classpath">
|
||||
<fileset file="${file.reference.jna.jar}"/>
|
||||
<fileset dir="../platform/dist" includes="jna-platform.jar"/>
|
||||
</path>
|
||||
|
||||
<!-- Run Demo. -->
|
||||
<target name="run" depends="compile">
|
||||
<java classname="${main-class}" fork="true">
|
||||
<classpath>
|
||||
<pathelement location="${classes}" />
|
||||
<path refid="classpath"/>
|
||||
</classpath>
|
||||
</java>
|
||||
</target>
|
||||
|
||||
<!-- Delete class and jar files. -->
|
||||
<target name="clean">
|
||||
<delete dir="${classes}"/>
|
||||
<delete file="${jar}"/>
|
||||
<delete dir="${build}"/>
|
||||
</target>
|
||||
|
||||
<!-- Compile all classes. -->
|
||||
<target name="compile">
|
||||
<mkdir dir="${classes}"/>
|
||||
<!-- Compile the project. -->
|
||||
<javac srcdir="${src}" destdir="${classes}" target="1.5" source="1.5"
|
||||
encoding="UTF-8" debug="on" includeantruntime="false">
|
||||
<classpath>
|
||||
<path refid="classpath"/>
|
||||
</classpath>
|
||||
</javac>
|
||||
</target>
|
||||
|
||||
<!-- Create jar-file. -->
|
||||
<target name="jar" depends="compile">
|
||||
|
||||
<!-- Copy all non-java files to classes. -->
|
||||
<copy todir="${classes}/com">
|
||||
<fileset dir="${src}/com">
|
||||
<exclude name="**/*.java"/>
|
||||
</fileset>
|
||||
</copy>
|
||||
|
||||
<jar jarfile="${jar}" basedir="${classes}">
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="${main-class}"/>
|
||||
</manifest>
|
||||
<!-- platform -->
|
||||
<fileset dir="../platform/build/classes/com"/>
|
||||
<!-- jna -->
|
||||
<zipfileset src="${file.reference.jna.jar}"/>
|
||||
</jar>
|
||||
</target>
|
||||
</project>
|
||||
|
||||
+68
-68
@@ -1,68 +1,68 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="jnacontrib.dnddemo" default="jar" basedir=".">
|
||||
<description>Builds, tests, and runs the project jnacontrib.dnddemo.</description>
|
||||
<!-- Locations -->
|
||||
<property name="src" location="."/>
|
||||
<property name="build" location="build"/>
|
||||
<property name="jna-dist" location="../../dist"/>
|
||||
|
||||
<property name="classes" location="${build}/classes"/>
|
||||
<property name="jar" location="${build}/demo-dnd.jar"/>
|
||||
<property name="file.reference.jna.jar" location="../../build/jna.jar"/>
|
||||
<property name="main-class" value="com.sun.jna.contrib.demo.GhostedDragImageDemo" />
|
||||
|
||||
<path id="classpath">
|
||||
<fileset file="${file.reference.jna.jar}"/>
|
||||
<fileset dir="../platform/dist" includes="platform.jar"/>
|
||||
</path>
|
||||
|
||||
<!-- Run Demo. -->
|
||||
<target name="run" depends="compile">
|
||||
<java classname="${main-class}" fork="true">
|
||||
<classpath>
|
||||
<pathelement location="${classes}" />
|
||||
<path refid="classpath"/>
|
||||
</classpath>
|
||||
</java>
|
||||
</target>
|
||||
|
||||
<!-- Delete class and jar files. -->
|
||||
<target name="clean">
|
||||
<delete dir="${classes}"/>
|
||||
<delete file="${jar}"/>
|
||||
<delete dir="${build}"/>
|
||||
</target>
|
||||
|
||||
<!-- Compile all classes. -->
|
||||
<target name="compile">
|
||||
<mkdir dir="${classes}"/>
|
||||
<!-- Compile the project. -->
|
||||
<javac srcdir="${src}" destdir="${classes}" target="1.5" source="1.5"
|
||||
encoding="UTF-8" debug="on" includeantruntime="false">
|
||||
<classpath>
|
||||
<path refid="classpath"/>
|
||||
</classpath>
|
||||
</javac>
|
||||
</target>
|
||||
|
||||
<!-- Create jar-file. -->
|
||||
<target name="jar" depends="compile">
|
||||
|
||||
<!-- Copy all non-java files to classes. -->
|
||||
<copy todir="${classes}/com">
|
||||
<fileset dir="${src}/com">
|
||||
<exclude name="**/*.java"/>
|
||||
</fileset>
|
||||
</copy>
|
||||
|
||||
<jar jarfile="${jar}" basedir="${classes}">
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="${main-class}"/>
|
||||
</manifest>
|
||||
<!-- platform -->
|
||||
<fileset dir="../platform/build/classes/com"/>
|
||||
<!-- jna -->
|
||||
<zipfileset src="${file.reference.jna.jar}"/>
|
||||
</jar>
|
||||
</target>
|
||||
</project>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="jnacontrib.dnddemo" default="jar" basedir=".">
|
||||
<description>Builds, tests, and runs the project jnacontrib.dnddemo.</description>
|
||||
<!-- Locations -->
|
||||
<property name="src" location="."/>
|
||||
<property name="build" location="build"/>
|
||||
<property name="jna-dist" location="../../dist"/>
|
||||
|
||||
<property name="classes" location="${build}/classes"/>
|
||||
<property name="jar" location="${build}/demo-dnd.jar"/>
|
||||
<property name="file.reference.jna.jar" location="../../build/jna.jar"/>
|
||||
<property name="main-class" value="com.sun.jna.contrib.demo.GhostedDragImageDemo" />
|
||||
|
||||
<path id="classpath">
|
||||
<fileset file="${file.reference.jna.jar}"/>
|
||||
<fileset dir="../platform/dist" includes="jna-platform.jar"/>
|
||||
</path>
|
||||
|
||||
<!-- Run Demo. -->
|
||||
<target name="run" depends="compile">
|
||||
<java classname="${main-class}" fork="true">
|
||||
<classpath>
|
||||
<pathelement location="${classes}" />
|
||||
<path refid="classpath"/>
|
||||
</classpath>
|
||||
</java>
|
||||
</target>
|
||||
|
||||
<!-- Delete class and jar files. -->
|
||||
<target name="clean">
|
||||
<delete dir="${classes}"/>
|
||||
<delete file="${jar}"/>
|
||||
<delete dir="${build}"/>
|
||||
</target>
|
||||
|
||||
<!-- Compile all classes. -->
|
||||
<target name="compile">
|
||||
<mkdir dir="${classes}"/>
|
||||
<!-- Compile the project. -->
|
||||
<javac srcdir="${src}" destdir="${classes}" target="1.5" source="1.5"
|
||||
encoding="UTF-8" debug="on" includeantruntime="false">
|
||||
<classpath>
|
||||
<path refid="classpath"/>
|
||||
</classpath>
|
||||
</javac>
|
||||
</target>
|
||||
|
||||
<!-- Create jar-file. -->
|
||||
<target name="jar" depends="compile">
|
||||
|
||||
<!-- Copy all non-java files to classes. -->
|
||||
<copy todir="${classes}/com">
|
||||
<fileset dir="${src}/com">
|
||||
<exclude name="**/*.java"/>
|
||||
</fileset>
|
||||
</copy>
|
||||
|
||||
<jar jarfile="${jar}" basedir="${classes}">
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="${main-class}"/>
|
||||
</manifest>
|
||||
<!-- platform -->
|
||||
<fileset dir="../platform/build/classes/com"/>
|
||||
<!-- jna -->
|
||||
<zipfileset src="${file.reference.jna.jar}"/>
|
||||
</jar>
|
||||
</target>
|
||||
</project>
|
||||
|
||||
@@ -14,17 +14,14 @@ debug.test.classpath=\
|
||||
${run.test.classpath}
|
||||
# This directory is removed when the project is cleaned:
|
||||
dist.dir=dist
|
||||
dist.jar=${dist.dir}/platform.jar
|
||||
dist.jar=${dist.dir}/jna-platform.jar
|
||||
dist.javadoc.dir=${dist.dir}/javadoc
|
||||
file.reference.jna.jar=../../build/jna.jar
|
||||
file.reference.jna-d64.jar=../../build-d64/jna.jar
|
||||
file.reference.jna-test.jar=../../build/jna-test.jar
|
||||
file.reference.jna-test-d64.jar=../../build-d64/jna-test.jar
|
||||
libs.junit.classpath=../../lib/junit.jar
|
||||
jar.compress=false
|
||||
javac.classpath=\
|
||||
${file.reference.jna.jar}:\
|
||||
${file.reference.jna-d64.jar}
|
||||
${file.reference.jna.jar}
|
||||
# Space-separated list of extra javac options
|
||||
javac.compilerargs=
|
||||
javac.deprecation=false
|
||||
@@ -33,7 +30,6 @@ javac.target=1.5
|
||||
javac.test.classpath=\
|
||||
${javac.classpath}:\
|
||||
${file.reference.jna-test.jar}:\
|
||||
${file.reference.jna-test-d64.jar}:\
|
||||
${build.classes.dir}:\
|
||||
${libs.junit.classpath}
|
||||
javadoc.additionalparam=
|
||||
|
||||
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
@@ -18,6 +18,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.sun.jna.LastErrorException;
|
||||
import com.sun.jna.Memory;
|
||||
import com.sun.jna.Native;
|
||||
import com.sun.jna.platform.win32.WinNT.HANDLE;
|
||||
import com.sun.jna.platform.win32.WinNT.HANDLEByReference;
|
||||
@@ -48,7 +49,7 @@ public abstract class Kernel32Util implements WinDef {
|
||||
|
||||
/**
|
||||
* Format a message from the value obtained from {@link
|
||||
* Kernel32.GetLastError} or {@link Native.getLastError}.
|
||||
* Kernel32#GetLastError} or {@link Native#getLastError}.
|
||||
* @param code
|
||||
* int
|
||||
* @return
|
||||
@@ -84,7 +85,7 @@ public abstract class Kernel32Util implements WinDef {
|
||||
return formatMessage(code.intValue());
|
||||
}
|
||||
|
||||
/** @deprecated use {@link formatMessage(HRESULT)} instead. */
|
||||
/** @deprecated use {@link #formatMessage(WinNT.HRESULT)} instead. */
|
||||
public static String formatMessageFromHR(HRESULT code) {
|
||||
return formatMessage(code.intValue());
|
||||
}
|
||||
@@ -305,4 +306,33 @@ public abstract class Kernel32Util implements WinDef {
|
||||
if (!Kernel32.INSTANCE.WritePrivateProfileString(appName, keyName, string, fileName))
|
||||
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to get the processor information. Takes care of auto-growing the array.
|
||||
*
|
||||
* @return the array of processor information.
|
||||
*/
|
||||
public static final WinNT.SYSTEM_LOGICAL_PROCESSOR_INFORMATION[] getLogicalProcessorInformation()
|
||||
{
|
||||
int sizePerStruct = new WinNT.SYSTEM_LOGICAL_PROCESSOR_INFORMATION().size();
|
||||
WinDef.DWORDByReference bufferSize = new WinDef.DWORDByReference(new WinDef.DWORD(sizePerStruct));
|
||||
Memory memory;
|
||||
while (true)
|
||||
{
|
||||
memory = new Memory(bufferSize.getValue().intValue());
|
||||
if (! Kernel32.INSTANCE.GetLogicalProcessorInformation(memory, bufferSize))
|
||||
{
|
||||
int err = Kernel32.INSTANCE.GetLastError();
|
||||
if (err != WinError.ERROR_INSUFFICIENT_BUFFER)
|
||||
throw new Win32Exception(err);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
WinNT.SYSTEM_LOGICAL_PROCESSOR_INFORMATION firstInformation = new WinNT.SYSTEM_LOGICAL_PROCESSOR_INFORMATION(memory);
|
||||
int returnedStructCount = bufferSize.getValue().intValue() / sizePerStruct;
|
||||
return (WinNT.SYSTEM_LOGICAL_PROCESSOR_INFORMATION[]) firstInformation.toArray(new WinNT.SYSTEM_LOGICAL_PROCESSOR_INFORMATION[returnedStructCount]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import com.sun.jna.Native;
|
||||
import com.sun.jna.platform.win32.WinDef.DWORD;
|
||||
import com.sun.jna.platform.win32.WinDef.HWND;
|
||||
import com.sun.jna.platform.win32.WinDef.INT_PTR;
|
||||
import com.sun.jna.platform.win32.WinDef.UINT_PTR;
|
||||
import com.sun.jna.platform.win32.WinNT.HANDLE;
|
||||
import com.sun.jna.platform.win32.WinNT.HRESULT;
|
||||
import com.sun.jna.ptr.PointerByReference;
|
||||
@@ -168,4 +169,42 @@ public interface Shell32 extends ShellAPI, StdCallLibrary {
|
||||
* @return {@code true} if successful; otherwise, {@code false}.
|
||||
*/
|
||||
boolean SHGetSpecialFolderPath(HWND owner, char[] path, int csidl, boolean create);
|
||||
|
||||
|
||||
/**
|
||||
* SHAppBarMessage function
|
||||
*
|
||||
* @param dwMessage
|
||||
* Appbar message value to send. This parameter can be one of the following values.
|
||||
* {@link ShellAPI#ABM_NEW} Registers a new appbar and specifies the message identifier that the system should use to send notification messages to the appbar.
|
||||
* {@link ShellAPI#ABM_REMOVE} Unregisters an appbar, removing the bar from the system's internal list.
|
||||
* {@link ShellAPI#ABM_QUERYPOS} Requests a size and screen position for an appbar.
|
||||
* {@link ShellAPI#ABM_SETPOS} Sets the size and screen position of an appbar.
|
||||
* {@link ShellAPI#ABM_GETSTATE} Retrieves the autohide and always-on-top states of the Windows taskbar.
|
||||
* {@link ShellAPI#ABM_GETTASKBARPOS} Retrieves the bounding rectangle of the Windows taskbar. Note that this applies only to the system taskbar. Other objects, particularly toolbars supplied with third-party software, also can be present. As a result, some of the screen area not covered by the Windows taskbar might not be visible to the user. To retrieve the area of the screen not covered by both the taskbar and other app barsÑthe working area available to your applicationÑ, use the GetMonitorInfo function.
|
||||
* {@link ShellAPI#ABM_ACTIVATE} Notifies the system to activate or deactivate an appbar. The lParam member of the APPBARDATA pointed to by pData is set to TRUE to activate or FALSE to deactivate.
|
||||
* {@link ShellAPI#ABM_GETAUTOHIDEBAR} Retrieves the handle to the autohide appbar associated with a particular edge of the screen.
|
||||
* {@link ShellAPI#ABM_SETAUTOHIDEBAR} Registers or unregisters an autohide appbar for an edge of the screen.
|
||||
* {@link ShellAPI#ABM_WINDOWPOSCHANGED} Notifies the system when an appbar's position has changed.
|
||||
* {@link ShellAPI#ABM_SETSTATE} Windows XP and later: Sets the state of the appbar's autohide and always-on-top attributes.
|
||||
*
|
||||
* @param pData
|
||||
* A pointer to an APPBARDATA structure. The content of the structure on entry and on exit depends on the value set in the dwMessage parameter. See the individual message pages for specifics.
|
||||
*
|
||||
* @return This function returns a message-dependent value. For more information, see the Windows SDK documentation for the specific appbar message sent.
|
||||
*
|
||||
* @see <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/bb787951(v=vs.85).aspx">ABM_NEW</a>
|
||||
* @see <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/bb787955(v=vs.85).aspx">ABM_REMOVE</a>
|
||||
* @see <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/bb787953(v=vs.85).aspx">ABM_QUERYPOS</a>
|
||||
* @see <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/bb787959(v=vs.85).aspx">ABM_SETPOS</a>
|
||||
* @see <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/bb787947(v=vs.85).aspx">ABM_GETSTATE</a>
|
||||
* @see <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/bb787949(v=vs.85).aspx">ABM_GETTASKBARPOS</a>
|
||||
* @see <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/bb787943(v=vs.85).aspx">ABM_ACTIVATE</a>
|
||||
* @see <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/bb787945(v=vs.85).aspx">ABM_GETAUTOHIDEBAR</a>
|
||||
* @see <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/bb787957(v=vs.85).aspx">ABM_SETAUTOHIDEBAR</a>
|
||||
* @see <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/bb787963(v=vs.85).aspx">ABM_WINDOWPOSCHANGED</a>
|
||||
* @see <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/bb787961(v=vs.85).aspx">ABM_SETSTATE</a>
|
||||
*
|
||||
*/
|
||||
UINT_PTR SHAppBarMessage( DWORD dwMessage, APPBARDATA pData );
|
||||
}
|
||||
|
||||
@@ -19,7 +19,13 @@ import com.sun.jna.Platform;
|
||||
import com.sun.jna.Pointer;
|
||||
import com.sun.jna.Structure;
|
||||
import com.sun.jna.WString;
|
||||
import com.sun.jna.platform.win32.WinDef.DWORD;
|
||||
import com.sun.jna.platform.win32.WinDef.HWND;
|
||||
import com.sun.jna.platform.win32.WinDef.LPARAM;
|
||||
import com.sun.jna.platform.win32.WinDef.RECT;
|
||||
import com.sun.jna.platform.win32.WinDef.UINT;
|
||||
import com.sun.jna.platform.win32.WinNT.HANDLE;
|
||||
import com.sun.jna.platform.win32.WinNT.PSID;
|
||||
import com.sun.jna.win32.StdCallLibrary;
|
||||
|
||||
/**
|
||||
@@ -115,5 +121,89 @@ public interface ShellAPI extends StdCallLibrary {
|
||||
}
|
||||
return encoded + "\0";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Appbar message value to send. This parameter can be one of the following
|
||||
* values.
|
||||
*/
|
||||
int ABM_NEW = 0x00000000;
|
||||
/**
|
||||
* Registers a new appbar and specifies the message identifier that the
|
||||
* system should use to send notification messages to the appbar.
|
||||
*/
|
||||
int ABM_REMOVE = 0x00000001;
|
||||
/** Unregisters an appbar, removing the bar from the system's internal list.*/
|
||||
int ABM_QUERYPOS = 0x00000002;
|
||||
/** Requests a size and screen position for an appbar. */
|
||||
int ABM_SETPOS = 0x00000003;
|
||||
/** Sets the size and screen position of an appbar. */
|
||||
int ABM_GETSTATE = 0x00000004;
|
||||
/** Retrieves the autohide and always-on-top states of the Windows taskbar. */
|
||||
int ABM_GETTASKBARPOS = 0x00000005;
|
||||
/**
|
||||
* Retrieves the bounding rectangle of the Windows taskbar. Note that this
|
||||
* applies only to the system taskbar. Other objects, particularly toolbars
|
||||
* supplied with third-party software, also can be present. As a result,
|
||||
* some of the screen area not covered by the Windows taskbar might not be
|
||||
* visible to the user. To retrieve the area of the screen not covered by
|
||||
* both the taskbar and other app barsÑthe working area available to your
|
||||
* applicationÑ, use the GetMonitorInfo function.
|
||||
*/
|
||||
int ABM_ACTIVATE = 0x00000006;
|
||||
/**
|
||||
* Notifies the system to activate or deactivate an appbar. The lParam
|
||||
* member of the APPBARDATA pointed to by pData is set to TRUE to activate
|
||||
* or FALSE to deactivate.
|
||||
*/
|
||||
int ABM_GETAUTOHIDEBAR = 0x00000007;
|
||||
/**
|
||||
* Retrieves the handle to the autohide appbar associated with a particular
|
||||
* edge of the screen.
|
||||
*/
|
||||
int ABM_SETAUTOHIDEBAR = 0x00000008;
|
||||
/** Registers or unregisters an autohide appbar for an edge of the screen. */
|
||||
int ABM_WINDOWPOSCHANGED = 0x00000009;
|
||||
/** Notifies the system when an appbar's position has changed. */
|
||||
int ABM_SETSTATE = 0x0000000A;
|
||||
|
||||
/** Left edge. */
|
||||
int ABE_LEFT = 0;
|
||||
/** Top edge. */
|
||||
int ABE_TOP = 1;
|
||||
/** Right edge. */
|
||||
int ABE_RIGHT = 2;
|
||||
/** Bottom edge. */
|
||||
int ABE_BOTTOM = 3;
|
||||
|
||||
/**
|
||||
* Contains information about a system appbar message.
|
||||
*/
|
||||
public static class APPBARDATA extends Structure {
|
||||
public static class ByReference extends APPBARDATA implements Structure.ByReference {
|
||||
}
|
||||
|
||||
public DWORD cbSize;
|
||||
public HWND hWnd;
|
||||
public UINT uCallbackMessage;
|
||||
public UINT uEdge;
|
||||
public RECT rc;
|
||||
public LPARAM lParam;
|
||||
|
||||
public APPBARDATA() {
|
||||
super();
|
||||
}
|
||||
|
||||
public APPBARDATA(Pointer p) {
|
||||
super(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List getFieldOrder() {
|
||||
return Arrays.asList("cbSize", "hWnd", "uCallbackMessage", "uEdge", "rc", "lParam");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -429,7 +429,7 @@ public interface WinBase extends StdCallLibrary, WinDef, BaseTSD {
|
||||
|
||||
protected List getFieldOrder() {
|
||||
return Arrays.asList(new String[] { "wProcessorArchitecture", "wReserved" });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Unnamed inner union. */
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
/* 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.
|
||||
* Lesser General Public License for more details.
|
||||
*/
|
||||
package com.sun.jna.platform.win32;
|
||||
|
||||
@@ -25,12 +25,15 @@ import com.sun.jna.Structure;
|
||||
import com.sun.jna.Union;
|
||||
import com.sun.jna.ptr.ByReference;
|
||||
|
||||
import com.sun.jna.platform.win32.WinNT.SYSTEM_LOGICAL_PROCESSOR_INFORMATION;
|
||||
import com.sun.jna.platform.win32.WinNT.LOGICAL_PROCESSOR_RELATIONSHIP;
|
||||
|
||||
/**
|
||||
* This module defines the 32-Bit Windows types and constants that are defined
|
||||
* by NT, but exposed through the Win32 API. Ported from WinNT.h Microsoft
|
||||
* Windows SDK 6.0A. Avoid including any NIO Buffer mappings here; put them in a
|
||||
* DLL-derived interface (e.g. kernel32, user32, etc) instead.
|
||||
*
|
||||
*
|
||||
* @author dblock[at]dblock.org
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
@@ -251,7 +254,7 @@ public interface WinNT extends WinError, WinDef, WinBase, BaseTSD {
|
||||
protected List getFieldOrder() {
|
||||
return Arrays.asList(new String[] { "Luid", "Attributes" });
|
||||
}
|
||||
|
||||
|
||||
public LUID_AND_ATTRIBUTES() {
|
||||
}
|
||||
|
||||
@@ -266,11 +269,11 @@ public interface WinNT extends WinError, WinDef, WinBase, BaseTSD {
|
||||
* and its attributes. SIDs are used to uniquely identify users or groups.
|
||||
*/
|
||||
public static class SID_AND_ATTRIBUTES extends Structure {
|
||||
|
||||
|
||||
protected List getFieldOrder() {
|
||||
return Arrays.asList(new String[] { "Sid", "Attributes" });
|
||||
}
|
||||
|
||||
|
||||
public SID_AND_ATTRIBUTES() {
|
||||
super();
|
||||
}
|
||||
@@ -296,11 +299,11 @@ public interface WinNT extends WinError, WinDef, WinBase, BaseTSD {
|
||||
* (SID) that will be applied to newly created objects.
|
||||
*/
|
||||
public static class TOKEN_OWNER extends Structure {
|
||||
|
||||
|
||||
protected List getFieldOrder() {
|
||||
return Arrays.asList(new String[] { "Owner" });
|
||||
}
|
||||
|
||||
|
||||
public TOKEN_OWNER() {
|
||||
super();
|
||||
}
|
||||
@@ -324,9 +327,9 @@ public interface WinNT extends WinError, WinDef, WinBase, BaseTSD {
|
||||
|
||||
public static class PSID extends Structure {
|
||||
public static class ByReference extends PSID implements Structure.ByReference { }
|
||||
|
||||
protected List getFieldOrder() {
|
||||
return Arrays.asList(new String[] { "sid" });
|
||||
|
||||
protected List getFieldOrder() {
|
||||
return Arrays.asList(new String[] { "sid" });
|
||||
}
|
||||
|
||||
public PSID() {
|
||||
@@ -386,11 +389,11 @@ public interface WinNT extends WinError, WinDef, WinBase, BaseTSD {
|
||||
* token.
|
||||
*/
|
||||
public static class TOKEN_USER extends Structure {
|
||||
|
||||
|
||||
protected List getFieldOrder() {
|
||||
return Arrays.asList(new String[] { "User" });
|
||||
}
|
||||
|
||||
|
||||
public TOKEN_USER() {
|
||||
super();
|
||||
}
|
||||
@@ -417,11 +420,11 @@ public interface WinNT extends WinError, WinDef, WinBase, BaseTSD {
|
||||
* identifiers (SIDs) in an access token.
|
||||
*/
|
||||
public static class TOKEN_GROUPS extends Structure {
|
||||
|
||||
|
||||
protected List getFieldOrder() {
|
||||
return Arrays.asList(new String[] { "GroupCount", "Group0" });
|
||||
}
|
||||
|
||||
|
||||
public TOKEN_GROUPS() {
|
||||
super();
|
||||
}
|
||||
@@ -465,7 +468,7 @@ public interface WinNT extends WinError, WinDef, WinBase, BaseTSD {
|
||||
* contains the LUID and attributes of a privilege.
|
||||
*/
|
||||
public LUID_AND_ATTRIBUTES Privileges[];
|
||||
|
||||
|
||||
protected List getFieldOrder() {
|
||||
return Arrays.asList(new String[] { "PrivilegeCount", "Privileges" });
|
||||
}
|
||||
@@ -679,7 +682,7 @@ public interface WinNT extends WinError, WinDef, WinBase, BaseTSD {
|
||||
/**
|
||||
* The FILE_NOTIFY_INFORMATION structure describes the changes found by the
|
||||
* ReadDirectoryChangesW function.
|
||||
*
|
||||
*
|
||||
* This structure is non-trivial since it is a pattern stamped into a large
|
||||
* block of result memory rather than something that stands alone or is used
|
||||
* for input.
|
||||
@@ -690,7 +693,7 @@ public interface WinNT extends WinError, WinDef, WinBase, BaseTSD {
|
||||
public int FileNameLength;
|
||||
// filename is not nul-terminated, so we can't use a String/WString
|
||||
public char[] FileName = new char[1];
|
||||
|
||||
|
||||
protected List getFieldOrder() {
|
||||
return Arrays.asList(new String[] { "NextEntryOffset", "Action", "FileNameLength", "FileName" });
|
||||
}
|
||||
@@ -946,7 +949,7 @@ public interface WinNT extends WinError, WinDef, WinBase, BaseTSD {
|
||||
int REG_FULL_RESOURCE_DESCRIPTOR = 9;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
int REG_RESOURCE_REQUIREMENTS_LIST = 10;
|
||||
|
||||
@@ -994,14 +997,14 @@ public interface WinNT extends WinError, WinDef, WinBase, BaseTSD {
|
||||
}
|
||||
|
||||
public UNION u;
|
||||
|
||||
|
||||
protected List getFieldOrder() {
|
||||
return Arrays.asList(new String[] { "u" });
|
||||
}
|
||||
|
||||
/**
|
||||
* Low DWORD.
|
||||
*
|
||||
*
|
||||
* @return DWORD.
|
||||
*/
|
||||
public DWORD getLow() {
|
||||
@@ -1010,7 +1013,7 @@ public interface WinNT extends WinError, WinDef, WinBase, BaseTSD {
|
||||
|
||||
/**
|
||||
* High DWORD.
|
||||
*
|
||||
*
|
||||
* @return DWORD.
|
||||
*/
|
||||
public DWORD getHigh() {
|
||||
@@ -1019,7 +1022,7 @@ public interface WinNT extends WinError, WinDef, WinBase, BaseTSD {
|
||||
|
||||
/**
|
||||
* 64-bit value.
|
||||
*
|
||||
*
|
||||
* @return 64-bit value.
|
||||
*/
|
||||
public long getValue() {
|
||||
@@ -1435,72 +1438,72 @@ public interface WinNT extends WinError, WinDef, WinBase, BaseTSD {
|
||||
public static final int WinBuiltinTerminalServerLicenseServersSid = 60;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
public static final int WinBuiltinDCOMUsersSid = 61;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
public static final int WinBuiltinIUsersSid = 62;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
public static final int WinIUserSid = 63;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
public static final int WinBuiltinCryptoOperatorsSid = 64;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
public static final int WinUntrustedLabelSid = 65;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
public static final int WinLowLabelSid = 66;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
public static final int WinMediumLabelSid = 67;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
public static final int WinHighLabelSid = 68;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
public static final int WinSystemLabelSid = 69;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
public static final int WinWriteRestrictedCodeSid = 70;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
public static final int WinCreatorOwnerRightsSid = 71;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
public static final int WinCacheablePrincipalsGroupSid = 72;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
public static final int WinNonCacheablePrincipalsGroupSid = 73;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
public static final int WinEnterpriseReadonlyControllersSid = 74;
|
||||
|
||||
@@ -1572,7 +1575,7 @@ public interface WinNT extends WinError, WinDef, WinBase, BaseTSD {
|
||||
protected List getFieldOrder() {
|
||||
return Arrays.asList(new String[] { "dwOSVersionInfoSize", "dwMajorVersion", "dwMinorVersion", "dwBuildNumber", "dwPlatformId", "szCSDVersion" });
|
||||
}
|
||||
|
||||
|
||||
public OSVERSIONINFO() {
|
||||
szCSDVersion = new char[128];
|
||||
dwOSVersionInfoSize = new DWORD(size()); // sizeof(OSVERSIONINFO)
|
||||
@@ -1657,7 +1660,7 @@ public interface WinNT extends WinError, WinDef, WinBase, BaseTSD {
|
||||
protected List getFieldOrder() {
|
||||
return Arrays.asList(new String[] { "dwOSVersionInfoSize", "dwMajorVersion", "dwMinorVersion", "dwBuildNumber", "dwPlatformId", "szCSDVersion", "wServicePackMajor", "wServicePackMinor", "wSuiteMask", "wProductType", "wReserved"});
|
||||
}
|
||||
|
||||
|
||||
public OSVERSIONINFOEX() {
|
||||
szCSDVersion = new char[128];
|
||||
dwOSVersionInfoSize = new DWORD(size()); // sizeof(OSVERSIONINFOEX)
|
||||
@@ -1862,7 +1865,7 @@ public interface WinNT extends WinError, WinDef, WinBase, BaseTSD {
|
||||
protected List getFieldOrder() {
|
||||
return Arrays.asList(new String[] { "Length", "Reserved", "RecordNumber", "TimeGenerated", "TimeWritten", "EventID", "EventType", "NumStrings", "EventCategory", "ReservedFlags", "ClosingRecordNumber", "StringOffset", "UserSidLength", "UserSidOffset", "DataLength", "DataOffset"});
|
||||
}
|
||||
|
||||
|
||||
public EVENTLOGRECORD() {
|
||||
}
|
||||
|
||||
@@ -1960,18 +1963,18 @@ public interface WinNT extends WinError, WinDef, WinBase, BaseTSD {
|
||||
}
|
||||
|
||||
public byte[] data;
|
||||
|
||||
|
||||
protected List getFieldOrder() {
|
||||
return Arrays.asList(new String[] { "data" });
|
||||
}
|
||||
}
|
||||
|
||||
public static class ACL extends Structure {
|
||||
|
||||
|
||||
protected List getFieldOrder() {
|
||||
return Arrays.asList(new String[] { "AclRevision", "Sbz1", "AclSize", "AceCount", "Sbz2" });
|
||||
}
|
||||
|
||||
|
||||
public ACL() {
|
||||
}
|
||||
|
||||
@@ -2030,7 +2033,7 @@ public interface WinNT extends WinError, WinDef, WinBase, BaseTSD {
|
||||
protected List getFieldOrder() {
|
||||
return Arrays.asList(new String[] { "Revision", "Sbz1", "Control", "Owner", "Group", "Sacl", "Dacl" });
|
||||
}
|
||||
|
||||
|
||||
private ACL DACL;
|
||||
|
||||
public SECURITY_DESCRIPTOR_RELATIVE() {
|
||||
@@ -2070,7 +2073,7 @@ public interface WinNT extends WinError, WinDef, WinBase, BaseTSD {
|
||||
public ACEStructure(Pointer p) {
|
||||
super(p);
|
||||
}
|
||||
|
||||
|
||||
protected List getFieldOrder() {
|
||||
return Arrays.asList(new String[] { "AceType", "AceFlags", "AceSize" });
|
||||
}
|
||||
@@ -2172,4 +2175,218 @@ public interface WinNT extends WinError, WinDef, WinBase, BaseTSD {
|
||||
void callback(int errorCode, int nBytesTransferred,
|
||||
WinBase.OVERLAPPED overlapped);
|
||||
}
|
||||
|
||||
/**
|
||||
* Describes the relationship between the specified processor set. This structure is used with the
|
||||
* {@link Kernel32#GetLogicalProcessorInformation} function.
|
||||
*/
|
||||
public static class SYSTEM_LOGICAL_PROCESSOR_INFORMATION extends Structure {
|
||||
/**
|
||||
* The processor mask identifying the processors described by this structure. A processor mask is a bit
|
||||
* vector in which each set bit represents an active processor in the relationship.
|
||||
*/
|
||||
public ULONG_PTR processorMask;
|
||||
|
||||
/**
|
||||
* The relationship between the processors identified by the value of the {@link #processorMask} member.
|
||||
* This member can be one of
|
||||
* {@link LOGICAL_PROCESSOR_RELATIONSHIP#RelationCache},
|
||||
* {@link LOGICAL_PROCESSOR_RELATIONSHIP#RelationNumaNode},
|
||||
* {@link LOGICAL_PROCESSOR_RELATIONSHIP#RelationProcessorCore} or
|
||||
* {@link LOGICAL_PROCESSOR_RELATIONSHIP#RelationProcessorPackage}.
|
||||
*
|
||||
* @see LOGICAL_PROCESSOR_RELATIONSHIP
|
||||
*/
|
||||
public int /* LOGICAL_PROCESSOR_RELATIONSHIP */ relationship;
|
||||
|
||||
/**
|
||||
* A union of fields which differs depending on {@link #relationship}.
|
||||
*/
|
||||
public AnonymousUnionPayload payload;
|
||||
|
||||
public SYSTEM_LOGICAL_PROCESSOR_INFORMATION() {
|
||||
}
|
||||
|
||||
public SYSTEM_LOGICAL_PROCESSOR_INFORMATION(Pointer memory) {
|
||||
super(memory);
|
||||
read();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List getFieldOrder() {
|
||||
return Arrays.asList(new String[] { "processorMask", "relationship", "payload" });
|
||||
}
|
||||
|
||||
public static class AnonymousUnionPayload extends Union {
|
||||
/**
|
||||
* Contains valid data only if {@link #relationship} is {@link LOGICAL_PROCESSOR_RELATIONSHIP#RelationProcessorCore}.
|
||||
*/
|
||||
public AnonymousStructProcessorCore processorCore;
|
||||
|
||||
/**
|
||||
* Contains valid data only if {@link #relationship} is {@link LOGICAL_PROCESSOR_RELATIONSHIP#RelationNumaNode}.
|
||||
*/
|
||||
public AnonymousStructNumaNode numaNode;
|
||||
|
||||
/**
|
||||
* <p>Identifies the characteristics of a particular cache. There is one record returned for each cache
|
||||
* reported. Some or all caches may not be reported, depending on how caches are identified. Therefore,
|
||||
* do not assume the absence of any particular caches. Caches are not necessarily shared among
|
||||
* logical processors.</p>
|
||||
*
|
||||
* <p>Contains valid data only if {@link #relationship} is
|
||||
* {@link LOGICAL_PROCESSOR_RELATIONSHIP#RelationCache}.</p>
|
||||
*
|
||||
* <p>This member was not supported until Windows Server 2003 SP1 / Windows XP Professional x64.</p>
|
||||
*/
|
||||
public CACHE_DESCRIPTOR cache;
|
||||
|
||||
/**
|
||||
* Reserved. Do not use.
|
||||
*/
|
||||
public ULONGLONG[] reserved = new ULONGLONG[2];
|
||||
}
|
||||
|
||||
public static class AnonymousStructProcessorCore extends Structure {
|
||||
/**
|
||||
* <p>If the value of this mmeber is {@code 1}, the logical processors identified by the value of the
|
||||
* {@link #processorMask} member share functional units, as in Hyperthreading or SMT. Otherwise, the
|
||||
* identified logical processors do not share functional units.</p>
|
||||
*
|
||||
* <p>Note: Prior to Windows Vista, this member is also {@code 1} for cores that share a physical
|
||||
* package.</p>
|
||||
*/
|
||||
public BYTE flags;
|
||||
|
||||
@Override
|
||||
protected List getFieldOrder() {
|
||||
return Arrays.asList(new String[] { "flags" });
|
||||
}
|
||||
}
|
||||
|
||||
public static class AnonymousStructNumaNode extends Structure {
|
||||
/**
|
||||
* Identifies the NUMA node. Valid values are {@code 0} to the highest NUMA node number inclusive.
|
||||
* A non-NUMA multiprocessor system will report that all processors belong to one NUMA node.
|
||||
*/
|
||||
public DWORD nodeNumber;
|
||||
|
||||
@Override
|
||||
protected List getFieldOrder() {
|
||||
return Arrays.asList(new String[] { "nodeNumber" });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the relationship between the processor set identified in the corresponding
|
||||
* {@link SYSTEM_LOGICAL_PROCESSOR_INFORMATION} or <code>SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX</code> structure.
|
||||
*/
|
||||
public interface LOGICAL_PROCESSOR_RELATIONSHIP {
|
||||
/**
|
||||
* The specified logical processors share a single processor core.
|
||||
*/
|
||||
int RelationProcessorCore = 0;
|
||||
|
||||
/**
|
||||
* The specified logical processors are part of the same NUMA node.
|
||||
*/
|
||||
int RelationNumaNode = 1;
|
||||
|
||||
/**
|
||||
* <p>The specified logical processors share a cache.</p>
|
||||
*
|
||||
* <p>Not supported until Windows Server 2003 SP1 / Windows XP Professional x64.</p>
|
||||
*/
|
||||
int RelationCache = 2;
|
||||
|
||||
/**
|
||||
* <p>The specified logical processors share a physical package (a single package socketed or soldered onto a
|
||||
* motherboard may contain multiple processor cores or threads, each of which is treated as a separate
|
||||
* processor by the operating system.)</p>
|
||||
*
|
||||
* <p>Not supported until Windows Server 2003 SP1 / Windows XP Professional x64.</p>
|
||||
*/
|
||||
int RelationProcessorPackage = 3;
|
||||
|
||||
/**
|
||||
* <p>The specified logical processors share a single processor group.</p>
|
||||
*
|
||||
* <p>Not supported until Windows Server 2008 R2.</p>
|
||||
*/
|
||||
int RelationGroup = 4;
|
||||
|
||||
/**
|
||||
* <p>On input, retrieves information about all possible relation types. This value is not used on output.</p>
|
||||
*
|
||||
* <p>Not supported until Windows Server 2008 R2.</p>
|
||||
*/
|
||||
int RelationAll = 0xFFFF;
|
||||
}
|
||||
|
||||
byte CACHE_FULLY_ASSOCIATIVE = (byte)0xFF;
|
||||
|
||||
/**
|
||||
* Describes the cache attributes.
|
||||
*/
|
||||
public static class CACHE_DESCRIPTOR extends Structure {
|
||||
/**
|
||||
* The cache level. This member can be 1, 2 or 3, corresponding to L1, L2 or L3 cache, respectively (other
|
||||
* values may be supported in the future.)
|
||||
*/
|
||||
public BYTE level;
|
||||
|
||||
/**
|
||||
* The cache associativity. If this member is {@link #CACHE_FULLY_ASSOCIATIVE}, the cache is fully
|
||||
* associative.
|
||||
*/
|
||||
public BYTE associativity;
|
||||
|
||||
/**
|
||||
* The cache line size, in bytes.
|
||||
*/
|
||||
public WORD lineSize;
|
||||
|
||||
/**
|
||||
* The cache size, in bytes.
|
||||
*/
|
||||
public DWORD size;
|
||||
|
||||
/**
|
||||
* The cache type.
|
||||
*
|
||||
* @see PROCESSOR_CACHE_TYPE
|
||||
*/
|
||||
public int /* PROCESSOR_CACHE_TYPE */ type;
|
||||
|
||||
@Override
|
||||
protected List getFieldOrder() {
|
||||
return Arrays.asList(new String[] { "level", "associativity", "lineSize", "size", "type" });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the type of processor cache identifier in the corresponding {@link CACHE_DESCRIPTOR} structure.
|
||||
*/
|
||||
public static abstract class PROCESSOR_CACHE_TYPE {
|
||||
/**
|
||||
* The cache is unified.
|
||||
*/
|
||||
public static int CacheUnified = 0;
|
||||
|
||||
/**
|
||||
* The cache is for processor instructions.
|
||||
*/
|
||||
public static int CacheInstruction = 1;
|
||||
|
||||
/**
|
||||
* The cache is for data.
|
||||
*/
|
||||
public static int CacheData = 2;
|
||||
|
||||
/**
|
||||
* The cache is for traces.
|
||||
*/
|
||||
public static int CacheTrace = 3;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import java.io.PrintWriter;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import com.sun.jna.platform.win32.WinNT.LARGE_INTEGER;
|
||||
import com.sun.jna.platform.win32.WinNT.LOGICAL_PROCESSOR_RELATIONSHIP;
|
||||
|
||||
/**
|
||||
* @author dblock[at]dblock[dot]org
|
||||
@@ -180,4 +181,13 @@ public class Kernel32UtilTest extends TestCase {
|
||||
assertEquals(reader.readLine(), null);
|
||||
reader.close();
|
||||
}
|
||||
|
||||
public final void testGetLogicalProcessorInformation() {
|
||||
WinNT.SYSTEM_LOGICAL_PROCESSOR_INFORMATION[] informationArray = Kernel32Util.getLogicalProcessorInformation();
|
||||
assertTrue(informationArray.length >= 1); // docs say so
|
||||
for (WinNT.SYSTEM_LOGICAL_PROCESSOR_INFORMATION info : informationArray) {
|
||||
assertTrue(info.processorMask.intValue() >= 0);
|
||||
assertTrue(info.relationship >= LOGICAL_PROCESSOR_RELATIONSHIP.RelationProcessorCore && info.relationship <= LOGICAL_PROCESSOR_RELATIONSHIP.RelationAll);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,14 +15,22 @@ package com.sun.jna.platform.win32;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import com.sun.jna.Native;
|
||||
import com.sun.jna.platform.win32.ShellAPI.APPBARDATA;
|
||||
import com.sun.jna.platform.win32.WinDef.DWORD;
|
||||
import com.sun.jna.platform.win32.WinDef.RECT;
|
||||
import com.sun.jna.platform.win32.WinDef.UINT_PTR;
|
||||
import com.sun.jna.ptr.PointerByReference;
|
||||
|
||||
|
||||
/**
|
||||
* @author dblock[at]dblock[dot]org
|
||||
* @author markus[at]headcrashing[dot]eu
|
||||
*/
|
||||
public class Shell32Test extends TestCase {
|
||||
|
||||
private static final int RESIZE_HEIGHT = 500;
|
||||
private static final int WM_USER = 0x0400;
|
||||
|
||||
public static void main(String[] args) {
|
||||
junit.textui.TestRunner.run(Shell32Test.class);
|
||||
}
|
||||
@@ -48,4 +56,75 @@ public class Shell32Test extends TestCase {
|
||||
assertTrue(Shell32.INSTANCE.SHGetSpecialFolderPath(null, pszPath, ShlObj.CSIDL_APPDATA, false));
|
||||
assertFalse(Native.toString(pszPath).isEmpty());
|
||||
}
|
||||
|
||||
|
||||
private void newAppBar() {
|
||||
APPBARDATA data = new APPBARDATA.ByReference();
|
||||
data.cbSize.setValue(data.size());
|
||||
data.uCallbackMessage.setValue(WM_USER + 1);
|
||||
|
||||
UINT_PTR result = Shell32.INSTANCE.SHAppBarMessage(new DWORD(ShellAPI.ABM_NEW), data);
|
||||
assertNotNull(result);
|
||||
}
|
||||
|
||||
private void removeAppBar() {
|
||||
APPBARDATA data = new APPBARDATA.ByReference();
|
||||
data.cbSize.setValue(data.size());
|
||||
UINT_PTR result = Shell32.INSTANCE.SHAppBarMessage(new DWORD(ShellAPI.ABM_REMOVE), data);
|
||||
assertNotNull(result);
|
||||
|
||||
}
|
||||
|
||||
private void queryPos(APPBARDATA data) {
|
||||
UINT_PTR h = Shell32.INSTANCE.SHAppBarMessage(new DWORD(ShellAPI.ABM_QUERYPOS), data);
|
||||
|
||||
assertNotNull(h);
|
||||
assertTrue(h.intValue() > 0);
|
||||
|
||||
}
|
||||
|
||||
public void testResizeDesktopFromBottom() throws InterruptedException {
|
||||
|
||||
newAppBar();
|
||||
|
||||
APPBARDATA data = new APPBARDATA.ByReference();
|
||||
|
||||
data.uEdge.setValue(ShellAPI.ABE_BOTTOM);
|
||||
data.rc.top = User32.INSTANCE.GetSystemMetrics(User32.SM_CYFULLSCREEN) - RESIZE_HEIGHT;
|
||||
data.rc.left = 0;
|
||||
data.rc.bottom = User32.INSTANCE.GetSystemMetrics(User32.SM_CYFULLSCREEN);
|
||||
data.rc.right = User32.INSTANCE.GetSystemMetrics(User32.SM_CXFULLSCREEN);
|
||||
|
||||
queryPos(data);
|
||||
|
||||
UINT_PTR h = Shell32.INSTANCE.SHAppBarMessage(new DWORD(ShellAPI.ABM_SETPOS), data);
|
||||
|
||||
assertNotNull(h);
|
||||
assertTrue(h.intValue() >= 0);
|
||||
|
||||
removeAppBar();
|
||||
}
|
||||
|
||||
public void testResizeDesktopFromTop() throws InterruptedException {
|
||||
|
||||
newAppBar();
|
||||
|
||||
APPBARDATA data = new APPBARDATA.ByReference();
|
||||
data.uEdge.setValue(ShellAPI.ABE_TOP);
|
||||
data.rc.top = 0;
|
||||
data.rc.left = 0;
|
||||
data.rc.bottom = RESIZE_HEIGHT;
|
||||
data.rc.right = User32.INSTANCE.GetSystemMetrics(User32.SM_CXFULLSCREEN);
|
||||
|
||||
queryPos(data);
|
||||
|
||||
UINT_PTR h = Shell32.INSTANCE.SHAppBarMessage(new DWORD(ShellAPI.ABM_SETPOS), data);
|
||||
|
||||
assertNotNull(h);
|
||||
assertTrue(h.intValue() >= 0);
|
||||
|
||||
removeAppBar();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,68 +1,68 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="jnacontrib.shapedwindowdemo" default="jar" basedir=".">
|
||||
<description>Builds, tests, and runs the project jnacontrib.shapedwindowdemo.</description>
|
||||
<!-- Locations -->
|
||||
<property name="src" location="."/>
|
||||
<property name="build" location="build"/>
|
||||
<property name="jna-dist" location="../../../dist"/>
|
||||
|
||||
<property name="classes" location="${build}/classes"/>
|
||||
<property name="jar" location="${build}/demo-shapedwindow.jar"/>
|
||||
<property name="file.reference.jna.jar" location="../../build/jna.jar"/>
|
||||
<property name="main-class" value="com.sun.jna.contrib.demo.ShapedWindowDemo" />
|
||||
|
||||
<path id="classpath">
|
||||
<fileset file="${file.reference.jna.jar}"/>
|
||||
<fileset dir="../platform/dist" includes="platform.jar"/>
|
||||
</path>
|
||||
|
||||
<!-- Run Demo. -->
|
||||
<target name="run" depends="compile">
|
||||
<java classname="${main-class}" fork="true">
|
||||
<classpath>
|
||||
<pathelement location="${classes}" />
|
||||
<path refid="classpath"/>
|
||||
</classpath>
|
||||
</java>
|
||||
</target>
|
||||
|
||||
<!-- Delete class and jar files. -->
|
||||
<target name="clean">
|
||||
<delete dir="${classes}"/>
|
||||
<delete file="${jar}"/>
|
||||
<delete dir="${build}"/>
|
||||
</target>
|
||||
|
||||
<!-- Compile all classes. -->
|
||||
<target name="compile">
|
||||
<mkdir dir="${classes}"/>
|
||||
<!-- Compile the project. -->
|
||||
<javac srcdir="${src}" destdir="${classes}" target="1.5" source="1.5"
|
||||
encoding="UTF-8" debug="on" includeantruntime="false">
|
||||
<classpath>
|
||||
<path refid="classpath"/>
|
||||
</classpath>
|
||||
</javac>
|
||||
</target>
|
||||
|
||||
<!-- Create jar-file. -->
|
||||
<target name="jar" depends="compile">
|
||||
|
||||
<!-- Copy all non-java files to classes. -->
|
||||
<copy todir="${classes}/com">
|
||||
<fileset dir="${src}/com">
|
||||
<exclude name="**/*.java"/>
|
||||
</fileset>
|
||||
</copy>
|
||||
|
||||
<jar jarfile="${jar}" basedir="${classes}">
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="${main-class}"/>
|
||||
</manifest>
|
||||
<!-- platform -->
|
||||
<fileset dir="../platform/build/classes/com"/>
|
||||
<!-- jna -->
|
||||
<zipfileset src="${file.reference.jna.jar}"/>
|
||||
</jar>
|
||||
</target>
|
||||
</project>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="jnacontrib.shapedwindowdemo" default="jar" basedir=".">
|
||||
<description>Builds, tests, and runs the project jnacontrib.shapedwindowdemo.</description>
|
||||
<!-- Locations -->
|
||||
<property name="src" location="."/>
|
||||
<property name="build" location="build"/>
|
||||
<property name="jna-dist" location="../../../dist"/>
|
||||
|
||||
<property name="classes" location="${build}/classes"/>
|
||||
<property name="jar" location="${build}/demo-shapedwindow.jar"/>
|
||||
<property name="file.reference.jna.jar" location="../../build/jna.jar"/>
|
||||
<property name="main-class" value="com.sun.jna.contrib.demo.ShapedWindowDemo" />
|
||||
|
||||
<path id="classpath">
|
||||
<fileset file="${file.reference.jna.jar}"/>
|
||||
<fileset dir="../platform/dist" includes="jna-platform.jar"/>
|
||||
</path>
|
||||
|
||||
<!-- Run Demo. -->
|
||||
<target name="run" depends="compile">
|
||||
<java classname="${main-class}" fork="true">
|
||||
<classpath>
|
||||
<pathelement location="${classes}" />
|
||||
<path refid="classpath"/>
|
||||
</classpath>
|
||||
</java>
|
||||
</target>
|
||||
|
||||
<!-- Delete class and jar files. -->
|
||||
<target name="clean">
|
||||
<delete dir="${classes}"/>
|
||||
<delete file="${jar}"/>
|
||||
<delete dir="${build}"/>
|
||||
</target>
|
||||
|
||||
<!-- Compile all classes. -->
|
||||
<target name="compile">
|
||||
<mkdir dir="${classes}"/>
|
||||
<!-- Compile the project. -->
|
||||
<javac srcdir="${src}" destdir="${classes}" target="1.5" source="1.5"
|
||||
encoding="UTF-8" debug="on" includeantruntime="false">
|
||||
<classpath>
|
||||
<path refid="classpath"/>
|
||||
</classpath>
|
||||
</javac>
|
||||
</target>
|
||||
|
||||
<!-- Create jar-file. -->
|
||||
<target name="jar" depends="compile">
|
||||
|
||||
<!-- Copy all non-java files to classes. -->
|
||||
<copy todir="${classes}/com">
|
||||
<fileset dir="${src}/com">
|
||||
<exclude name="**/*.java"/>
|
||||
</fileset>
|
||||
</copy>
|
||||
|
||||
<jar jarfile="${jar}" basedir="${classes}">
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="${main-class}"/>
|
||||
</manifest>
|
||||
<!-- platform -->
|
||||
<fileset dir="../platform/build/classes/com"/>
|
||||
<!-- jna -->
|
||||
<zipfileset src="${file.reference.jna.jar}"/>
|
||||
</jar>
|
||||
</target>
|
||||
</project>
|
||||
|
||||
@@ -1,68 +1,68 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="jnacontrib.w32keyhook" default="jar" basedir=".">
|
||||
<description>Builds, tests, and runs the project jnacontrib.w32keyhook.</description>
|
||||
<!-- Locations -->
|
||||
<property name="src" location="."/>
|
||||
<property name="build" location="build"/>
|
||||
<property name="jna-dist" location="../../../dist"/>
|
||||
|
||||
<property name="classes" location="${build}/classes"/>
|
||||
<property name="jar" location="${build}/demo-w32keyhook.jar"/>
|
||||
<property name="file.reference.jna.jar" location="../../build/jna.jar"/>
|
||||
<property name="main-class" value="com.sun.jna.contrib.demo.KeyHook" />
|
||||
|
||||
<path id="classpath">
|
||||
<fileset file="${file.reference.jna.jar}"/>
|
||||
<fileset dir="../platform/dist" includes="platform.jar"/>
|
||||
</path>
|
||||
|
||||
<!-- Run Demo. -->
|
||||
<target name="run" depends="compile">
|
||||
<java classname="${main-class}" fork="true">
|
||||
<classpath>
|
||||
<pathelement location="${classes}" />
|
||||
<path refid="classpath"/>
|
||||
</classpath>
|
||||
</java>
|
||||
</target>
|
||||
|
||||
<!-- Delete class and jar files. -->
|
||||
<target name="clean">
|
||||
<delete dir="${classes}"/>
|
||||
<delete file="${jar}"/>
|
||||
<delete dir="${build}"/>
|
||||
</target>
|
||||
|
||||
<!-- Compile all classes. -->
|
||||
<target name="compile">
|
||||
<mkdir dir="${classes}"/>
|
||||
<!-- Compile the project. -->
|
||||
<javac srcdir="${src}" destdir="${classes}" target="1.5" source="1.5"
|
||||
encoding="UTF-8" debug="on" includeantruntime="false">
|
||||
<classpath>
|
||||
<path refid="classpath"/>
|
||||
</classpath>
|
||||
</javac>
|
||||
</target>
|
||||
|
||||
<!-- Create jar-file. -->
|
||||
<target name="jar" depends="compile">
|
||||
|
||||
<!-- Copy all non-java files to classes. -->
|
||||
<copy todir="${classes}/com">
|
||||
<fileset dir="${src}/com">
|
||||
<exclude name="**/*.java"/>
|
||||
</fileset>
|
||||
</copy>
|
||||
|
||||
<jar jarfile="${jar}" basedir="${classes}">
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="${main-class}"/>
|
||||
</manifest>
|
||||
<!-- platform -->
|
||||
<fileset dir="../platform/build/classes" />
|
||||
<!-- jna -->
|
||||
<zipfileset src="${file.reference.jna.jar}" />
|
||||
</jar>
|
||||
</target>
|
||||
</project>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="jnacontrib.w32keyhook" default="jar" basedir=".">
|
||||
<description>Builds, tests, and runs the project jnacontrib.w32keyhook.</description>
|
||||
<!-- Locations -->
|
||||
<property name="src" location="."/>
|
||||
<property name="build" location="build"/>
|
||||
<property name="jna-dist" location="../../../dist"/>
|
||||
|
||||
<property name="classes" location="${build}/classes"/>
|
||||
<property name="jar" location="${build}/demo-w32keyhook.jar"/>
|
||||
<property name="file.reference.jna.jar" location="../../build/jna.jar"/>
|
||||
<property name="main-class" value="com.sun.jna.contrib.demo.KeyHook" />
|
||||
|
||||
<path id="classpath">
|
||||
<fileset file="${file.reference.jna.jar}"/>
|
||||
<fileset dir="../platform/dist" includes="jna-platform.jar"/>
|
||||
</path>
|
||||
|
||||
<!-- Run Demo. -->
|
||||
<target name="run" depends="compile">
|
||||
<java classname="${main-class}" fork="true">
|
||||
<classpath>
|
||||
<pathelement location="${classes}" />
|
||||
<path refid="classpath"/>
|
||||
</classpath>
|
||||
</java>
|
||||
</target>
|
||||
|
||||
<!-- Delete class and jar files. -->
|
||||
<target name="clean">
|
||||
<delete dir="${classes}"/>
|
||||
<delete file="${jar}"/>
|
||||
<delete dir="${build}"/>
|
||||
</target>
|
||||
|
||||
<!-- Compile all classes. -->
|
||||
<target name="compile">
|
||||
<mkdir dir="${classes}"/>
|
||||
<!-- Compile the project. -->
|
||||
<javac srcdir="${src}" destdir="${classes}" target="1.5" source="1.5"
|
||||
encoding="UTF-8" debug="on" includeantruntime="false">
|
||||
<classpath>
|
||||
<path refid="classpath"/>
|
||||
</classpath>
|
||||
</javac>
|
||||
</target>
|
||||
|
||||
<!-- Create jar-file. -->
|
||||
<target name="jar" depends="compile">
|
||||
|
||||
<!-- Copy all non-java files to classes. -->
|
||||
<copy todir="${classes}/com">
|
||||
<fileset dir="${src}/com">
|
||||
<exclude name="**/*.java"/>
|
||||
</fileset>
|
||||
</copy>
|
||||
|
||||
<jar jarfile="${jar}" basedir="${classes}">
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="${main-class}"/>
|
||||
</manifest>
|
||||
<!-- platform -->
|
||||
<fileset dir="../platform/build/classes" />
|
||||
<!-- jna -->
|
||||
<zipfileset src="${file.reference.jna.jar}" />
|
||||
</jar>
|
||||
</target>
|
||||
</project>
|
||||
|
||||
+77
-77
@@ -1,77 +1,77 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="jnacontrib.x11" default="jar" basedir=".">
|
||||
<description>Builds, tests, and runs the project jnacontrib.x11.</description>
|
||||
<!-- Locations -->
|
||||
<property name="src" location="src"/>
|
||||
<property name="build" location="build"/>
|
||||
<property name="jna-src" location="../../src"/>
|
||||
<property name="jna-dist" location="../../dist"/>
|
||||
<property name="classes" location="${build}/classes"/>
|
||||
<property name="jar" location="${build}/demo-x11.jar"/>
|
||||
<property name="file.reference.jna.jar" location="../../build/jna.jar"/>
|
||||
|
||||
<path id="classpath">
|
||||
<fileset file="${file.reference.jna.jar}"/>
|
||||
<fileset dir="../platform/dist" includes="platform.jar"/>
|
||||
</path>
|
||||
|
||||
<!-- Run XDesktopDemo. -->
|
||||
<target name="runXDesktopDemo" depends="compile">
|
||||
<java classname="jnacontrib.x11.demos.XDesktopDemo" fork="true">
|
||||
<classpath>
|
||||
<pathelement location="${classes}" />
|
||||
<path refid="classpath"/>
|
||||
</classpath>
|
||||
</java>
|
||||
</target>
|
||||
|
||||
<!-- Run XTestDemo. -->
|
||||
<target name="runXTestDemo" depends="compile">
|
||||
<java classname="jnacontrib.x11.demos.XTestDemo" fork="true">
|
||||
<classpath>
|
||||
<pathelement location="${classes}" />
|
||||
<path refid="classpath"/>
|
||||
</classpath>
|
||||
</java>
|
||||
</target>
|
||||
|
||||
<!-- Delete class and jar files. -->
|
||||
<target name="clean">
|
||||
<delete dir="${classes}"/>
|
||||
<delete file="${jar}"/>
|
||||
<delete dir="${build}"/>
|
||||
</target>
|
||||
|
||||
<!-- Compile all classes. -->
|
||||
<target name="compile">
|
||||
<mkdir dir="${classes}"/>
|
||||
<!-- Compile the project. -->
|
||||
<javac srcdir="${src}" destdir="${classes}" target="1.5" source="1.5"
|
||||
encoding="UTF-8" debug="on" includeantruntime="false">
|
||||
<classpath>
|
||||
<path refid="classpath"/>
|
||||
</classpath>
|
||||
</javac>
|
||||
</target>
|
||||
|
||||
<!-- Create jar-file. -->
|
||||
<target name="jar" depends="compile">
|
||||
|
||||
<!-- Copy all non-java files to classes. -->
|
||||
<copy todir="${classes}">
|
||||
<fileset dir="${src}">
|
||||
<exclude name="**/*.java"/>
|
||||
</fileset>
|
||||
</copy>
|
||||
|
||||
<jar jarfile="${jar}" basedir="${classes}">
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="jnacontrib.x11.demos.XDesktopDemo"/>
|
||||
</manifest>
|
||||
<!-- platform -->
|
||||
<fileset dir="../platform/build/classes"/>
|
||||
<!-- jna -->
|
||||
<zipfileset src="${file.reference.jna.jar}"/>
|
||||
</jar>
|
||||
</target>
|
||||
</project>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="jnacontrib.x11" default="jar" basedir=".">
|
||||
<description>Builds, tests, and runs the project jnacontrib.x11.</description>
|
||||
<!-- Locations -->
|
||||
<property name="src" location="src"/>
|
||||
<property name="build" location="build"/>
|
||||
<property name="jna-src" location="../../src"/>
|
||||
<property name="jna-dist" location="../../dist"/>
|
||||
<property name="classes" location="${build}/classes"/>
|
||||
<property name="jar" location="${build}/demo-x11.jar"/>
|
||||
<property name="file.reference.jna.jar" location="../../build/jna.jar"/>
|
||||
|
||||
<path id="classpath">
|
||||
<fileset file="${file.reference.jna.jar}"/>
|
||||
<fileset dir="../platform/dist" includes="jna-platform.jar"/>
|
||||
</path>
|
||||
|
||||
<!-- Run XDesktopDemo. -->
|
||||
<target name="runXDesktopDemo" depends="compile">
|
||||
<java classname="jnacontrib.x11.demos.XDesktopDemo" fork="true">
|
||||
<classpath>
|
||||
<pathelement location="${classes}" />
|
||||
<path refid="classpath"/>
|
||||
</classpath>
|
||||
</java>
|
||||
</target>
|
||||
|
||||
<!-- Run XTestDemo. -->
|
||||
<target name="runXTestDemo" depends="compile">
|
||||
<java classname="jnacontrib.x11.demos.XTestDemo" fork="true">
|
||||
<classpath>
|
||||
<pathelement location="${classes}" />
|
||||
<path refid="classpath"/>
|
||||
</classpath>
|
||||
</java>
|
||||
</target>
|
||||
|
||||
<!-- Delete class and jar files. -->
|
||||
<target name="clean">
|
||||
<delete dir="${classes}"/>
|
||||
<delete file="${jar}"/>
|
||||
<delete dir="${build}"/>
|
||||
</target>
|
||||
|
||||
<!-- Compile all classes. -->
|
||||
<target name="compile">
|
||||
<mkdir dir="${classes}"/>
|
||||
<!-- Compile the project. -->
|
||||
<javac srcdir="${src}" destdir="${classes}" target="1.5" source="1.5"
|
||||
encoding="UTF-8" debug="on" includeantruntime="false">
|
||||
<classpath>
|
||||
<path refid="classpath"/>
|
||||
</classpath>
|
||||
</javac>
|
||||
</target>
|
||||
|
||||
<!-- Create jar-file. -->
|
||||
<target name="jar" depends="compile">
|
||||
|
||||
<!-- Copy all non-java files to classes. -->
|
||||
<copy todir="${classes}">
|
||||
<fileset dir="${src}">
|
||||
<exclude name="**/*.java"/>
|
||||
</fileset>
|
||||
</copy>
|
||||
|
||||
<jar jarfile="${jar}" basedir="${classes}">
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="jnacontrib.x11.demos.XDesktopDemo"/>
|
||||
</manifest>
|
||||
<!-- platform -->
|
||||
<fileset dir="../platform/build/classes"/>
|
||||
<!-- jna -->
|
||||
<zipfileset src="${file.reference.jna.jar}"/>
|
||||
</jar>
|
||||
</target>
|
||||
</project>
|
||||
|
||||
externo
BIN
Arquivo binário não exibido.
externo
BIN
Arquivo binário não exibido.
externo
BIN
Arquivo binário não exibido.
externo
BIN
Arquivo binário não exibido.
externo
BIN
Arquivo binário não exibido.
externo
BIN
Arquivo binário não exibido.
externo
BIN
Arquivo binário não exibido.
externo
BIN
Arquivo binário não exibido.
externo
BIN
Arquivo binário não exibido.
BIN
Arquivo binário não exibido.
externo
BIN
Arquivo binário não exibido.
BIN
Arquivo binário não exibido.
BIN
Arquivo binário não exibido.
BIN
Arquivo binário não exibido.
externo
BIN
Arquivo binário não exibido.
BIN
Arquivo binário não exibido.
BIN
Arquivo binário não exibido.
externo
BIN
Arquivo binário não exibido.
externo
BIN
Arquivo binário não exibido.
externo
BIN
Arquivo binário não exibido.
externo
BIN
Arquivo binário não exibido.
externo
BIN
Arquivo binário não exibido.
externo
BIN
Arquivo binário não exibido.
externo
BIN
Arquivo binário não exibido.
externo
BIN
Arquivo binário não exibido.
externo
BIN
Arquivo binário não exibido.
externo
BIN
Arquivo binário não exibido.
externo
BIN
Arquivo binário não exibido.
externo
BIN
Arquivo binário não exibido.
externo
BIN
Arquivo binário não exibido.
Arquivo binário não exibido.
@@ -1,5 +1,5 @@
|
||||
qRNQnmsMoNMDGXUenVfHVPuFPrNBGUUdBvfgtIdgVQWSbAa
|
||||
mj2KW7Oo9ud83ZbEKfK2xx922L04T>gYjDdLjGld4Wa6MPW
|
||||
NrqPtxROppqOmmqROMPSTnMmRqNOMnMnoPVSXswPsVXQwXV
|
||||
SPVVUtUNQmnmqmUUnopmqsvommmmmUUnopmqsvommmmmUUg
|
||||
kXkabskgXsXkkbqUUnmm
|
||||
onoMnApeShTpQtDJbcUgJTIFONPQeUndIgfQWWNNddIwBl
|
||||
mi2Kp5RjfhIJdGCSo<bOTNof2KNxm9KCi5lxEyKI9BJW3p
|
||||
qOPQUXpopOopMMPqnPnXXQPNOPNRnqQNQqStwVxuQSTtVW
|
||||
UrwSUSSSTVwxWSXNmrrpnmqmUUnpsvpntsmmmmmUUnpsvp
|
||||
ntsmmmmmUUFmbkWJlroZbW4bsbilmjbkqUUnmmmm
|
||||
|
||||
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 executável
BIN
Arquivo binário não exibido.
Arquivo executável
BIN
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 executável
BIN
Arquivo binário não exibido.
Arquivo executável
BIN
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.
Arquivo binário não exibido.
Arquivo binário não exibido.
+37
-13
@@ -48,7 +48,7 @@ OS=$(shell uname | sed -e 's/CYGWIN.*/win32/g' \
|
||||
-e 's/Linux.*/linux/g')
|
||||
|
||||
JNA_JNI_VERSION=4.0.0 # auto-generated by ant
|
||||
CHECKSUM=059b6e5f0534df9b7f28dd7a87485721 # auto-generated by ant
|
||||
CHECKSUM=1a6047467b59e8748f975e03016ce3d9 # auto-generated by ant
|
||||
|
||||
JAVA_INCLUDES=-I"$(JAVA_HOME)/include" \
|
||||
-I"$(JAVA_HOME)/include/$(OS)"
|
||||
@@ -162,8 +162,22 @@ endif
|
||||
|
||||
ifeq ($(OS),win32)
|
||||
ARCH=$(shell uname -m | sed 's/i.86/i386/g')
|
||||
CDEFINES=-DHAVE_PROTECTION -DPSAPI_VERSION=1 -DFFI_BUILDING
|
||||
ifeq ($(ARCH),amd64)
|
||||
# To build entirely with mingw64, comment out this line (default is MSVC)
|
||||
USE_MSVC=true
|
||||
else
|
||||
# To build 32-bit under MSVC, un-comment this line (default is gcc)
|
||||
#USE_MSVC=true
|
||||
endif
|
||||
|
||||
CDEFINES=-DHAVE_PROTECTION -DPSAPI_VERSION=1 -DFFI_BUILDING -DUNICODE -D_UNICODE
|
||||
ifndef USE_MSVC
|
||||
LIBS=-lpsapi
|
||||
else
|
||||
ARSFX=.lib
|
||||
COPT=
|
||||
LIBS=psapi.lib
|
||||
endif
|
||||
WINDRES=windres
|
||||
EXTRAOBJS=$(RSRC)
|
||||
STRIP=@echo
|
||||
@@ -172,6 +186,14 @@ LIBSFX=.dll
|
||||
TESTLIB_TRUNC=$(BUILD)/testlib-truncated.dll
|
||||
|
||||
ifneq ($(ARCH),amd64)
|
||||
ifdef USE_MSVC
|
||||
CC=$(FFI_SRC)/../cc.sh -m32
|
||||
CPP=$(FFI_SRC)/../cc.sh -m32 -E
|
||||
LD=$(FFI_SRC)/../ld.sh -m32
|
||||
FFI_CONFIG+= && rm -f include/ffitarget.h && cp $(FFI_SRC)/include/*.h $(FFI_SRC)/src/x86/ffitarget.h include
|
||||
FFI_ENV+=LD="$(LD)" CPP="$(CPP)"
|
||||
endif
|
||||
|
||||
ifeq ($(CC),gcc)
|
||||
# -mno-cygwin is only available on GCC 3; GCC 4 requires an explicit mingw
|
||||
# installation
|
||||
@@ -187,18 +209,19 @@ endif
|
||||
|
||||
else
|
||||
|
||||
# Set CC to $(MINGW) to enable mingw64 cross compiler; ensure $(MINGW) is in
|
||||
# Undefine USE_MSVC to enable mingw64 cross compiler; ensure $(MINGW) is in
|
||||
# PATH. Should build properly as of 111121, but lacks SEH, so MSVC build is
|
||||
# preferred
|
||||
MINGW_PREFIX?=x86_64-w64-mingw32-
|
||||
MINGW=$(MINGW_PREFIX)gcc
|
||||
# Still need windres from mingw distribution
|
||||
# Still need windres from mingw distribution, even if building with MSVC
|
||||
WINDRES=$(MINGW_PREFIX)windres
|
||||
# To build entirely with mingw64, uncomment this line
|
||||
#CC=$(MINGW)
|
||||
ifndef USE_MSVC
|
||||
CC=$(MINGW)
|
||||
endif
|
||||
|
||||
ifeq ($(CC),$(MINGW))
|
||||
# No SEH under mingw64
|
||||
# No SEH under mingw64, thus no HAVE_PROTECTION
|
||||
CDEFINES=-DPSAPI_VERSION=1
|
||||
LD = $(CC)
|
||||
LDFLAGS=-o $@ -shared
|
||||
@@ -209,9 +232,6 @@ else
|
||||
CC=$(FFI_SRC)/../cc.sh -m64
|
||||
CPP=$(FFI_SRC)/../cc.sh -m64 -E
|
||||
LD=$(FFI_SRC)/../ld.sh -m64
|
||||
COPT=
|
||||
LIBS=psapi.lib
|
||||
ARSFX=.lib
|
||||
FFI_CONFIG+=--host=x86_64-w64-mingw32 && rm -f include/ffitarget.h && cp $(FFI_SRC)/include/*.h $(FFI_SRC)/src/x86/ffitarget.h include
|
||||
FFI_ENV+=LD="$(LD)" CPP="$(CPP)"
|
||||
EXTRAOBJS+=$(DLLCB)
|
||||
@@ -231,7 +251,7 @@ ARCH=$(shell uname -m | sed 's/i.86/i386/g')
|
||||
PCFLAGS+=-fPIC
|
||||
CINCLUDES+=-I/usr/X11R6/include
|
||||
LDFLAGS=-o $@ -shared
|
||||
CDEFINES+=-DHAVE_PROTECTION -DFFI_MMAP_EXEC_WRIT
|
||||
CDEFINES+=-DHAVE_PROTECTION -DFFI_MMAP_EXEC_WRIT -DUSE_DEAFULT_LIBNAME_ENCODING
|
||||
endif
|
||||
|
||||
ifeq ($(OS),solaris)
|
||||
@@ -239,7 +259,7 @@ ifeq ($(ARCH),)
|
||||
ARCH=$(shell uname -p)
|
||||
endif
|
||||
PCFLAGS+=-fPIC
|
||||
CDEFINES+=-DHAVE_PROTECTION -DFFI_MMAP_EXEC_WRIT
|
||||
CDEFINES+=-DHAVE_PROTECTION -DFFI_MMAP_EXEC_WRIT -DUSE_DEFAULT_LIBNAME_ENCODING
|
||||
ifeq ($(ARCH), sparcv9)
|
||||
# alter CC instead of PCFLAGS, since we need to pass it down to libffi
|
||||
# configure and some of the other settings in PCFLAGS might make the build
|
||||
@@ -253,7 +273,7 @@ endif
|
||||
ifeq ($(OS),aix)
|
||||
LIBSFX=.a
|
||||
PCFLAGS+=-fPIC
|
||||
CDEFINES+=-DHAVE_PROTECTION -DNO_JAWT -Wall -D_AIX -DPOWERPC_AIX
|
||||
CDEFINES+=-DHAVE_PROTECTION -DNO_JAWT -Wall -D_AIX -DPOWERPC_AIX -D_THREAD_SAFE_ERRNO
|
||||
COPT+=-D_AIX -DPOWERPC_AIX -mxl-compat
|
||||
LDFLAGS+=-Wl,-lc128,-lc,-lm,-lpthread
|
||||
FFI_ENV+=AR_FLAGS="-X32_64 cru"
|
||||
@@ -288,6 +308,10 @@ ifeq ($(ARCH),ppc)
|
||||
LD += -m32
|
||||
HOST_CONFIG=--host=ppc-linux
|
||||
endif
|
||||
ifeq ($(ARCH),i386)
|
||||
CC += -m32
|
||||
LD += -m32
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
+118
-86
@@ -23,12 +23,17 @@
|
||||
# include <windows.h>
|
||||
# define TLS_SET(KEY,VALUE) TlsSetValue(KEY,VALUE)
|
||||
# define TLS_GET(KEY) TlsGetValue(KEY)
|
||||
# define TLS_KEY_T DWORD
|
||||
#else
|
||||
# include <sys/types.h>
|
||||
# include <sys/param.h>
|
||||
# include <pthread.h>
|
||||
# define PTHREADS
|
||||
# define TLS_SET(KEY,VALUE) (pthread_setspecific(KEY,VALUE)==0)
|
||||
# define TLS_GET(KEY) pthread_getspecific(KEY)
|
||||
# define TLS_KEY_T pthread_key_t
|
||||
#endif
|
||||
|
||||
#include "dispatch.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -49,10 +54,9 @@ extern "C" {
|
||||
#endif
|
||||
#else /* _WIN64 */
|
||||
#ifdef _MSC_VER
|
||||
// FIXME is "PROC NEAR" correct?
|
||||
#define ASMFN(X) extern void asmfn ## X(); \
|
||||
__asm asmfn ## X PROC NEAR \
|
||||
__asm jmp fn[X]
|
||||
#define ASMFN(X) void __declspec(naked) asmfn ## X () { \
|
||||
__asm jmp DWORD PTR fn[4*X] \
|
||||
}
|
||||
#else
|
||||
#define ASMFN(X) extern void asmfn ## X (); asm(".globl _asmfn" #X "\n\
|
||||
_asmfn" #X ":\n\
|
||||
@@ -74,9 +78,21 @@ static void * const dll_fptrs[] = {
|
||||
|
||||
#endif /* _WIN32 && !_WIN32_WCE */
|
||||
|
||||
typedef struct _tls {
|
||||
JavaVM* jvm;
|
||||
jint last_error;
|
||||
// Contents set to JNI_TRUE if thread has terminated and detached properly
|
||||
int* termination_flag;
|
||||
jboolean jvm_thread;
|
||||
jboolean detach;
|
||||
char name[256];
|
||||
} thread_storage;
|
||||
|
||||
static void callback_dispatch(ffi_cif*, void*, void**, void*);
|
||||
static jclass classObject;
|
||||
|
||||
extern void println(JNIEnv*, const char*);
|
||||
|
||||
callback*
|
||||
create_callback(JNIEnv* env, jobject obj, jobject method,
|
||||
jobjectArray param_types, jclass return_type,
|
||||
@@ -92,7 +108,7 @@ create_callback(JNIEnv* env, jobject obj, jobject method,
|
||||
jsize argc;
|
||||
JavaVM* vm;
|
||||
int rtype;
|
||||
char msg[64];
|
||||
char msg[MSG_SIZE];
|
||||
int i;
|
||||
int cvt = 0;
|
||||
const char* throw_type = NULL;
|
||||
@@ -165,8 +181,9 @@ create_callback(JNIEnv* env, jobject obj, jobject method,
|
||||
}
|
||||
}
|
||||
|
||||
// Java callback method is called using varargs, so promote floats to
|
||||
// double where appropriate for the platform
|
||||
if (cb->arg_types[i]->type == FFI_TYPE_FLOAT) {
|
||||
// Java method is varargs, so promote floats to double
|
||||
cb->java_arg_types[i+3] = &ffi_type_double;
|
||||
cb->conversion_flags[i] = CVT_FLOAT;
|
||||
cvt = 1;
|
||||
@@ -236,7 +253,7 @@ create_callback(JNIEnv* env, jobject obj, jobject method,
|
||||
case 'D': cb->fptr_offset = OFFSETOF(env, CallDoubleMethod); break;
|
||||
default: cb->fptr_offset = OFFSETOF(env, CallObjectMethod); break;
|
||||
}
|
||||
status = ffi_prep_cif(&cb->java_cif, java_abi, argc+3, java_ffi_rtype, cb->java_arg_types);
|
||||
status = ffi_prep_cif_var(&cb->java_cif, java_abi, 2, argc+3, java_ffi_rtype, cb->java_arg_types);
|
||||
if (!ffi_error(env, "callback setup (2)", status)) {
|
||||
ffi_prep_closure_loc(cb->closure, &cb->cif, callback_dispatch, cb,
|
||||
cb->x_closure);
|
||||
@@ -478,43 +495,72 @@ callback_invoke(JNIEnv* env, callback *cb, ffi_cif* cif, void *resp, void **cbar
|
||||
}
|
||||
}
|
||||
|
||||
// Handle automatic thread cleanup
|
||||
static void detach_thread(void* data) {
|
||||
if (data != NULL) {
|
||||
JavaVM* jvm = (JavaVM *)data;
|
||||
(*jvm)->DetachCurrentThread(jvm);
|
||||
static TLS_KEY_T tls_thread_data_key;
|
||||
static thread_storage* get_thread_storage(JNIEnv* env) {
|
||||
thread_storage* tls = (thread_storage *)TLS_GET(tls_thread_data_key);
|
||||
if (tls == NULL) {
|
||||
tls = (thread_storage*)malloc(sizeof(thread_storage));
|
||||
if (!tls) {
|
||||
throwByName(env, EOutOfMemory, "JNA: Can't allocate thread storage");
|
||||
}
|
||||
else {
|
||||
snprintf(tls->name, sizeof(tls->name), "<uninitialized thread name>");
|
||||
tls->jvm_thread = JNI_TRUE;
|
||||
tls->last_error = 0;
|
||||
tls->termination_flag = NULL;
|
||||
if ((*env)->GetJavaVM(env, &tls->jvm) != JNI_OK) {
|
||||
free(tls);
|
||||
throwByName(env, EIllegalState, "JNA: Could not get JavaVM");
|
||||
tls = NULL;
|
||||
}
|
||||
else if (!TLS_SET(tls_thread_data_key, tls)) {
|
||||
free(tls);
|
||||
throwByName(env, EOutOfMemory, "JNA: Internal TLS error");
|
||||
tls = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return tls;
|
||||
}
|
||||
|
||||
static void dispose_thread_data(void* data) {
|
||||
thread_storage* tls = (thread_storage*)data;
|
||||
JavaVM* jvm = tls->jvm;
|
||||
JNIEnv* env;
|
||||
int is_attached = (*jvm)->GetEnv(jvm, (void*)&env, JNI_VERSION_1_4) == JNI_OK;
|
||||
jboolean detached = JNI_TRUE;
|
||||
if (is_attached) {
|
||||
if ((*jvm)->DetachCurrentThread(jvm) != 0) {
|
||||
fprintf(stderr, "JNA: could not detach native thread (automatic)\n");
|
||||
detached = JNI_FALSE;
|
||||
}
|
||||
}
|
||||
if (tls->termination_flag && detached) {
|
||||
*(tls->termination_flag) = JNI_TRUE;
|
||||
}
|
||||
free(data);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
static DWORD tls_thread_cleanup_key;
|
||||
static DWORD tls_errno_key, tls_detach_key;
|
||||
BOOL WINAPI DllMain(HINSTANCE hDLL, DWORD fdwReason, LPVOID lpvReserved) {
|
||||
switch (fdwReason) {
|
||||
case DLL_PROCESS_ATTACH:
|
||||
tls_thread_cleanup_key = TlsAlloc();
|
||||
if (tls_thread_cleanup_key == TLS_OUT_OF_INDEXES) {
|
||||
return FALSE;
|
||||
}
|
||||
tls_detach_key = TlsAlloc();
|
||||
if (tls_detach_key == TLS_OUT_OF_INDEXES) {
|
||||
return FALSE;
|
||||
}
|
||||
tls_errno_key = TlsAlloc();
|
||||
if (tls_errno_key == TLS_OUT_OF_INDEXES) {
|
||||
tls_thread_data_key = TlsAlloc();
|
||||
if (tls_thread_data_key == TLS_OUT_OF_INDEXES) {
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
TlsFree(tls_thread_cleanup_key);
|
||||
TlsFree(tls_detach_key);
|
||||
TlsFree(tls_errno_key);
|
||||
TlsFree(tls_thread_data_key);
|
||||
break;
|
||||
case DLL_THREAD_ATTACH:
|
||||
break;
|
||||
case DLL_THREAD_DETACH: {
|
||||
detach_thread(TlsGetValue(tls_thread_cleanup_key));
|
||||
thread_storage* tls = (thread_storage*)TlsGetValue(tls_thread_data_key);
|
||||
if (tls) {
|
||||
dispose_thread_data(tls);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -523,71 +569,54 @@ BOOL WINAPI DllMain(HINSTANCE hDLL, DWORD fdwReason, LPVOID lpvReserved) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#else
|
||||
#endif
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
static pthread_key_t tls_thread_cleanup_key, tls_detach_key;
|
||||
static void make_thread_cleanup_key() {
|
||||
pthread_key_create(&tls_thread_cleanup_key, detach_thread);
|
||||
#ifdef PTHREADS
|
||||
static void make_thread_data_key() {
|
||||
pthread_key_create(&tls_thread_data_key, dispose_thread_data);
|
||||
}
|
||||
static pthread_key_t tls_errno_key;
|
||||
static void make_thread_keys() {
|
||||
pthread_key_create(&tls_errno_key, NULL);
|
||||
pthread_key_create(&tls_detach_key, NULL);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/** Store the requested detach state for the current thread. */
|
||||
void
|
||||
JNA_detach(jboolean d) {
|
||||
if (!TLS_SET(tls_detach_key, L2A((jlong)(d?THREAD_DETACH:THREAD_LEAVE_ATTACHED)))) {
|
||||
fprintf(stderr, "JNA: unable to set thread-local detach value\n");
|
||||
JNA_detach(JNIEnv* env, jboolean detach, void* termination_flag) {
|
||||
thread_storage* tls = get_thread_storage(env);
|
||||
if (tls) {
|
||||
tls->detach = detach;
|
||||
tls->termination_flag = (int *)termination_flag;
|
||||
if (detach && tls->jvm_thread) {
|
||||
throwByName(env, EIllegalState, "Can not detach from a JVM thread");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Store the value of errno/GetLastError in TLS */
|
||||
void
|
||||
JNA_set_last_error(int err) {
|
||||
if (!TLS_SET(tls_errno_key, L2A((jlong)err))) {
|
||||
fprintf(stderr, "JNA: unable to set thread-local errno value\n");
|
||||
JNA_set_last_error(JNIEnv* env, int err) {
|
||||
thread_storage* tls = get_thread_storage(env);
|
||||
if (tls) {
|
||||
tls->last_error = err;
|
||||
}
|
||||
}
|
||||
|
||||
/** Store the value of errno/GetLastError in TLS */
|
||||
int
|
||||
JNA_get_last_error() {
|
||||
return (int)A2L(TLS_GET(tls_errno_key));
|
||||
}
|
||||
|
||||
/** Set up to detach the thread when it exits, or clear any handlers if the
|
||||
argument is NULL.
|
||||
*/
|
||||
static void
|
||||
jvm_detach_on_exit(JavaVM* jvm) {
|
||||
#ifdef _WIN32
|
||||
if (!TlsSetValue(tls_thread_cleanup_key, (void *)jvm)) {
|
||||
fprintf(stderr, "JNA: unable to set thread-local JVM value\n");
|
||||
JNA_get_last_error(JNIEnv* env) {
|
||||
thread_storage* tls = get_thread_storage(env);
|
||||
if (tls) {
|
||||
return tls->last_error;
|
||||
}
|
||||
#else
|
||||
static pthread_once_t key_once = PTHREAD_ONCE_INIT;
|
||||
pthread_once(&key_once, make_thread_cleanup_key);
|
||||
if (!jvm || pthread_getspecific(tls_thread_cleanup_key) == NULL) {
|
||||
if (pthread_setspecific(tls_thread_cleanup_key, jvm)) {
|
||||
fprintf(stderr, "JNA: unable to set thread-local JVM value\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
callback_dispatch(ffi_cif* cif, void* resp, void** cbargs, void* user_data) {
|
||||
callback* cb = ((callback *)user_data);
|
||||
JavaVM* jvm = cb->vm;
|
||||
JNIEnv* env;
|
||||
JNIEnv* env = NULL;
|
||||
int was_attached = (*jvm)->GetEnv(jvm, (void *)&env, JNI_VERSION_1_4) == JNI_OK;
|
||||
jboolean detach = was_attached ? JNI_FALSE : JNI_TRUE;
|
||||
thread_storage* tls = was_attached ? get_thread_storage(env) : NULL;
|
||||
|
||||
if (!was_attached) {
|
||||
int attach_status = 0;
|
||||
@@ -613,6 +642,12 @@ callback_dispatch(ffi_cif* cif, void* resp, void** cbargs, void* user_data) {
|
||||
else {
|
||||
attach_status = (*jvm)->AttachCurrentThread(jvm, (void *)&env, &args);
|
||||
}
|
||||
tls = get_thread_storage(env);
|
||||
if (tls) {
|
||||
snprintf(tls->name, sizeof(tls->name), "%s", args.name ? args.name : "<unconfigured native thread>");
|
||||
tls->detach = detach;
|
||||
tls->jvm_thread = JNI_FALSE;
|
||||
}
|
||||
// Dispose of allocated memory
|
||||
free(args.name);
|
||||
if (attach_status != JNI_OK) {
|
||||
@@ -623,37 +658,36 @@ callback_dispatch(ffi_cif* cif, void* resp, void** cbargs, void* user_data) {
|
||||
(*env)->DeleteWeakGlobalRef(env, args.group);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!tls) {
|
||||
fprintf(stderr, "JNA: couldn't obtain thread-local storage\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Give the callback glue its own local frame to ensure all local references
|
||||
// are properly disposed
|
||||
if ((*env)->PushLocalFrame(env, 16) < 0) {
|
||||
fprintf(stderr, "JNA: Out of memory: Can't allocate local frame\n");
|
||||
}
|
||||
else {
|
||||
TLS_SET(tls_detach_key, L2A((jlong)THREAD_NOCHANGE));
|
||||
callback_invoke(env, cb, cif, resp, cbargs);
|
||||
switch((int)A2L(TLS_GET(tls_detach_key))) {
|
||||
case THREAD_LEAVE_ATTACHED: detach = JNI_FALSE; break;
|
||||
case THREAD_DETACH: detach = JNI_TRUE; break;
|
||||
default: break; /* use default detach behavior */
|
||||
}
|
||||
// Make note of whether the callback wants to avoid detach
|
||||
detach = tls->detach && !tls->jvm_thread;
|
||||
(*env)->PopLocalFrame(env, NULL);
|
||||
}
|
||||
|
||||
if (detach) {
|
||||
(*jvm)->DetachCurrentThread(jvm);
|
||||
jvm_detach_on_exit(NULL);
|
||||
}
|
||||
else if (!was_attached) {
|
||||
jvm_detach_on_exit(jvm);
|
||||
if ((*jvm)->DetachCurrentThread(jvm) != 0) {
|
||||
fprintf(stderr, "JNA: could not detach thread\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char*
|
||||
JNA_callback_init(JNIEnv* env) {
|
||||
#ifndef _WIN32
|
||||
#ifdef PTHREADS
|
||||
static pthread_once_t key_once = PTHREAD_ONCE_INIT;
|
||||
pthread_once(&key_once, make_thread_keys);
|
||||
pthread_once(&key_once, make_thread_data_key);
|
||||
#endif
|
||||
|
||||
if (!LOAD_CREF(env, Object, "java/lang/Object")) return "java.lang.Object";
|
||||
@@ -667,10 +701,8 @@ JNA_callback_dispose(JNIEnv* env) {
|
||||
(*env)->DeleteWeakGlobalRef(env, classObject);
|
||||
classObject = NULL;
|
||||
}
|
||||
#ifndef _WIN32
|
||||
pthread_key_delete(tls_errno_key);
|
||||
pthread_key_delete(tls_thread_cleanup_key);
|
||||
pthread_key_delete(tls_detach_key);
|
||||
#ifdef PTHREADS
|
||||
pthread_key_delete(tls_thread_data_key);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -36,7 +36,7 @@ do
|
||||
shift 1
|
||||
;;
|
||||
-m32)
|
||||
if echo $PATH | grep amd64 >& /dev/null; then
|
||||
if type cl | grep amd64 >& /dev/null; then
|
||||
echo "Wrong CL.EXE in path; use 32-bit version"
|
||||
exit 1
|
||||
fi
|
||||
@@ -48,7 +48,7 @@ do
|
||||
shift 1
|
||||
;;
|
||||
-m64)
|
||||
if ! echo $PATH | grep amd64 >& /dev/null; then
|
||||
if ! type cl | grep amd64 >& /dev/null; then
|
||||
echo "Wrong CL.EXE in path; use 64-bit version"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
+245
-172
@@ -17,14 +17,11 @@
|
||||
*/
|
||||
|
||||
#if defined(_WIN32)
|
||||
#ifndef UNICODE
|
||||
#define UNICODE
|
||||
#endif
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <psapi.h>
|
||||
#define STRTYPE wchar_t*
|
||||
#define NAME2CSTR(ENV,JSTR) newWideCString(ENV,JSTR)
|
||||
#define NAME2CSTR(ENV,JSTR) w32_short_name(ENV,JSTR)
|
||||
#ifdef _WIN32_WCE
|
||||
#include <tlhelp32.h>
|
||||
#define DEFAULT_LOAD_OPTS 0 /* altered search path unsupported on CE */
|
||||
@@ -49,7 +46,11 @@
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
#define STRTYPE char*
|
||||
#ifdef USE_DEFAULT_LIBNAME_ENCODING
|
||||
#define NAME2CSTR(ENV,JSTR) newCString(ENV,JSTR)
|
||||
#else
|
||||
#define NAME2CSTR(ENV,JSTR) newCStringUTF8(ENV,JSTR)
|
||||
#endif
|
||||
#define DEFAULT_LOAD_OPTS (RTLD_LAZY|RTLD_GLOBAL)
|
||||
#define LOAD_LIBRARY(NAME,OPTS) dlopen(NAME, OPTS)
|
||||
#define LOAD_ERROR(BUF,LEN) (snprintf(BUF, LEN, "%s", dlerror()), BUF)
|
||||
@@ -80,15 +81,6 @@
|
||||
#include <jawt_md.h>
|
||||
#endif
|
||||
|
||||
/* Native memory fault protection */
|
||||
#ifdef HAVE_PROTECTION
|
||||
#define PROTECT is_protected()
|
||||
#endif
|
||||
#include "protect.h"
|
||||
#define ON_ERROR() throwByName(env, EError, "Invalid memory access")
|
||||
#define PSTART() PROTECTED_START()
|
||||
#define PEND() PROTECTED_END(ON_ERROR())
|
||||
|
||||
#ifdef HAVE_PROTECTION
|
||||
// When we have SEH, default to protection on
|
||||
#if defined(_WIN32) && !(defined(_WIN64) && defined(__GNUC__))
|
||||
@@ -106,76 +98,11 @@ static int _protect;
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
static char*
|
||||
w32_format_error(int error, char* buf, int len) {
|
||||
wchar_t* wbuf = NULL;
|
||||
int wlen =
|
||||
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|FORMAT_MESSAGE_ALLOCATE_BUFFER,
|
||||
NULL, error, 0, (LPWSTR)&wbuf, 0, NULL);
|
||||
if (wlen > 0) {
|
||||
WideCharToMultiByte(CP_UTF8, 0, wbuf, wlen+1, buf, len, NULL, NULL);
|
||||
}
|
||||
else {
|
||||
*buf = 0;
|
||||
}
|
||||
if (wbuf) {
|
||||
LocalFree(wbuf);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
static HANDLE
|
||||
w32_find_entry(JNIEnv* env, HANDLE handle, const char* funname) {
|
||||
void* func = NULL;
|
||||
if (handle != GetModuleHandle(NULL)) {
|
||||
func = GetProcAddress(handle, funname);
|
||||
}
|
||||
else {
|
||||
#if defined(_WIN32_WCE)
|
||||
/* CE has no EnumProcessModules, have to use an alternate API */
|
||||
HANDLE snapshot;
|
||||
if ((snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 0)) != INVALID_HANDLE_VALUE) {
|
||||
MODULEENTRY32 moduleInfo;
|
||||
moduleInfo.dwSize = sizeof(moduleInfo);
|
||||
if (Module32First(snapshot, &moduleInfo)) {
|
||||
do {
|
||||
if ((func = (void *) GetProcAddress(moduleInfo.hModule, funname))) {
|
||||
break;
|
||||
}
|
||||
} while (Module32Next(snapshot, &moduleInfo));
|
||||
}
|
||||
CloseToolhelp32Snapshot(snapshot);
|
||||
}
|
||||
#else
|
||||
HANDLE cur_proc = GetCurrentProcess ();
|
||||
HMODULE *modules;
|
||||
DWORD needed, i;
|
||||
if (!EnumProcessModules (cur_proc, NULL, 0, &needed)) {
|
||||
fail:
|
||||
throwByName(env, EError, "Unexpected error enumerating modules");
|
||||
return 0;
|
||||
}
|
||||
modules = (HMODULE*) alloca (needed);
|
||||
if (!EnumProcessModules (cur_proc, modules, needed, &needed)) {
|
||||
goto fail;
|
||||
}
|
||||
for (i = 0; i < needed / sizeof (HMODULE); i++) {
|
||||
if ((func = (void *) GetProcAddress (modules[i], funname))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return func;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#define MEMCPY(D,S,L) do { \
|
||||
PSTART(); memcpy(D,S,L); PEND(); \
|
||||
#define MEMCPY(ENV,D,S,L) do { \
|
||||
PSTART(); memcpy(D,S,L); PEND(ENV); \
|
||||
} while(0)
|
||||
#define MEMSET(D,C,L) do { \
|
||||
PSTART(); memset(D,C,L); PEND(); \
|
||||
#define MEMSET(ENV,D,C,L) do { \
|
||||
PSTART(); memset(D,C,L); PEND(ENV); \
|
||||
} while(0)
|
||||
|
||||
#define MASK_CC com_sun_jna_Function_MASK_CC
|
||||
@@ -286,6 +213,8 @@ static jfieldID FID_Structure_typeInfo;
|
||||
static jfieldID FID_IntegerType_value;
|
||||
static jfieldID FID_PointerType_pointer;
|
||||
|
||||
jstring fileEncoding;
|
||||
|
||||
/* Forward declarations */
|
||||
static char* newCString(JNIEnv *env, jstring jstr);
|
||||
static char* newCStringEncoding(JNIEnv *env, jstring jstr, const char* encoding);
|
||||
@@ -300,15 +229,139 @@ static ffi_type* getStructureType(JNIEnv *, jobject);
|
||||
|
||||
typedef void (JNICALL* release_t)(JNIEnv*,jarray,void*,jint);
|
||||
|
||||
#ifdef _WIN32
|
||||
static char*
|
||||
w32_format_error(int err, char* buf, int len) {
|
||||
wchar_t* wbuf = NULL;
|
||||
int wlen =
|
||||
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM
|
||||
|FORMAT_MESSAGE_IGNORE_INSERTS
|
||||
|FORMAT_MESSAGE_ALLOCATE_BUFFER,
|
||||
NULL, err, 0, (LPWSTR)&wbuf, 0, NULL);
|
||||
if (wlen > 0) {
|
||||
int result = WideCharToMultiByte(CP_UTF8, 0, wbuf, -1, buf, len, NULL, NULL);
|
||||
if (result == 0) {
|
||||
fprintf(stderr, "JNA: error converting error message: %d\n", (int)GET_LAST_ERROR());
|
||||
*buf = 0;
|
||||
}
|
||||
else {
|
||||
buf[len-1] = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Error retrieving message
|
||||
*buf = 0;
|
||||
}
|
||||
if (wbuf) {
|
||||
LocalFree(wbuf);
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
static wchar_t*
|
||||
w32_short_name(JNIEnv* env, jstring str) {
|
||||
wchar_t* wstr = newWideCString(env, str);
|
||||
if (wstr && *wstr) {
|
||||
DWORD required;
|
||||
size_t size = wcslen(wstr) + 5;
|
||||
wchar_t* prefixed = (wchar_t*)alloca(sizeof(wchar_t) * size);
|
||||
|
||||
#ifdef _MSC_VER
|
||||
swprintf(prefixed, size, L"\\\\?\\%ls", wstr);
|
||||
#else
|
||||
swprintf(prefixed, L"\\\\?\\%ls", wstr);
|
||||
#endif
|
||||
if ((required = GetShortPathNameW(prefixed, NULL, 0)) != 0) {
|
||||
wchar_t* wshort = (wchar_t*)malloc(sizeof(wchar_t) * required);
|
||||
if (GetShortPathNameW(prefixed, wshort, required)) {
|
||||
free((void *)wstr);
|
||||
wstr = wshort;
|
||||
}
|
||||
else {
|
||||
char buf[MSG_SIZE];
|
||||
throwByName(env, EError, LOAD_ERROR(buf, sizeof(buf)));
|
||||
free((void *)wstr);
|
||||
free((void *)wshort);
|
||||
wstr = NULL;
|
||||
}
|
||||
}
|
||||
else if (GET_LAST_ERROR() != ERROR_FILE_NOT_FOUND) {
|
||||
char buf[MSG_SIZE];
|
||||
throwByName(env, EError, LOAD_ERROR(buf, sizeof(buf)));
|
||||
free((void *)wstr);
|
||||
wstr = NULL;
|
||||
}
|
||||
}
|
||||
return wstr;
|
||||
}
|
||||
|
||||
static HANDLE
|
||||
w32_find_entry(JNIEnv* env, HANDLE handle, const char* funname) {
|
||||
void* func = NULL;
|
||||
if (handle != GetModuleHandle(NULL)) {
|
||||
func = GetProcAddress(handle, funname);
|
||||
}
|
||||
else {
|
||||
#if defined(_WIN32_WCE)
|
||||
/* CE has no EnumProcessModules, have to use an alternate API */
|
||||
HANDLE snapshot;
|
||||
if ((snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 0)) != INVALID_HANDLE_VALUE) {
|
||||
MODULEENTRY32 moduleInfo;
|
||||
moduleInfo.dwSize = sizeof(moduleInfo);
|
||||
if (Module32First(snapshot, &moduleInfo)) {
|
||||
do {
|
||||
if ((func = (void *) GetProcAddress(moduleInfo.hModule, funname))) {
|
||||
break;
|
||||
}
|
||||
} while (Module32Next(snapshot, &moduleInfo));
|
||||
}
|
||||
CloseToolhelp32Snapshot(snapshot);
|
||||
}
|
||||
#else
|
||||
HANDLE cur_proc = GetCurrentProcess ();
|
||||
HMODULE *modules;
|
||||
DWORD needed, i;
|
||||
if (!EnumProcessModules (cur_proc, NULL, 0, &needed)) {
|
||||
fail:
|
||||
throwByName(env, EError, "Unexpected error enumerating modules");
|
||||
return 0;
|
||||
}
|
||||
modules = (HMODULE*) alloca (needed);
|
||||
if (!EnumProcessModules (cur_proc, modules, needed, &needed)) {
|
||||
goto fail;
|
||||
}
|
||||
for (i = 0; i < needed / sizeof (HMODULE); i++) {
|
||||
if ((func = (void *) GetProcAddress (modules[i], funname))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return func;
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#if 0
|
||||
/** Invokes System.err.println (for debugging only). */
|
||||
static void
|
||||
void
|
||||
println(JNIEnv* env, const char* msg) {
|
||||
jclass cls = (*env)->FindClass(env, "java/lang/System");
|
||||
if (!cls) {
|
||||
fprintf(stderr, "JNA: failed to find java.lang.System\n");
|
||||
return;
|
||||
}
|
||||
jfieldID fid = (*env)->GetStaticFieldID(env, cls, "err",
|
||||
"Ljava/io/PrintStream;");
|
||||
"Ljava/io/PrintStream;");
|
||||
jobject err = (*env)->GetStaticObjectField(env, cls, fid);
|
||||
if (!err) {
|
||||
fprintf(stderr, "JNA: failed to find System.err\n");
|
||||
return;
|
||||
}
|
||||
jclass pscls = (*env)->FindClass(env, "java/io/PrintStream");
|
||||
if (!pscls) {
|
||||
fprintf(stderr, "JNA: failed to find java.io.PrintStream\n");
|
||||
return;
|
||||
}
|
||||
jmethodID mid = (*env)->GetMethodID(env, pscls, "println",
|
||||
"(Ljava/lang/String;)V");
|
||||
jstring str = newJavaString(env, msg, CHARSET_UTF8);
|
||||
@@ -337,7 +390,7 @@ throwByName(JNIEnv *env, const char *name, const char *msg)
|
||||
/** Translate FFI errors into exceptions. */
|
||||
jboolean
|
||||
ffi_error(JNIEnv* env, const char* op, ffi_status status) {
|
||||
char msg[256];
|
||||
char msg[MSG_SIZE];
|
||||
switch(status) {
|
||||
case FFI_BAD_ABI:
|
||||
snprintf(msg, sizeof(msg), "%s: Invalid calling convention", op);
|
||||
@@ -376,7 +429,7 @@ dispatch(JNIEnv *env, void* func, jint flags, jobjectArray arr,
|
||||
void** ffi_values;
|
||||
ffi_abi abi;
|
||||
ffi_status status;
|
||||
char msg[128];
|
||||
char msg[MSG_SIZE];
|
||||
callconv_t callconv = flags & MASK_CC;
|
||||
const char* volatile throw_type = NULL;
|
||||
const char* volatile throw_msg = NULL;
|
||||
@@ -553,20 +606,20 @@ dispatch(JNIEnv *env, void* func, jint flags, jobjectArray arr,
|
||||
status = ffi_prep_cif(&cif, abi, nargs, ffi_return_type, ffi_types);
|
||||
if (!ffi_error(env, "Native call setup", status)) {
|
||||
PSTART();
|
||||
if (flags & THROW_LAST_ERROR) {
|
||||
if ((flags & THROW_LAST_ERROR) != 0) {
|
||||
SET_LAST_ERROR(0);
|
||||
}
|
||||
ffi_call(&cif, FFI_FN(func), resP, ffi_values);
|
||||
if (flags & THROW_LAST_ERROR) {
|
||||
int error = GET_LAST_ERROR();
|
||||
if (error) {
|
||||
char emsg[1024];
|
||||
snprintf(msg, sizeof(msg), "[%d] %s", error, STR_ERROR(error, emsg, sizeof(emsg)));
|
||||
{
|
||||
int err = GET_LAST_ERROR();
|
||||
JNA_set_last_error(env, err);
|
||||
if ((flags & THROW_LAST_ERROR) && err) {
|
||||
char emsg[MSG_SIZE];
|
||||
snprintf(msg, sizeof(msg), "[%d] %s", err, STR_ERROR(err, emsg, sizeof(emsg)));
|
||||
throw_type = ELastError;
|
||||
throw_msg = msg;
|
||||
}
|
||||
}
|
||||
JNA_set_last_error(GET_LAST_ERROR());
|
||||
|
||||
PROTECTED_END(do { throw_type=EError;throw_msg="Invalid memory access";} while(0));
|
||||
}
|
||||
@@ -605,6 +658,8 @@ getChars(JNIEnv* env, wchar_t* volatile dst, jcharArray chars, volatile jint off
|
||||
int i;
|
||||
(*env)->GetCharArrayRegion(env, chars, off, count, buf);
|
||||
for (i=0;i < count;i++) {
|
||||
// TODO: ensure proper encoding conversion from jchar to native
|
||||
// wchar_t
|
||||
dst[i] = (wchar_t)buf[i];
|
||||
}
|
||||
dst += count;
|
||||
@@ -614,7 +669,7 @@ getChars(JNIEnv* env, wchar_t* volatile dst, jcharArray chars, volatile jint off
|
||||
}
|
||||
}
|
||||
}
|
||||
PEND();
|
||||
PEND(env);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -644,7 +699,7 @@ setChars(JNIEnv* env, wchar_t* src, jcharArray chars, volatile jint off, volatil
|
||||
}
|
||||
}
|
||||
}
|
||||
PEND();
|
||||
PEND(env);
|
||||
}
|
||||
|
||||
/* Translates a Java string to a C string using the
|
||||
@@ -709,13 +764,16 @@ newCStringEncoding(JNIEnv *env, jstring jstr, const char* encoding)
|
||||
/* Translates a Java string to a wide C string using the String.toCharArray
|
||||
* method.
|
||||
*/
|
||||
// TODO: are any encoding changes required?
|
||||
static wchar_t *
|
||||
newWideCString(JNIEnv *env, jstring str)
|
||||
{
|
||||
jcharArray chars = 0;
|
||||
wchar_t *result = NULL;
|
||||
|
||||
if ((*env)->IsSameObject(env, str, NULL)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
chars = (*env)->CallObjectMethod(env, str, MID_String_toCharArray);
|
||||
if (!(*env)->ExceptionCheck(env)) {
|
||||
jint len = (*env)->GetArrayLength(env, chars);
|
||||
@@ -725,7 +783,6 @@ newWideCString(JNIEnv *env, jstring str)
|
||||
throwByName(env, EOutOfMemory, "Can't allocate wide C string");
|
||||
return NULL;
|
||||
}
|
||||
// TODO: ensure proper encoding conversion from jchar to native wchar_t
|
||||
getChars(env, result, chars, 0, len);
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
free((void *)result);
|
||||
@@ -812,7 +869,7 @@ newJavaString(JNIEnv *env, const char *ptr, const char* charset)
|
||||
}
|
||||
}
|
||||
}
|
||||
PEND();
|
||||
PEND(env);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1005,10 +1062,13 @@ initializeThread(callback* cb, AttachOptions* args) {
|
||||
JavaVM* jvm = cb->vm;
|
||||
JNIEnv* env;
|
||||
jobject group = NULL;
|
||||
int attached = (*jvm)->GetEnv(jvm, (void *)&env, JNI_VERSION_1_4) == JNI_OK;
|
||||
|
||||
if ((*jvm)->AttachCurrentThread(jvm, (void *)&env, NULL) != JNI_OK) {
|
||||
fprintf(stderr, "JNA: Can't attach native thread to VM for callback thread initialization\n");
|
||||
return NULL;
|
||||
if (!attached) {
|
||||
if ((*jvm)->AttachCurrentThread(jvm, (void *)&env, NULL) != JNI_OK) {
|
||||
fprintf(stderr, "JNA: Can't attach native thread to VM for callback thread initialization\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
(*env)->PushLocalFrame(env, 16);
|
||||
{
|
||||
@@ -1029,7 +1089,11 @@ initializeThread(callback* cb, AttachOptions* args) {
|
||||
}
|
||||
}
|
||||
(*env)->PopLocalFrame(env, NULL);
|
||||
(*jvm)->DetachCurrentThread(jvm);
|
||||
if (!attached) {
|
||||
if ((*jvm)->DetachCurrentThread(jvm) != 0) {
|
||||
fprintf(stderr, "JNA: could not detach thread after callback init\n");
|
||||
}
|
||||
}
|
||||
|
||||
return group;
|
||||
}
|
||||
@@ -1055,7 +1119,7 @@ toNative(JNIEnv* env, jobject obj, void* valuep, size_t size, jboolean promote)
|
||||
}
|
||||
}
|
||||
else {
|
||||
MEMSET(valuep, 0, size);
|
||||
MEMSET(env, valuep, 0, size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1068,7 +1132,7 @@ toNativeTypeMapped(JNIEnv* env, jobject obj, void* valuep, size_t size, jobject
|
||||
}
|
||||
}
|
||||
else {
|
||||
MEMSET(valuep, 0, size);
|
||||
MEMSET(env, valuep, 0, size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1224,22 +1288,15 @@ getBufferArray(JNIEnv* env, jobject buf,
|
||||
}
|
||||
#endif /* NO_NIO_BUFFERS */
|
||||
|
||||
static const void*
|
||||
get_system_property(JNIEnv* env, const char* name, jboolean wide) {
|
||||
static jstring
|
||||
get_system_property(JNIEnv* env, const char* name) {
|
||||
jclass classSystem = (*env)->FindClass(env, "java/lang/System");
|
||||
if (classSystem != NULL) {
|
||||
jmethodID mid = (*env)->GetStaticMethodID(env, classSystem, "getProperty",
|
||||
"(Ljava/lang/String;)Ljava/lang/String;");
|
||||
if (mid != NULL) {
|
||||
jstring propname = newJavaString(env, name, CHARSET_UTF8);
|
||||
jstring value = (*env)->CallStaticObjectMethod(env, classSystem,
|
||||
mid, propname);
|
||||
if (value) {
|
||||
if (wide) {
|
||||
return newWideCString(env, value);
|
||||
}
|
||||
return newCStringUTF8(env, value);
|
||||
}
|
||||
return (*env)->CallStaticObjectMethod(env, classSystem, mid, propname);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
@@ -1374,6 +1431,11 @@ JNA_init(JNIEnv* env) {
|
||||
if (!LOAD_FID(env, FID_Double_value, classDouble, "value", "D"))
|
||||
return "Double.value";
|
||||
|
||||
fileEncoding = get_system_property(env, "file.encoding");
|
||||
if (fileEncoding) {
|
||||
fileEncoding = (*env)->NewGlobalRef(env, fileEncoding);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1591,7 +1653,7 @@ method_handler(ffi_cif* cif, void* volatile resp, void** argp, void *cdata) {
|
||||
void* oldresp = resp;
|
||||
const char* volatile throw_type = NULL;
|
||||
const char* volatile throw_msg = NULL;
|
||||
char msg[64];
|
||||
char msg[MSG_SIZE];
|
||||
|
||||
if (data->flags) {
|
||||
objects = alloca(data->cif.nargs * sizeof(void*));
|
||||
@@ -1729,17 +1791,16 @@ method_handler(ffi_cif* cif, void* volatile resp, void** argp, void *cdata) {
|
||||
SET_LAST_ERROR(0);
|
||||
}
|
||||
ffi_call(&data->cif, FFI_FN(data->fptr), resp, args);
|
||||
if (data->throw_last_error) {
|
||||
int error = GET_LAST_ERROR();
|
||||
if (error) {
|
||||
char emsg[1024];
|
||||
snprintf(msg, sizeof(msg), "[%d]%s", error, STR_ERROR(error, emsg, sizeof(emsg)));
|
||||
{
|
||||
int err = GET_LAST_ERROR();
|
||||
JNA_set_last_error(env, err);
|
||||
if (data->throw_last_error && err) {
|
||||
char emsg[MSG_SIZE];
|
||||
snprintf(msg, sizeof(msg), "[%d] %s", err, STR_ERROR(err, emsg, sizeof(emsg)));
|
||||
throw_type = ELastError;
|
||||
throw_msg = msg;
|
||||
}
|
||||
}
|
||||
JNA_set_last_error(GET_LAST_ERROR());
|
||||
|
||||
PROTECTED_END(do { throw_type=EError;throw_msg="Invalid memory access"; } while(0));
|
||||
}
|
||||
|
||||
@@ -1796,8 +1857,9 @@ method_handler(ffi_cif* cif, void* volatile resp, void** argp, void *cdata) {
|
||||
case CVT_ARRAY_LONG:
|
||||
case CVT_ARRAY_FLOAT:
|
||||
case CVT_ARRAY_DOUBLE:
|
||||
if (*(void **)args[i] && release[i])
|
||||
if (*(void **)args[i] && release[i] != NULL) {
|
||||
release[i](env, objects[i], elems[i], 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1815,9 +1877,8 @@ closure_handler(ffi_cif* cif, void* resp, void** argp, void *cdata)
|
||||
JavaVM* jvm = cb->vm;
|
||||
JNIEnv* env;
|
||||
jobject obj;
|
||||
int attached;
|
||||
int attached = (*jvm)->GetEnv(jvm, (void *)&env, JNI_VERSION_1_4) == JNI_OK;
|
||||
|
||||
attached = (*jvm)->GetEnv(jvm, (void *)&env, JNI_VERSION_1_4) == JNI_OK;
|
||||
if (!attached) {
|
||||
if ((*jvm)->AttachCurrentThread(jvm, (void *)&env, NULL) != JNI_OK) {
|
||||
fprintf(stderr, "JNA: Can't attach native thread to VM for closure handler\n");
|
||||
@@ -1846,7 +1907,9 @@ closure_handler(ffi_cif* cif, void* resp, void** argp, void *cdata)
|
||||
}
|
||||
|
||||
if (!attached) {
|
||||
(*jvm)->DetachCurrentThread(jvm);
|
||||
if ((*jvm)->DetachCurrentThread(jvm) != 0) {
|
||||
fprintf(stderr, "JNA: could not detach thread after callback handling\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2015,7 +2078,7 @@ Java_com_sun_jna_Native_open(JNIEnv *env, jclass UNUSED(cls), jstring lib, jint
|
||||
|
||||
handle = (void *)LOAD_LIBRARY(libname, flags != -1 ? flags : DEFAULT_LOAD_OPTS);
|
||||
if (!handle) {
|
||||
char buf[1024];
|
||||
char buf[MSG_SIZE];
|
||||
throwByName(env, EUnsatisfiedLink, LOAD_ERROR(buf, sizeof(buf)));
|
||||
}
|
||||
if (libname != NULL) {
|
||||
@@ -2033,7 +2096,7 @@ JNIEXPORT void JNICALL
|
||||
Java_com_sun_jna_Native_close(JNIEnv *env, jclass UNUSED(cls), jlong handle)
|
||||
{
|
||||
if (FREE_LIBRARY(L2A(handle))) {
|
||||
char buf[1024];
|
||||
char buf[MSG_SIZE];
|
||||
throwByName(env, EError, LOAD_ERROR(buf, sizeof(buf)));
|
||||
}
|
||||
}
|
||||
@@ -2054,7 +2117,7 @@ Java_com_sun_jna_Native_findSymbol(JNIEnv *env, jclass UNUSED(cls),
|
||||
if (funname != NULL) {
|
||||
func = (void *)FIND_ENTRY(handle, funname);
|
||||
if (!func) {
|
||||
char buf[1024];
|
||||
char buf[MSG_SIZE];
|
||||
throwByName(env, EUnsatisfiedLink, LOAD_ERROR(buf, sizeof(buf)));
|
||||
}
|
||||
free((void *)funname);
|
||||
@@ -2072,7 +2135,7 @@ JNIEXPORT void JNICALL Java_com_sun_jna_Native_write__J_3BII
|
||||
{
|
||||
PSTART();
|
||||
(*env)->GetByteArrayRegion(env, arr, off, n, L2A(addr));
|
||||
PEND();
|
||||
PEND(env);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2096,7 +2159,7 @@ JNIEXPORT void JNICALL Java_com_sun_jna_Native_write__J_3DII
|
||||
{
|
||||
PSTART();
|
||||
(*env)->GetDoubleArrayRegion(env, arr, off, n, (jdouble*)L2A(addr));
|
||||
PEND();
|
||||
PEND(env);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2109,7 +2172,7 @@ JNIEXPORT void JNICALL Java_com_sun_jna_Native_write__J_3FII
|
||||
{
|
||||
PSTART();
|
||||
(*env)->GetFloatArrayRegion(env, arr, off, n, (jfloat*)L2A(addr));
|
||||
PEND();
|
||||
PEND(env);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2122,7 +2185,7 @@ JNIEXPORT void JNICALL Java_com_sun_jna_Native_write__J_3III
|
||||
{
|
||||
PSTART();
|
||||
(*env)->GetIntArrayRegion(env, arr, off, n, (jint*)L2A(addr));
|
||||
PEND();
|
||||
PEND(env);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2135,7 +2198,7 @@ JNIEXPORT void JNICALL Java_com_sun_jna_Native_write__J_3JII
|
||||
{
|
||||
PSTART();
|
||||
(*env)->GetLongArrayRegion(env, arr, off, n, (jlong*)L2A(addr));
|
||||
PEND();
|
||||
PEND(env);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2148,7 +2211,7 @@ JNIEXPORT void JNICALL Java_com_sun_jna_Native_write__J_3SII
|
||||
{
|
||||
PSTART();
|
||||
(*env)->GetShortArrayRegion(env, arr, off, n, (jshort*)L2A(addr));
|
||||
PEND();
|
||||
PEND(env);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2168,7 +2231,7 @@ JNIEXPORT jlong JNICALL Java_com_sun_jna_Native_indexOf__JB
|
||||
result = i;
|
||||
++i;
|
||||
}
|
||||
PEND();
|
||||
PEND(env);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -2183,7 +2246,7 @@ JNIEXPORT void JNICALL Java_com_sun_jna_Native_read__J_3BII
|
||||
{
|
||||
PSTART();
|
||||
(*env)->SetByteArrayRegion(env, arr, off, n, L2A(addr));
|
||||
PEND();
|
||||
PEND(env);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2207,7 +2270,7 @@ JNIEXPORT void JNICALL Java_com_sun_jna_Native_read__J_3DII
|
||||
{
|
||||
PSTART();
|
||||
(*env)->SetDoubleArrayRegion(env, arr, off, n, (jdouble*)L2A(addr));
|
||||
PEND();
|
||||
PEND(env);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2220,7 +2283,7 @@ JNIEXPORT void JNICALL Java_com_sun_jna_Native_read__J_3FII
|
||||
{
|
||||
PSTART();
|
||||
(*env)->SetFloatArrayRegion(env, arr, off, n, (jfloat*)L2A(addr));
|
||||
PEND();
|
||||
PEND(env);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2233,7 +2296,7 @@ JNIEXPORT void JNICALL Java_com_sun_jna_Native_read__J_3III
|
||||
{
|
||||
PSTART();
|
||||
(*env)->SetIntArrayRegion(env, arr, off, n, (jint*)L2A(addr));
|
||||
PEND();
|
||||
PEND(env);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2246,7 +2309,7 @@ JNIEXPORT void JNICALL Java_com_sun_jna_Native_read__J_3JII
|
||||
{
|
||||
PSTART();
|
||||
(*env)->SetLongArrayRegion(env, arr, off, n, (jlong*)L2A(addr));
|
||||
PEND();
|
||||
PEND(env);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2259,7 +2322,7 @@ JNIEXPORT void JNICALL Java_com_sun_jna_Native_read__J_3SII
|
||||
{
|
||||
PSTART();
|
||||
(*env)->SetShortArrayRegion(env, arr, off, n, (jshort*)L2A(addr));
|
||||
PEND();
|
||||
PEND(env);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2271,7 +2334,7 @@ JNIEXPORT jbyte JNICALL Java_com_sun_jna_Native_getByte
|
||||
(JNIEnv * env, jclass UNUSED(cls), jlong addr)
|
||||
{
|
||||
jbyte res = 0;
|
||||
MEMCPY(&res, L2A(addr), sizeof(res));
|
||||
MEMCPY(env, &res, L2A(addr), sizeof(res));
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -2284,7 +2347,7 @@ JNIEXPORT jchar JNICALL Java_com_sun_jna_Native_getChar
|
||||
(JNIEnv * env, jclass UNUSED(cls), jlong addr)
|
||||
{
|
||||
wchar_t res = 0;
|
||||
MEMCPY(&res, L2A(addr), sizeof(res));
|
||||
MEMCPY(env, &res, L2A(addr), sizeof(res));
|
||||
return (jchar)res;
|
||||
}
|
||||
|
||||
@@ -2297,7 +2360,7 @@ JNIEXPORT jlong JNICALL Java_com_sun_jna_Native__1getPointer
|
||||
(JNIEnv *env, jclass UNUSED(cls), jlong addr)
|
||||
{
|
||||
void *ptr = NULL;
|
||||
MEMCPY(&ptr, L2A(addr), sizeof(ptr));
|
||||
MEMCPY(env, &ptr, L2A(addr), sizeof(ptr));
|
||||
return A2L(ptr);
|
||||
}
|
||||
|
||||
@@ -2325,7 +2388,7 @@ JNIEXPORT jdouble JNICALL Java_com_sun_jna_Native_getDouble
|
||||
(JNIEnv * env, jclass UNUSED(cls), jlong addr)
|
||||
{
|
||||
jdouble res = 0;
|
||||
MEMCPY(&res, L2A(addr), sizeof(res));
|
||||
MEMCPY(env, &res, L2A(addr), sizeof(res));
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -2338,7 +2401,7 @@ JNIEXPORT jfloat JNICALL Java_com_sun_jna_Native_getFloat
|
||||
(JNIEnv * env, jclass UNUSED(cls), jlong addr)
|
||||
{
|
||||
jfloat res = 0;
|
||||
MEMCPY(&res, L2A(addr), sizeof(res));
|
||||
MEMCPY(env, &res, L2A(addr), sizeof(res));
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -2351,7 +2414,7 @@ JNIEXPORT jint JNICALL Java_com_sun_jna_Native_getInt
|
||||
(JNIEnv * env, jclass UNUSED(cls), jlong addr)
|
||||
{
|
||||
jint res = 0;
|
||||
MEMCPY(&res, L2A(addr), sizeof(res));
|
||||
MEMCPY(env, &res, L2A(addr), sizeof(res));
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -2364,7 +2427,7 @@ JNIEXPORT jlong JNICALL Java_com_sun_jna_Native_getLong
|
||||
(JNIEnv * env, jclass UNUSED(cls), jlong addr)
|
||||
{
|
||||
jlong res = 0;
|
||||
MEMCPY(&res, L2A(addr), sizeof(res));
|
||||
MEMCPY(env, &res, L2A(addr), sizeof(res));
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -2377,7 +2440,7 @@ JNIEXPORT jshort JNICALL Java_com_sun_jna_Native_getShort
|
||||
(JNIEnv * env, jclass UNUSED(cls), jlong addr)
|
||||
{
|
||||
jshort res = 0;
|
||||
MEMCPY(&res, L2A(addr), sizeof(res));
|
||||
MEMCPY(env, &res, L2A(addr), sizeof(res));
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -2412,7 +2475,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_sun_jna_Native_getStringBytes
|
||||
throwByName(env, EOutOfMemory, "Can't allocate byte array");
|
||||
}
|
||||
}
|
||||
PEND();
|
||||
PEND(env);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
@@ -2424,7 +2487,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_sun_jna_Native_getStringBytes
|
||||
JNIEXPORT void JNICALL Java_com_sun_jna_Native_setMemory
|
||||
(JNIEnv *env, jclass UNUSED(cls), jlong addr, jlong count, jbyte value)
|
||||
{
|
||||
MEMSET(L2A(addr), (int)value, (size_t)count);
|
||||
MEMSET(env, L2A(addr), (int)value, (size_t)count);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2435,7 +2498,7 @@ JNIEXPORT void JNICALL Java_com_sun_jna_Native_setMemory
|
||||
JNIEXPORT void JNICALL Java_com_sun_jna_Native_setByte
|
||||
(JNIEnv * env, jclass UNUSED(cls), jlong addr, jbyte value)
|
||||
{
|
||||
MEMCPY(L2A(addr), &value, sizeof(value));
|
||||
MEMCPY(env, L2A(addr), &value, sizeof(value));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2447,7 +2510,7 @@ JNIEXPORT void JNICALL Java_com_sun_jna_Native_setChar
|
||||
(JNIEnv * env, jclass UNUSED(cls), jlong addr, jchar value)
|
||||
{
|
||||
wchar_t ch = value;
|
||||
MEMCPY(L2A(addr), &ch, sizeof(ch));
|
||||
MEMCPY(env, L2A(addr), &ch, sizeof(ch));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2459,7 +2522,7 @@ JNIEXPORT void JNICALL Java_com_sun_jna_Native_setPointer
|
||||
(JNIEnv * env, jclass UNUSED(cls), jlong addr, jlong value)
|
||||
{
|
||||
void *ptr = L2A(value);
|
||||
MEMCPY(L2A(addr), &ptr, sizeof(void *));
|
||||
MEMCPY(env, L2A(addr), &ptr, sizeof(void *));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2470,7 +2533,7 @@ JNIEXPORT void JNICALL Java_com_sun_jna_Native_setPointer
|
||||
JNIEXPORT void JNICALL Java_com_sun_jna_Native_setDouble
|
||||
(JNIEnv * env, jclass UNUSED(cls), jlong addr, jdouble value)
|
||||
{
|
||||
MEMCPY(L2A(addr), &value, sizeof(value));
|
||||
MEMCPY(env, L2A(addr), &value, sizeof(value));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2481,7 +2544,7 @@ JNIEXPORT void JNICALL Java_com_sun_jna_Native_setDouble
|
||||
JNIEXPORT void JNICALL Java_com_sun_jna_Native_setFloat
|
||||
(JNIEnv * env, jclass UNUSED(cls), jlong addr, jfloat value)
|
||||
{
|
||||
MEMCPY(L2A(addr), &value, sizeof(value));
|
||||
MEMCPY(env, L2A(addr), &value, sizeof(value));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2492,7 +2555,7 @@ JNIEXPORT void JNICALL Java_com_sun_jna_Native_setFloat
|
||||
JNIEXPORT void JNICALL Java_com_sun_jna_Native_setInt
|
||||
(JNIEnv * env, jclass UNUSED(cls), jlong addr, jint value)
|
||||
{
|
||||
MEMCPY(L2A(addr), &value, sizeof(value));
|
||||
MEMCPY(env, L2A(addr), &value, sizeof(value));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2503,7 +2566,7 @@ JNIEXPORT void JNICALL Java_com_sun_jna_Native_setInt
|
||||
JNIEXPORT void JNICALL Java_com_sun_jna_Native_setLong
|
||||
(JNIEnv * env, jclass UNUSED(cls), jlong addr, jlong value)
|
||||
{
|
||||
MEMCPY(L2A(addr), &value, sizeof(value));
|
||||
MEMCPY(env, L2A(addr), &value, sizeof(value));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2514,7 +2577,7 @@ JNIEXPORT void JNICALL Java_com_sun_jna_Native_setLong
|
||||
JNIEXPORT void JNICALL Java_com_sun_jna_Native_setShort
|
||||
(JNIEnv * env, jclass UNUSED(cls), jlong addr, jshort value)
|
||||
{
|
||||
MEMCPY(L2A(addr), &value, sizeof(value));
|
||||
MEMCPY(env, L2A(addr), &value, sizeof(value));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2531,7 +2594,7 @@ JNIEXPORT void JNICALL Java_com_sun_jna_Native_setWideString
|
||||
|
||||
str = newWideCString(env, value);
|
||||
if (str != NULL) {
|
||||
MEMCPY(L2A(addr), str, size);
|
||||
MEMCPY(env, L2A(addr), str, size);
|
||||
free((void*)str);
|
||||
}
|
||||
}
|
||||
@@ -2574,7 +2637,7 @@ Java_com_sun_jna_Native_sizeof(JNIEnv *env, jclass UNUSED(cls), jint type)
|
||||
case com_sun_jna_Native_TYPE_SIZE_T: return sizeof(size_t);
|
||||
default:
|
||||
{
|
||||
char msg[1024];
|
||||
char msg[MSG_SIZE];
|
||||
snprintf(msg, sizeof(msg), "Invalid sizeof type %d", (int)type);
|
||||
throwByName(env, EIllegalArgument, msg);
|
||||
return -1;
|
||||
@@ -2827,8 +2890,9 @@ Java_com_sun_jna_Native_getWindowHandle0(JNIEnv *env, jclass UNUSED(classp), job
|
||||
// Use Unicode strings in case the path to the library includes non-ASCII
|
||||
// characters.
|
||||
wchar_t* path = L"jawt.dll";
|
||||
wchar_t* prop = (wchar_t*)get_system_property(env, "java.home", JNI_TRUE);
|
||||
if (prop != NULL) {
|
||||
jstring jprop = get_system_property(env, "java.home");
|
||||
if (jprop != NULL) {
|
||||
const wchar_t* prop = newWideCString(env, jprop);
|
||||
const wchar_t* suffix = L"/bin/jawt.dll";
|
||||
size_t len = wcslen(prop) + wcslen(suffix) + 1;
|
||||
path = (wchar_t*)alloca(len * sizeof(wchar_t));
|
||||
@@ -2843,12 +2907,12 @@ Java_com_sun_jna_Native_getWindowHandle0(JNIEnv *env, jclass UNUSED(classp), job
|
||||
#define JAWT_NAME path
|
||||
#endif
|
||||
if ((jawt_handle = LOAD_LIBRARY(JAWT_NAME, DEFAULT_LOAD_OPTS)) == NULL) {
|
||||
char msg[1024];
|
||||
char msg[MSG_SIZE];
|
||||
throwByName(env, EUnsatisfiedLink, LOAD_ERROR(msg, sizeof(msg)));
|
||||
return -1;
|
||||
}
|
||||
if ((pJAWT_GetAWT = (void*)FIND_ENTRY(jawt_handle, METHOD_NAME)) == NULL) {
|
||||
char msg[1024], buf[1024];
|
||||
char msg[MSG_SIZE], buf[MSG_SIZE];
|
||||
snprintf(msg, sizeof(msg), "Error looking up JAWT method %s: %s",
|
||||
METHOD_NAME, LOAD_ERROR(buf, sizeof(buf)));
|
||||
throwByName(env, EUnsatisfiedLink, msg);
|
||||
@@ -2967,13 +3031,13 @@ Java_com_sun_jna_Native_isProtected(JNIEnv *UNUSED(env), jclass UNUSED(classp))
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_sun_jna_Native_setLastError(JNIEnv *env, jclass UNUSED(classp), jint code) {
|
||||
JNA_set_last_error(code);
|
||||
JNA_set_last_error(env, code);
|
||||
SET_LAST_ERROR(code);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_sun_jna_Native_getLastError(JNIEnv *env, jclass UNUSED(classp)) {
|
||||
return JNA_get_last_error();
|
||||
return JNA_get_last_error(env);
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
@@ -3015,7 +3079,9 @@ JNI_OnLoad(JavaVM *jvm, void *UNUSED(reserved)) {
|
||||
result = 0;
|
||||
}
|
||||
if (!attached) {
|
||||
(*jvm)->DetachCurrentThread(jvm);
|
||||
if ((*jvm)->DetachCurrentThread(jvm) != 0) {
|
||||
fprintf(stderr, "JNA: could not detach thread on initial load\n");
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -3055,6 +3121,11 @@ JNI_OnUnload(JavaVM *vm, void *UNUSED(reserved)) {
|
||||
}
|
||||
}
|
||||
|
||||
if (fileEncoding) {
|
||||
(*env)->DeleteGlobalRef(env, fileEncoding);
|
||||
fileEncoding = NULL;
|
||||
}
|
||||
|
||||
for (i=0;i < sizeof(refs)/sizeof(refs[0]);i++) {
|
||||
if (*refs[i]) {
|
||||
(*env)->DeleteWeakGlobalRef(env, *refs[i]);
|
||||
@@ -3073,7 +3144,9 @@ JNI_OnUnload(JavaVM *vm, void *UNUSED(reserved)) {
|
||||
#endif
|
||||
|
||||
if (!attached) {
|
||||
(*vm)->DetachCurrentThread(vm);
|
||||
if ((*vm)->DetachCurrentThread(vm) != 0) {
|
||||
fprintf(stderr, "JNA: could not detach thread on unload\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3275,8 +3348,8 @@ Java_com_sun_jna_Native_initialize_1ffi_1type(JNIEnv *env, jclass UNUSED(cls), j
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_sun_jna_Native_detach(JNIEnv* env, jclass UNUSED(cls), jboolean d) {
|
||||
JNA_detach(d);
|
||||
Java_com_sun_jna_Native_setDetachState(JNIEnv* env, jclass UNUSED(cls), jboolean d, jlong flag) {
|
||||
JNA_detach(env, d, L2A(flag));
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
+13
-13
@@ -13,10 +13,12 @@
|
||||
#ifndef DISPATCH_H
|
||||
#define DISPATCH_H
|
||||
|
||||
#define MSG_SIZE 1024
|
||||
|
||||
#include "ffi.h"
|
||||
#include "com_sun_jna_Function.h"
|
||||
#include "com_sun_jna_Native.h"
|
||||
#if defined(sun) || defined(_AIX)
|
||||
#if defined(__sun__) || defined(_AIX)
|
||||
# include <alloca.h>
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
@@ -94,10 +96,6 @@ enum {
|
||||
/* callback behavior flags */
|
||||
enum {
|
||||
CB_HAS_INITIALIZER = com_sun_jna_Native_CB_HAS_INITIALIZER,
|
||||
// detach options
|
||||
THREAD_NOCHANGE,
|
||||
THREAD_DETACH,
|
||||
THREAD_LEAVE_ATTACHED,
|
||||
};
|
||||
|
||||
typedef struct _callback {
|
||||
@@ -134,12 +132,14 @@ typedef struct _callback {
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include "snprintf.h"
|
||||
#define strdup _strdup
|
||||
#if defined(_WIN64)
|
||||
#define L2A(X) ((void *)(X))
|
||||
#define A2L(X) ((jlong)(X))
|
||||
#define snprintf sprintf_s
|
||||
#else
|
||||
#if defined(_WIN32_WCE)
|
||||
#define snprintf _snprintf
|
||||
#define L2A(X) ((void *)(unsigned long)(X))
|
||||
#define A2L(X) ((jlong)(unsigned long)(X))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -177,10 +177,10 @@ extern int get_jtype(JNIEnv*, jclass);
|
||||
extern ffi_type* get_ffi_type(JNIEnv*, jclass, char);
|
||||
extern ffi_type* get_ffi_rtype(JNIEnv*, jclass, char);
|
||||
extern const char* JNA_callback_init(JNIEnv*);
|
||||
extern void JNA_set_last_error(int);
|
||||
extern int JNA_get_last_error();
|
||||
extern void JNA_set_last_error(JNIEnv*,int);
|
||||
extern int JNA_get_last_error(JNIEnv*);
|
||||
extern void JNA_callback_dispose(JNIEnv*);
|
||||
extern void JNA_detach(jboolean);
|
||||
extern void JNA_detach(JNIEnv*,jboolean,void*);
|
||||
extern callback* create_callback(JNIEnv*, jobject, jobject,
|
||||
jobjectArray, jclass,
|
||||
callconv_t, jint, jstring);
|
||||
@@ -225,9 +225,9 @@ extern jobject initializeThread(callback*,AttachOptions*);
|
||||
#define PROTECT is_protected()
|
||||
#endif
|
||||
#include "protect.h"
|
||||
#define ON_ERROR() throwByName(env, EError, "Invalid memory access")
|
||||
#define ON_ERROR(ENV) throwByName(ENV, EError, "Invalid memory access")
|
||||
#define PSTART() PROTECTED_START()
|
||||
#define PEND() PROTECTED_END(ON_ERROR())
|
||||
#define PEND(ENV) PROTECTED_END(ON_ERROR(ENV))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
+2
-2
@@ -15,7 +15,7 @@ do
|
||||
case $1
|
||||
in
|
||||
-m32)
|
||||
if echo $PATH | grep amd64; then
|
||||
if type link | grep amd64; then
|
||||
echo "Wrong LINK.EXE in path; use 32-bit version"
|
||||
exit 1
|
||||
fi
|
||||
@@ -26,7 +26,7 @@ do
|
||||
shift 1
|
||||
;;
|
||||
-m64)
|
||||
if ! echo $PATH | grep amd64; then
|
||||
if ! type link | grep amd64; then
|
||||
echo "Wrong LINK.EXE in path; use 64-bit version"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
#ifndef _SNPRINTF_H
|
||||
#define _SNPRINTF_H
|
||||
// snprintf on windows is broken; always nul-terminate manually
|
||||
// DO NOT rely on the return value...
|
||||
static int snprintf(char * str, size_t size, const char * format, ...) {
|
||||
int retval;
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
retval = _vsnprintf_s(str, size, _TRUNCATE, format, ap);
|
||||
va_end(ap);
|
||||
return retval;
|
||||
}
|
||||
#endif /* _SNPRINTF_H */
|
||||
+16
-7
@@ -19,6 +19,7 @@ extern "C" {
|
||||
#include <wchar.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#if !defined(_WIN32_WCE)
|
||||
#include <errno.h>
|
||||
#endif
|
||||
@@ -28,6 +29,7 @@ typedef signed char int8_t;
|
||||
typedef short int16_t;
|
||||
typedef int int32_t;
|
||||
typedef __int64 int64_t;
|
||||
#include "snprintf.h"
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
@@ -45,7 +47,11 @@ typedef __int64 int64_t;
|
||||
#define THREAD_EXIT() ExitThread(0)
|
||||
#define THREAD_FUNC(FN,ARG) DWORD WINAPI FN(LPVOID ARG)
|
||||
#define THREAD_CURRENT() GetCurrentThreadId()
|
||||
#ifdef _WIN64
|
||||
#define THREAD_RETURN
|
||||
#else
|
||||
#define THREAD_RETURN return 0
|
||||
#endif
|
||||
#else
|
||||
#define EXPORT
|
||||
#include <unistd.h>
|
||||
@@ -635,9 +641,9 @@ typedef struct thread_data {
|
||||
int repeat_count;
|
||||
int sleep_time;
|
||||
void (*func)(void);
|
||||
char name[256];
|
||||
} thread_data;
|
||||
static THREAD_FUNC(thread_function, arg) {
|
||||
// make a local copy
|
||||
thread_data td = *(thread_data*)arg;
|
||||
void (*func)(void) = td.func;
|
||||
int i;
|
||||
@@ -646,18 +652,21 @@ static THREAD_FUNC(thread_function, arg) {
|
||||
func();
|
||||
SLEEP(td.sleep_time);
|
||||
}
|
||||
free((void*)arg);
|
||||
THREAD_EXIT();
|
||||
THREAD_RETURN;
|
||||
}
|
||||
|
||||
static thread_data data;
|
||||
EXPORT void
|
||||
callVoidCallbackThreaded(void (*func)(void), int n, int ms) {
|
||||
callVoidCallbackThreaded(void (*func)(void), int n, int ms, const char* name) {
|
||||
THREAD_T thread;
|
||||
data.repeat_count = n;
|
||||
data.sleep_time = ms;
|
||||
data.func = func;
|
||||
THREAD_CREATE(&thread, &thread_function, &data);
|
||||
thread_data* data = (thread_data*)malloc(sizeof(thread_data));
|
||||
|
||||
data->repeat_count = n;
|
||||
data->sleep_time = ms;
|
||||
data->func = func;
|
||||
snprintf(data->name, sizeof(data->name), "%s", name);
|
||||
THREAD_CREATE(&thread, &thread_function, data);
|
||||
}
|
||||
|
||||
EXPORT int
|
||||
|
||||
@@ -1,53 +1,53 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
|
||||
http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>net.java.dev.jna</groupId>
|
||||
<artifactId>platform</artifactId>
|
||||
<version>4.0.0-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>Java Native Access Platform</name>
|
||||
<description>Java Native Access Platform</description>
|
||||
<url>https://github.com/twall/jna</url>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>LGPL, version 2.1</name>
|
||||
<url>http://www.gnu.org/licenses/licenses.html</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
<license>
|
||||
<name>ASL, version 2</name>
|
||||
<url>http://www.apache.org/licenses/</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<scm>
|
||||
<connection>scm:git:https://github.com/twall/jna</connection>
|
||||
<developerConnection>scm:git:ssh://git@github.com/twall/jna.git</developerConnection>
|
||||
<url>https://github.com/twall/jna</url>
|
||||
</scm>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<id>twall</id>
|
||||
<name>Timothy Wall</name>
|
||||
<roles>
|
||||
<role>Owner</role>
|
||||
</roles>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>net.java.dev.jna</groupId>
|
||||
<artifactId>jna</artifactId>
|
||||
<version>4.0.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
|
||||
http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>net.java.dev.jna</groupId>
|
||||
<artifactId>jna-platform</artifactId>
|
||||
<version>4.0.0-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>Java Native Access Platform</name>
|
||||
<description>Java Native Access Platform</description>
|
||||
<url>https://github.com/twall/jna</url>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>LGPL, version 2.1</name>
|
||||
<url>http://www.gnu.org/licenses/licenses.html</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
<license>
|
||||
<name>ASL, version 2</name>
|
||||
<url>http://www.apache.org/licenses/</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<scm>
|
||||
<connection>scm:git:https://github.com/twall/jna</connection>
|
||||
<developerConnection>scm:git:ssh://git@github.com/twall/jna.git</developerConnection>
|
||||
<url>https://github.com/twall/jna</url>
|
||||
</scm>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<id>twall</id>
|
||||
<name>Timothy Wall</name>
|
||||
<roles>
|
||||
<role>Owner</role>
|
||||
</roles>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>net.java.dev.jna</groupId>
|
||||
<artifactId>jna</artifactId>
|
||||
<version>4.0.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
+44
-44
@@ -1,45 +1,45 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
|
||||
http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>net.java.dev.jna</groupId>
|
||||
<artifactId>jna</artifactId>
|
||||
<version>4.0.0-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>Java Native Access</name>
|
||||
<description>Java Native Access</description>
|
||||
<url>https://github.com/twall/jna</url>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>LGPL, version 2.1</name>
|
||||
<url>http://www.gnu.org/licenses/licenses.html</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
<license>
|
||||
<name>ASL, version 2</name>
|
||||
<url>http://www.apache.org/licenses/</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<scm>
|
||||
<connection>scm:git:https://github.com/twall/jna</connection>
|
||||
<developerConnection>scm:git:ssh://git@github.com/twall/jna.git</developerConnection>
|
||||
<url>https://github.com/twall/jna</url>
|
||||
</scm>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<id>twall</id>
|
||||
<name>Timothy Wall</name>
|
||||
<roles>
|
||||
<role>Owner</role>
|
||||
</roles>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
|
||||
http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>net.java.dev.jna</groupId>
|
||||
<artifactId>jna</artifactId>
|
||||
<version>4.0.0-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>Java Native Access</name>
|
||||
<description>Java Native Access</description>
|
||||
<url>https://github.com/twall/jna</url>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>LGPL, version 2.1</name>
|
||||
<url>http://www.gnu.org/licenses/licenses.html</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
<license>
|
||||
<name>ASL, version 2</name>
|
||||
<url>http://www.apache.org/licenses/</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<scm>
|
||||
<connection>scm:git:https://github.com/twall/jna</connection>
|
||||
<developerConnection>scm:git:ssh://git@github.com/twall/jna.git</developerConnection>
|
||||
<url>https://github.com/twall/jna</url>
|
||||
</scm>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<id>twall</id>
|
||||
<name>Timothy Wall</name>
|
||||
<roles>
|
||||
<role>Owner</role>
|
||||
</roles>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
</project>
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2007-2008 Timothy Wall, All Rights Reserved
|
||||
/* Copyright (c) 2007-2013 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
|
||||
@@ -12,12 +12,14 @@
|
||||
*/
|
||||
package com.sun.jna;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
@@ -36,7 +38,9 @@ class CallbackReference extends WeakReference {
|
||||
|
||||
static final Map callbackMap = new WeakHashMap();
|
||||
static final Map directCallbackMap = new WeakHashMap();
|
||||
static final Map pointerCallbackMap = new WeakHashMap();
|
||||
static final Map allocations = new WeakHashMap();
|
||||
|
||||
private static final Method PROXY_CALLBACK_METHOD;
|
||||
|
||||
static {
|
||||
@@ -67,16 +71,17 @@ class CallbackReference extends WeakReference {
|
||||
// Thread name must be UTF8-encoded
|
||||
{ setStringEncoding("utf8"); }
|
||||
protected List getFieldOrder() {
|
||||
return Arrays.asList(new String[] { "daemon", "detach", "name" });
|
||||
return Arrays.asList(new String[] { "daemon", "detach", "name", });
|
||||
}
|
||||
}
|
||||
|
||||
/** Called from native code to initialize a callback thread. */
|
||||
private static ThreadGroup initializeThread(Callback cb, AttachOptions args) {
|
||||
CallbackThreadInitializer init = null;
|
||||
if (cb instanceof DefaultCallbackProxy) {
|
||||
cb = ((DefaultCallbackProxy)cb).getCallback();
|
||||
}
|
||||
synchronized(initializers) {
|
||||
synchronized(callbackMap) {
|
||||
init = (CallbackThreadInitializer)initializers.get(cb);
|
||||
}
|
||||
ThreadGroup group = null;
|
||||
@@ -92,7 +97,10 @@ class CallbackReference extends WeakReference {
|
||||
|
||||
/** Return a Callback associated with the given function pointer.
|
||||
* If the pointer refers to a Java callback trampoline, return the original
|
||||
* Java Callback. Otherwise, return a proxy to the native function pointer.
|
||||
* Java Callback. Otherwise, return a proxy to the native function
|
||||
* pointer.
|
||||
* @throws IllegalStateException if the given pointer has already been
|
||||
* mapped to a callback of a different type.
|
||||
*/
|
||||
public static Callback getCallback(Class type, Pointer p) {
|
||||
return getCallback(type, p, false);
|
||||
@@ -107,29 +115,30 @@ class CallbackReference extends WeakReference {
|
||||
throw new IllegalArgumentException("Callback type must be an interface");
|
||||
Map map = direct ? directCallbackMap : callbackMap;
|
||||
synchronized(callbackMap) {
|
||||
for (Iterator i=map.keySet().iterator();i.hasNext();) {
|
||||
Callback cb = (Callback)i.next();
|
||||
if (type.isAssignableFrom(cb.getClass())) {
|
||||
CallbackReference cbref = (CallbackReference)map.get(cb);
|
||||
Pointer cbp = cbref != null
|
||||
? cbref.getTrampoline() : getNativeFunctionPointer(cb);
|
||||
if (p.equals(cbp)) {
|
||||
return cb;
|
||||
}
|
||||
Callback cb = null;
|
||||
Reference ref = (Reference)pointerCallbackMap.get(p);
|
||||
if (ref != null) {
|
||||
cb = (Callback)ref.get();
|
||||
if (cb != null && !type.isAssignableFrom(cb.getClass())) {
|
||||
throw new IllegalStateException("Pointer " + p + " already mapped to " + cb);
|
||||
}
|
||||
return cb;
|
||||
}
|
||||
int ctype = AltCallingConvention.class.isAssignableFrom(type)
|
||||
? Function.ALT_CONVENTION : Function.C_CONVENTION;
|
||||
Map foptions = new HashMap(Native.getLibraryOptions(type));
|
||||
foptions.put(Function.OPTION_INVOKING_METHOD, getCallbackMethod(type));
|
||||
NativeFunctionHandler h = new NativeFunctionHandler(p, ctype, foptions);
|
||||
Callback cb = (Callback)Proxy.newProxyInstance(type.getClassLoader(), new Class[] { type }, h);
|
||||
cb = (Callback)Proxy.newProxyInstance(type.getClassLoader(), new Class[] { type }, h);
|
||||
// No CallbackReference for this callback
|
||||
map.put(cb, null);
|
||||
pointerCallbackMap.put(p, new WeakReference(cb));
|
||||
return cb;
|
||||
}
|
||||
}
|
||||
|
||||
Pointer cbstruct;
|
||||
Pointer trampoline;
|
||||
// Keep a reference to the proxy to avoid premature GC of it
|
||||
CallbackProxy proxy;
|
||||
Method method;
|
||||
@@ -328,7 +337,10 @@ class CallbackReference extends WeakReference {
|
||||
|
||||
/** Obtain a pointer to the native glue code for this callback. */
|
||||
public Pointer getTrampoline() {
|
||||
return cbstruct.getPointer(0);
|
||||
if (trampoline == null) {
|
||||
trampoline = cbstruct.getPointer(0);
|
||||
}
|
||||
return trampoline;
|
||||
}
|
||||
|
||||
/** Free native resources associated with this callback when GC'd. */
|
||||
@@ -386,6 +398,7 @@ class CallbackReference extends WeakReference {
|
||||
if (cbref == null) {
|
||||
cbref = new CallbackReference(cb, callingConvention, direct);
|
||||
map.put(cb, cbref);
|
||||
pointerCallbackMap.put(cbref.getTrampoline(), new WeakReference(cb));
|
||||
if (initializers.containsKey(cb)) {
|
||||
cbref.setCallbackOptions(Native.CB_HAS_INITIALIZER);
|
||||
}
|
||||
|
||||
@@ -286,10 +286,16 @@ public class Function extends Pointer {
|
||||
TypeMapper mapper =
|
||||
(TypeMapper)options.get(Library.OPTION_TYPE_MAPPER);
|
||||
Method invokingMethod = (Method)options.get(OPTION_INVOKING_METHOD);
|
||||
Class[] paramTypes = invokingMethod != null ? invokingMethod.getParameterTypes() : null;
|
||||
boolean allowObjects = Boolean.TRUE.equals(options.get(Library.OPTION_ALLOW_OBJECTS));
|
||||
for (int i=0; i < args.length; i++) {
|
||||
Class paramType = invokingMethod != null
|
||||
? (isVarArgs(invokingMethod) && i >= paramTypes.length-1
|
||||
? paramTypes[paramTypes.length-1].getComponentType()
|
||||
: paramTypes[i])
|
||||
: null;
|
||||
args[i] = convertArgument(args, i, invokingMethod,
|
||||
mapper, allowObjects);
|
||||
mapper, allowObjects, paramType);
|
||||
}
|
||||
|
||||
Class nativeType = returnType;
|
||||
@@ -467,7 +473,7 @@ public class Function extends Pointer {
|
||||
|
||||
private Object convertArgument(Object[] args, int index,
|
||||
Method invokingMethod, TypeMapper mapper,
|
||||
boolean allowObjects) {
|
||||
boolean allowObjects, Class expectedType) {
|
||||
Object arg = args[index];
|
||||
if (arg != null) {
|
||||
Class type = arg.getClass();
|
||||
@@ -556,9 +562,29 @@ public class Function extends Pointer {
|
||||
return new NativeMappedArray((NativeMapped[])arg);
|
||||
}
|
||||
else if (Structure[].class.isAssignableFrom(argClass)) {
|
||||
// If the signature is Structure[], disallow
|
||||
// Structure.ByReference[] and Structure.ByReference elements
|
||||
Structure[] ss = (Structure[])arg;
|
||||
Class type = argClass.getComponentType();
|
||||
boolean byRef = Structure.ByReference.class.isAssignableFrom(type);
|
||||
if (expectedType != null) {
|
||||
if (!Structure.ByReference[].class.isAssignableFrom(expectedType)) {
|
||||
if (byRef) {
|
||||
throw new IllegalArgumentException("Function " + getName()
|
||||
+ " declared Structure[] at parameter "
|
||||
+ index + " but array of "
|
||||
+ type + " was passed");
|
||||
}
|
||||
for (int i=0;i < ss.length;i++) {
|
||||
if (ss[i] instanceof Structure.ByReference) {
|
||||
throw new IllegalArgumentException("Function " + getName()
|
||||
+ " declared Structure[] at parameter "
|
||||
+ index + " but element " + i
|
||||
+ " is of Structure.ByReference type");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (byRef) {
|
||||
Structure.autoWrite(ss);
|
||||
Pointer[] pointers = new Pointer[ss.length + 1];
|
||||
|
||||
@@ -51,11 +51,12 @@ import java.util.WeakHashMap;
|
||||
* <code>loadLibrary</code> result.
|
||||
* <p>
|
||||
* <b>OPTIONS</b> (an instance of {@link Map}),
|
||||
* <b>TYPE_MAPPER</b> (an instance of {@link TypeMapper}) and
|
||||
* <b>TYPE_MAPPER</b> (an instance of {@link TypeMapper}),
|
||||
* <b>STRUCTURE_ALIGNMENT</b> (one of the alignment types defined in
|
||||
* {@link Structure}) may also be defined. If no instance of the interface
|
||||
* has been instantiated, these fields will be used to determine customization
|
||||
* settings for structures and methods defined within the interface.
|
||||
* {@link Structure}), and <b>STRING_ENCODING</b> (a {@link String}) may also
|
||||
* be defined. If no instance of the interface has been instantiated, these
|
||||
* fields will be used to determine customization settings for structures and
|
||||
* methods defined within the interface.
|
||||
* <p>
|
||||
*
|
||||
* @author Todd Fast, todd.fast@sun.com
|
||||
@@ -117,25 +118,10 @@ public interface Library {
|
||||
}
|
||||
}
|
||||
|
||||
private static class FunctionNameMap implements FunctionMapper {
|
||||
private final Map map;
|
||||
public FunctionNameMap(Map map) {
|
||||
this.map = new HashMap(map);
|
||||
}
|
||||
public String getFunctionName(NativeLibrary library, Method method) {
|
||||
String name = method.getName();
|
||||
if (map.containsKey(name)) {
|
||||
return (String)map.get(name);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
private final NativeLibrary nativeLibrary;
|
||||
private final Class interfaceClass;
|
||||
// Library invocation options
|
||||
private final Map options;
|
||||
private FunctionMapper functionMapper;
|
||||
private final InvocationMapper invocationMapper;
|
||||
private final Map functions = new WeakHashMap();
|
||||
public Handler(String libname, Class interfaceClass, Map options) {
|
||||
@@ -154,13 +140,11 @@ public interface Library {
|
||||
options.put(OPTION_CALLING_CONVENTION,
|
||||
new Integer(callingConvention));
|
||||
}
|
||||
if (options.get(OPTION_CLASSLOADER) == null) {
|
||||
options.put(OPTION_CLASSLOADER, interfaceClass.getClassLoader());
|
||||
}
|
||||
this.options = options;
|
||||
this.nativeLibrary = NativeLibrary.getInstance(libname, options);
|
||||
functionMapper = (FunctionMapper)options.get(OPTION_FUNCTION_MAPPER);
|
||||
if (functionMapper == null) {
|
||||
// backward compatibility; passed-in map is itself the name map
|
||||
functionMapper = new FunctionNameMap(options);
|
||||
}
|
||||
invocationMapper = (InvocationMapper)options.get(OPTION_INVOCATION_MAPPER);
|
||||
}
|
||||
|
||||
@@ -212,13 +196,7 @@ public interface Library {
|
||||
}
|
||||
if (f.handler == null) {
|
||||
// Find the function to invoke
|
||||
String methodName =
|
||||
functionMapper.getFunctionName(nativeLibrary, method);
|
||||
if (methodName == null) {
|
||||
// Just in case the function mapper screwed up
|
||||
methodName = method.getName();
|
||||
}
|
||||
f.function = nativeLibrary.getFunction(methodName, method);
|
||||
f.function = nativeLibrary.getFunction(method.getName(), method);
|
||||
f.options = new HashMap(this.options);
|
||||
f.options.put(Function.OPTION_INVOKING_METHOD, method);
|
||||
}
|
||||
|
||||
+186
-74
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2007-2012 Timothy Wall, All Rights Reserved
|
||||
/* Copyright (c) 2007-2013 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
|
||||
@@ -92,9 +92,11 @@ import com.sun.jna.Structure.FFIType;
|
||||
public final class Native implements Version {
|
||||
|
||||
public static final String DEFAULT_ENCODING = "utf8";
|
||||
static final boolean DEBUG_LOAD = Boolean.getBoolean("jna.debug_load");
|
||||
static final boolean DEBUG_JNA_LOAD = Boolean.getBoolean("jna.debug_load.jna");
|
||||
|
||||
// Used by tests, do not remove
|
||||
private static String nativeLibraryPath = null;
|
||||
static String jnidispatchPath = null;
|
||||
private static Map options = new WeakHashMap();
|
||||
private static Map libraries = new WeakHashMap();
|
||||
private static final UncaughtExceptionHandler DEFAULT_HANDLER =
|
||||
@@ -122,6 +124,7 @@ public final class Native implements Version {
|
||||
private static final int TYPE_WCHAR_T = 2;
|
||||
private static final int TYPE_SIZE_T = 3;
|
||||
|
||||
static final int MAX_ALIGNMENT;
|
||||
static final int MAX_PADDING;
|
||||
|
||||
static {
|
||||
@@ -142,8 +145,8 @@ public final class Native implements Version {
|
||||
String LS = System.getProperty("line.separator");
|
||||
throw new Error(LS + LS
|
||||
+ "There is an incompatible JNA native library installed on this system" + LS
|
||||
+ (nativeLibraryPath != null
|
||||
? "(at " + nativeLibraryPath + ")" : System.getProperty("java.library.path"))
|
||||
+ (jnidispatchPath != null
|
||||
? "(at " + jnidispatchPath + ")" : System.getProperty("java.library.path"))
|
||||
+ "." + LS
|
||||
+ "To resolve this issue you may do one of the following:" + LS
|
||||
+ " - remove or uninstall the offending library" + LS
|
||||
@@ -151,9 +154,12 @@ public final class Native implements Version {
|
||||
+ " - set jna.boot.library.path to include the path to the version of the " + LS
|
||||
+ " jnidispatch library included with the JNA jar file you are using" + LS);
|
||||
}
|
||||
setPreserveLastError("true".equalsIgnoreCase(System.getProperty("jna.preserve_last_error", "true")));
|
||||
MAX_PADDING = Platform.isSPARC() || Platform.isWindows()
|
||||
MAX_ALIGNMENT = Platform.isSPARC() || Platform.isWindows()
|
||||
|| (Platform.isLinux() && (Platform.isARM() || Platform.isPPC()))
|
||||
|| Platform.isAIX()
|
||||
|| Platform.isAndroid()
|
||||
? 8 : LONG_SIZE;
|
||||
MAX_PADDING = (Platform.isMac() && Platform.isPPC()) ? 8 : MAX_ALIGNMENT;
|
||||
}
|
||||
|
||||
/** Force a dispose when this class is GC'd. */
|
||||
@@ -166,7 +172,7 @@ public final class Native implements Version {
|
||||
/** Properly dispose of JNA functionality. */
|
||||
private static void dispose() {
|
||||
NativeLibrary.disposeAll();
|
||||
nativeLibraryPath = null;
|
||||
jnidispatchPath = null;
|
||||
}
|
||||
|
||||
/** Remove any automatically unpacked native library.
|
||||
@@ -419,22 +425,24 @@ public final class Native implements Version {
|
||||
* Expects that lock on libraries is already held
|
||||
*/
|
||||
private static void loadLibraryInstance(Class cls) {
|
||||
if (cls != null && !libraries.containsKey(cls)) {
|
||||
try {
|
||||
Field[] fields = cls.getFields();
|
||||
for (int i=0;i < fields.length;i++) {
|
||||
Field field = fields[i];
|
||||
if (field.getType() == cls
|
||||
&& Modifier.isStatic(field.getModifiers())) {
|
||||
// Ensure the field gets initialized by reading it
|
||||
libraries.put(cls, new WeakReference(field.get(null)));
|
||||
break;
|
||||
synchronized(libraries) {
|
||||
if (cls != null && !libraries.containsKey(cls)) {
|
||||
try {
|
||||
Field[] fields = cls.getFields();
|
||||
for (int i=0;i < fields.length;i++) {
|
||||
Field field = fields[i];
|
||||
if (field.getType() == cls
|
||||
&& Modifier.isStatic(field.getModifiers())) {
|
||||
// Ensure the field gets initialized by reading it
|
||||
libraries.put(cls, new WeakReference(field.get(null)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IllegalArgumentException("Could not access instance of "
|
||||
+ cls + " (" + e + ")");
|
||||
catch (Exception e) {
|
||||
throw new IllegalArgumentException("Could not access instance of "
|
||||
+ cls + " (" + e + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -447,6 +455,8 @@ public final class Native implements Version {
|
||||
if (cls == null) {
|
||||
return null;
|
||||
}
|
||||
// Check for direct-mapped libraries, which won't necessarily
|
||||
// implement com.sun.jna.Library.
|
||||
synchronized(libraries) {
|
||||
if (options.containsKey(cls)) {
|
||||
return cls;
|
||||
@@ -479,41 +489,53 @@ public final class Native implements Version {
|
||||
*/
|
||||
public static Map getLibraryOptions(Class type) {
|
||||
synchronized(libraries) {
|
||||
Class mappingClass = findEnclosingLibraryClass(type);
|
||||
if (mappingClass != null) {
|
||||
loadLibraryInstance(mappingClass);
|
||||
if (options.containsKey(type)) {
|
||||
return (Map)options.get(type);
|
||||
}
|
||||
else {
|
||||
mappingClass = type;
|
||||
}
|
||||
Class mappingClass = findEnclosingLibraryClass(type);
|
||||
if (mappingClass != null) {
|
||||
loadLibraryInstance(mappingClass);
|
||||
}
|
||||
else {
|
||||
mappingClass = type;
|
||||
}
|
||||
synchronized(libraries) {
|
||||
if (options.containsKey(mappingClass)) {
|
||||
Map libraryOptions = (Map)options.get(mappingClass);
|
||||
options.put(type, libraryOptions);
|
||||
return libraryOptions;
|
||||
}
|
||||
if (!options.containsKey(mappingClass)) {
|
||||
Map libraryOptions = null;
|
||||
try {
|
||||
Field field = mappingClass.getField("OPTIONS");
|
||||
field.setAccessible(true);
|
||||
libraryOptions = (Map)field.get(null);
|
||||
}
|
||||
catch (NoSuchFieldException e) {
|
||||
libraryOptions = Collections.EMPTY_MAP;
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IllegalArgumentException("OPTIONS must be a public field of type java.util.Map ("
|
||||
+ e + "): " + mappingClass);
|
||||
}
|
||||
// Make a clone of the original
|
||||
libraryOptions = new HashMap(libraryOptions);
|
||||
if (!libraryOptions.containsKey(Library.OPTION_TYPE_MAPPER)) {
|
||||
libraryOptions.put(Library.OPTION_TYPE_MAPPER, lookupField(mappingClass, "TYPE_MAPPER", TypeMapper.class));
|
||||
}
|
||||
if (!libraryOptions.containsKey(Library.OPTION_STRUCTURE_ALIGNMENT)) {
|
||||
libraryOptions.put(Library.OPTION_STRUCTURE_ALIGNMENT, lookupField(mappingClass, "STRUCTURE_ALIGNMENT", Integer.class));
|
||||
}
|
||||
if (!libraryOptions.containsKey(Library.OPTION_STRING_ENCODING)) {
|
||||
libraryOptions.put(Library.OPTION_STRING_ENCODING, lookupField(mappingClass, "STRING_ENCODING", String.class));
|
||||
}
|
||||
options.put(mappingClass, libraryOptions);
|
||||
Map libraryOptions = null;
|
||||
try {
|
||||
Field field = mappingClass.getField("OPTIONS");
|
||||
field.setAccessible(true);
|
||||
libraryOptions = (Map)field.get(null);
|
||||
}
|
||||
return (Map)options.get(mappingClass);
|
||||
catch (NoSuchFieldException e) {
|
||||
libraryOptions = Collections.EMPTY_MAP;
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IllegalArgumentException("OPTIONS must be a public field of type java.util.Map ("
|
||||
+ e + "): " + mappingClass);
|
||||
}
|
||||
// Make a clone of the original options
|
||||
libraryOptions = new HashMap(libraryOptions);
|
||||
if (!libraryOptions.containsKey(Library.OPTION_TYPE_MAPPER)) {
|
||||
libraryOptions.put(Library.OPTION_TYPE_MAPPER, lookupField(mappingClass, "TYPE_MAPPER", TypeMapper.class));
|
||||
}
|
||||
if (!libraryOptions.containsKey(Library.OPTION_STRUCTURE_ALIGNMENT)) {
|
||||
libraryOptions.put(Library.OPTION_STRUCTURE_ALIGNMENT, lookupField(mappingClass, "STRUCTURE_ALIGNMENT", Integer.class));
|
||||
}
|
||||
if (!libraryOptions.containsKey(Library.OPTION_STRING_ENCODING)) {
|
||||
libraryOptions.put(Library.OPTION_STRING_ENCODING, lookupField(mappingClass, "STRING_ENCODING", String.class));
|
||||
}
|
||||
options.put(mappingClass, libraryOptions);
|
||||
// Store the original lookup class, if different from the mapping class
|
||||
if (type != mappingClass) {
|
||||
options.put(type, libraryOptions);
|
||||
}
|
||||
return libraryOptions;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -643,10 +665,20 @@ public final class Native implements Version {
|
||||
String dir = dirs.nextToken();
|
||||
File file = new File(new File(dir), System.mapLibraryName(libName).replace(".dylib", ".jnilib"));
|
||||
String path = file.getAbsolutePath();
|
||||
if (DEBUG_JNA_LOAD) {
|
||||
System.out.println("Looking in " + path);
|
||||
}
|
||||
if (file.exists()) {
|
||||
try {
|
||||
if (DEBUG_JNA_LOAD) {
|
||||
System.out.println("Trying " + path);
|
||||
}
|
||||
System.setProperty("jnidispatch.path", path);
|
||||
System.load(path);
|
||||
nativeLibraryPath = path;
|
||||
jnidispatchPath = path;
|
||||
if (DEBUG_JNA_LOAD) {
|
||||
System.out.println("Found jnidispatch at " + path);
|
||||
}
|
||||
return;
|
||||
} catch (UnsatisfiedLinkError ex) {
|
||||
// Not a problem if already loaded in anoteher class loader
|
||||
@@ -664,10 +696,20 @@ public final class Native implements Version {
|
||||
ext = "dylib";
|
||||
}
|
||||
path = path.substring(0, path.lastIndexOf(orig)) + ext;
|
||||
if (DEBUG_JNA_LOAD) {
|
||||
System.out.println("Looking in " + path);
|
||||
}
|
||||
if (new File(path).exists()) {
|
||||
try {
|
||||
if (DEBUG_JNA_LOAD) {
|
||||
System.out.println("Trying " + path);
|
||||
}
|
||||
System.setProperty("jnidispatch.path", path);
|
||||
System.load(path);
|
||||
nativeLibraryPath = path;
|
||||
jnidispatchPath = path;
|
||||
if (DEBUG_JNA_LOAD) {
|
||||
System.out.println("Found jnidispatch at " + path);
|
||||
}
|
||||
return;
|
||||
} catch (UnsatisfiedLinkError ex) {
|
||||
System.err.println("File found at " + path + " but not loadable: " + ex.getMessage());
|
||||
@@ -678,7 +720,13 @@ public final class Native implements Version {
|
||||
}
|
||||
if (!Boolean.getBoolean("jna.nosys")) {
|
||||
try {
|
||||
if (DEBUG_JNA_LOAD) {
|
||||
System.out.println("Trying (via loadLibrary) " + libName);
|
||||
}
|
||||
System.loadLibrary(libName);
|
||||
if (DEBUG_JNA_LOAD) {
|
||||
System.out.println("Found jnidispatch on system path");
|
||||
}
|
||||
return;
|
||||
}
|
||||
catch(UnsatisfiedLinkError e) {
|
||||
@@ -706,13 +754,21 @@ public final class Native implements Version {
|
||||
throw new UnsatisfiedLinkError("Could not find JNA native support");
|
||||
}
|
||||
}
|
||||
System.load(lib.getAbsolutePath());
|
||||
nativeLibraryPath = lib.getAbsolutePath();
|
||||
if (DEBUG_JNA_LOAD) {
|
||||
System.out.println("Trying " + lib.getAbsolutePath());
|
||||
}
|
||||
System.setProperty("jnidispatch.path", lib.getAbsolutePath());
|
||||
System.load(lib.getAbsolutePath());
|
||||
jnidispatchPath = lib.getAbsolutePath();
|
||||
if (DEBUG_JNA_LOAD) {
|
||||
System.out.println("Found jnidispatch at " + jnidispatchPath);
|
||||
}
|
||||
// Attempt to delete immediately once jnidispatch is successfully
|
||||
// loaded. This avoids the complexity of trying to do so on "exit",
|
||||
// which point can vary under different circumstances (native
|
||||
// compilation, dynamically loaded modules, normal application, etc).
|
||||
if (isUnpacked(lib)) {
|
||||
if (isUnpacked(lib)
|
||||
&& !Boolean.getBoolean("jnidispatch.preserve")) {
|
||||
deleteLibrary(lib);
|
||||
}
|
||||
}
|
||||
@@ -754,6 +810,8 @@ public final class Native implements Version {
|
||||
* @throws IOException if resource not found
|
||||
*/
|
||||
public static File extractFromResourcePath(String name, ClassLoader loader) throws IOException {
|
||||
final boolean DEBUG = DEBUG_LOAD
|
||||
|| (DEBUG_JNA_LOAD && name.indexOf("jnidispatch") != -1);
|
||||
if (loader == null) {
|
||||
loader = Thread.currentThread().getContextClassLoader();
|
||||
// Context class loader is not guaranteed to be set
|
||||
@@ -761,6 +819,9 @@ public final class Native implements Version {
|
||||
loader = Native.class.getClassLoader();
|
||||
}
|
||||
}
|
||||
if (DEBUG) {
|
||||
System.out.println("Looking in classpath from " + loader + " for " + name);
|
||||
}
|
||||
String libname = name.startsWith("/") ? name : NativeLibrary.mapSharedLibraryName(name);
|
||||
String resourcePath = name.startsWith("/") ? name : Platform.RESOURCE_PREFIX + "/" + libname;
|
||||
if (resourcePath.startsWith("/")) {
|
||||
@@ -778,6 +839,9 @@ public final class Native implements Version {
|
||||
}
|
||||
throw new IOException("Native library (" + resourcePath + ") not found in resource path (" + path + ")");
|
||||
}
|
||||
if (DEBUG) {
|
||||
System.out.println("Found library resource at " + url);
|
||||
}
|
||||
|
||||
File lib = null;
|
||||
if (url.getProtocol().toLowerCase().equals("file")) {
|
||||
@@ -787,6 +851,9 @@ public final class Native implements Version {
|
||||
catch(URISyntaxException e) {
|
||||
lib = new File(url.getPath());
|
||||
}
|
||||
if (DEBUG) {
|
||||
System.out.println("Looking in " + lib.getAbsolutePath());
|
||||
}
|
||||
if (!lib.exists()) {
|
||||
throw new IOException("File URL " + url + " could not be properly decoded");
|
||||
}
|
||||
@@ -804,7 +871,9 @@ public final class Native implements Version {
|
||||
// problems with Web Start.
|
||||
File dir = getTempDir();
|
||||
lib = File.createTempFile(JNA_TMPLIB_PREFIX, Platform.isWindows()?".dll":null, dir);
|
||||
lib.deleteOnExit();
|
||||
if (!Boolean.getBoolean("jnidispatch.preserve")) {
|
||||
lib.deleteOnExit();
|
||||
}
|
||||
fos = new FileOutputStream(lib);
|
||||
int count;
|
||||
byte[] buf = new byte[1024];
|
||||
@@ -1084,7 +1153,7 @@ public final class Native implements Version {
|
||||
* @param libName library name to which functions should be bound
|
||||
*/
|
||||
public static void register(String libName) {
|
||||
register(getNativeClass(getCallingClass()), libName);
|
||||
register(findDirectMappedClass(getCallingClass()), libName);
|
||||
}
|
||||
|
||||
/** When called from a class static initializer, maps all native methods
|
||||
@@ -1093,10 +1162,11 @@ public final class Native implements Version {
|
||||
* @param lib native library to which functions should be bound
|
||||
*/
|
||||
public static void register(NativeLibrary lib) {
|
||||
register(getNativeClass(getCallingClass()), lib);
|
||||
register(findDirectMappedClass(getCallingClass()), lib);
|
||||
}
|
||||
|
||||
static Class getNativeClass(Class cls) {
|
||||
/** Find the nearest enclosing class with native methods. */
|
||||
static Class findDirectMappedClass(Class cls) {
|
||||
Method[] methods = cls.getDeclaredMethods();
|
||||
for (int i=0;i < methods.length;i++) {
|
||||
if ((methods[i].getModifiers() & Modifier.NATIVE) != 0) {
|
||||
@@ -1107,7 +1177,7 @@ public final class Native implements Version {
|
||||
if (idx != -1) {
|
||||
String name = cls.getName().substring(0, idx);
|
||||
try {
|
||||
return getNativeClass(Class.forName(name, true, cls.getClassLoader()));
|
||||
return findDirectMappedClass(Class.forName(name, true, cls.getClassLoader()));
|
||||
}
|
||||
catch(ClassNotFoundException e) {
|
||||
}
|
||||
@@ -1115,6 +1185,9 @@ public final class Native implements Version {
|
||||
throw new IllegalArgumentException("Can't determine class with native methods from the current context (" + cls + ")");
|
||||
}
|
||||
|
||||
/** Try to determine the class context in which a {@link #register(String)} call
|
||||
was made.
|
||||
*/
|
||||
static Class getCallingClass() {
|
||||
Class[] context = new SecurityManager() {
|
||||
public Class[] getClassContext() {
|
||||
@@ -1159,7 +1232,7 @@ public final class Native implements Version {
|
||||
to be garbage collected.
|
||||
*/
|
||||
public static void unregister() {
|
||||
unregister(getNativeClass(getCallingClass()));
|
||||
unregister(findDirectMappedClass(getCallingClass()));
|
||||
}
|
||||
|
||||
/** Remove all native mappings for the given class.
|
||||
@@ -1433,12 +1506,7 @@ public final class Native implements Version {
|
||||
}
|
||||
}
|
||||
|
||||
String name = method.getName();
|
||||
FunctionMapper fmapper = (FunctionMapper)lib.getOptions().get(Library.OPTION_FUNCTION_MAPPER);
|
||||
if (fmapper != null) {
|
||||
name = fmapper.getFunctionName(lib, method);
|
||||
}
|
||||
Function f = lib.getFunction(name, method);
|
||||
Function f = lib.getFunction(method.getName(), method);
|
||||
try {
|
||||
handles[i] = registerMethod(cls, method.getName(),
|
||||
sig, cvt,
|
||||
@@ -1465,6 +1533,7 @@ public final class Native implements Version {
|
||||
looking them up later.
|
||||
*/
|
||||
private static void cacheOptions(Class cls, Map libOptions, Object proxy) {
|
||||
libOptions = new HashMap(libOptions);
|
||||
synchronized(libraries) {
|
||||
options.put(cls, libOptions);
|
||||
if (proxy != null) {
|
||||
@@ -1816,12 +1885,55 @@ public final class Native implements Version {
|
||||
*/
|
||||
public static native ByteBuffer getDirectByteBuffer(long addr, long length);
|
||||
|
||||
/** Indicate the desired attachment state for the current thread.
|
||||
/** Indicate whether the JVM should detach the current native thread when
|
||||
the current Java code finishes execution. Generally this is used to
|
||||
avoid detaching native threads when it is known that a given thread
|
||||
will be relatively long-lived and call back to Java code frequently.
|
||||
<p/>
|
||||
<em>Warning</em>: avoid calling {@link #detach detach(true)} on threads
|
||||
spawned by the JVM; the resulting behavior is not defined.
|
||||
This call is lightweight; it only results in an additional JNI
|
||||
crossing if the desired state changes from its last setting.
|
||||
|
||||
@throws IllegalStateException if {@link #detach detach(true)} is
|
||||
called on a thread created by the JVM.
|
||||
*/
|
||||
public static native void detach(boolean detach);
|
||||
public static void detach(boolean detach) {
|
||||
Thread thread = Thread.currentThread();
|
||||
if (detach) {
|
||||
// If a CallbackThreadInitializer was used to avoid detach,
|
||||
// we won't have put that thread into the nativeThreads map.
|
||||
// Performance is not as critical in that case, and since
|
||||
// detach is the default behavior, force an update of the detach
|
||||
// state every time. Clear the termination flag, since it's not
|
||||
// needed when the native thread is detached normally.
|
||||
nativeThreads.remove(thread);
|
||||
Pointer p = (Pointer)nativeThreadTerminationFlag.get();
|
||||
setDetachState(true, 0);
|
||||
}
|
||||
else {
|
||||
if (!nativeThreads.containsKey(thread)) {
|
||||
Pointer p = (Pointer)nativeThreadTerminationFlag.get();
|
||||
nativeThreads.put(thread, p);
|
||||
setDetachState(false, p.peer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Pointer getTerminationFlag(Thread t) {
|
||||
return (Pointer)nativeThreads.get(t);
|
||||
}
|
||||
|
||||
private static Map nativeThreads = Collections.synchronizedMap(new WeakHashMap());
|
||||
|
||||
private static ThreadLocal nativeThreadTerminationFlag =
|
||||
new ThreadLocal() {
|
||||
protected Object initialValue() {
|
||||
Memory m = new Memory(4);
|
||||
m.clear();
|
||||
return m;
|
||||
}
|
||||
};
|
||||
|
||||
private static native void setDetachState(boolean detach, long terminationFlag);
|
||||
|
||||
private static class Buffers {
|
||||
static boolean isBuffer(Class cls) {
|
||||
|
||||
@@ -58,6 +58,8 @@ import java.util.StringTokenizer;
|
||||
* resource will be extracted to <code>jna.tmpdir</code> for loading, and
|
||||
* later removed (but only if <code>jna.nounpack</code> is false or not set).
|
||||
* </ol>
|
||||
* You may set the system property <code>jna.debug_load=true</code> to make
|
||||
* JNA print the steps of its library search to the console.
|
||||
* @author Wayne Meissner, split library loading from Function.java
|
||||
* @author twall
|
||||
*/
|
||||
@@ -68,6 +70,7 @@ public class NativeLibrary {
|
||||
private final String libraryPath;
|
||||
private final Map functions = new HashMap();
|
||||
final int callFlags;
|
||||
private String encoding;
|
||||
final Map options;
|
||||
|
||||
private static final Map libraries = new HashMap();
|
||||
@@ -89,13 +92,13 @@ public class NativeLibrary {
|
||||
this.libraryPath = libraryPath;
|
||||
this.handle = handle;
|
||||
Object option = options.get(Library.OPTION_CALLING_CONVENTION);
|
||||
int callingConvention = option instanceof Integer
|
||||
? ((Integer)option).intValue() : Function.C_CONVENTION;
|
||||
int callingConvention = option instanceof Number
|
||||
? ((Number)option).intValue() : Function.C_CONVENTION;
|
||||
this.callFlags = callingConvention;
|
||||
this.options = options;
|
||||
String encoding = (String)options.get(Library.OPTION_STRING_ENCODING);
|
||||
if (encoding == null) {
|
||||
encoding = Native.getDefaultStringEncoding();
|
||||
this.encoding = (String)options.get(Library.OPTION_STRING_ENCODING);
|
||||
if (this.encoding == null) {
|
||||
this.encoding = Native.getDefaultStringEncoding();
|
||||
}
|
||||
|
||||
// Special workaround for w32 kernel32.GetLastError
|
||||
@@ -103,10 +106,10 @@ public class NativeLibrary {
|
||||
if (Platform.isWindows() && "kernel32".equals(this.libraryName.toLowerCase())) {
|
||||
synchronized(functions) {
|
||||
Function f = new Function(this, "GetLastError", Function.ALT_CONVENTION, encoding) {
|
||||
Object invoke(Object[] args, Class returnType, boolean b) {
|
||||
return new Integer(Native.getLastError());
|
||||
}
|
||||
};
|
||||
Object invoke(Object[] args, Class returnType, boolean b) {
|
||||
return new Integer(Native.getLastError());
|
||||
}
|
||||
};
|
||||
functions.put(functionKey("GetLastError", callFlags, encoding), f);
|
||||
}
|
||||
}
|
||||
@@ -122,6 +125,10 @@ public class NativeLibrary {
|
||||
}
|
||||
|
||||
private static NativeLibrary loadLibrary(String libraryName, Map options) {
|
||||
if (Native.DEBUG_LOAD) {
|
||||
System.out.println("Looking for library '" + libraryName + "'");
|
||||
}
|
||||
|
||||
boolean isAbsolutePath = new File(libraryName).isAbsolute();
|
||||
List searchPath = new LinkedList();
|
||||
int openFlags = openFlags(options);
|
||||
@@ -130,6 +137,9 @@ public class NativeLibrary {
|
||||
// attempt any library name variations
|
||||
String webstartPath = Native.getWebStartLibraryPath(libraryName);
|
||||
if (webstartPath != null) {
|
||||
if (Native.DEBUG_LOAD) {
|
||||
System.out.println("Adding web start path " + webstartPath);
|
||||
}
|
||||
searchPath.add(webstartPath);
|
||||
}
|
||||
|
||||
@@ -143,6 +153,9 @@ public class NativeLibrary {
|
||||
}
|
||||
}
|
||||
|
||||
if (Native.DEBUG_LOAD) {
|
||||
System.out.println("Adding paths from jna.library.path: " + System.getProperty("jna.library.path"));
|
||||
}
|
||||
searchPath.addAll(initPaths("jna.library.path"));
|
||||
String libraryPath = findLibraryPath(libraryName, searchPath);
|
||||
long handle = 0;
|
||||
@@ -152,15 +165,24 @@ public class NativeLibrary {
|
||||
// name if it cannot find the library.
|
||||
//
|
||||
try {
|
||||
if (Native.DEBUG_LOAD) {
|
||||
System.out.println("Trying " + libraryPath);
|
||||
}
|
||||
handle = Native.open(libraryPath, openFlags);
|
||||
}
|
||||
catch(UnsatisfiedLinkError e) {
|
||||
// Add the system paths back for all fallback searching
|
||||
if (Native.DEBUG_LOAD) {
|
||||
System.out.println("Adding system paths: " + librarySearchPath);
|
||||
}
|
||||
searchPath.addAll(librarySearchPath);
|
||||
}
|
||||
try {
|
||||
if (handle == 0) {
|
||||
libraryPath = findLibraryPath(libraryName, searchPath);
|
||||
if (Native.DEBUG_LOAD) {
|
||||
System.out.println("Trying " + libraryPath);
|
||||
}
|
||||
handle = Native.open(libraryPath, openFlags);
|
||||
if (handle == 0) {
|
||||
throw new UnsatisfiedLinkError("Failed to load library '" + libraryName + "'");
|
||||
@@ -173,6 +195,9 @@ public class NativeLibrary {
|
||||
// path, not found in any properties
|
||||
if (Platform.isAndroid()) {
|
||||
try {
|
||||
if (Native.DEBUG_LOAD) {
|
||||
System.out.println("Preload (via System.loadLibrary) " + libraryName);
|
||||
}
|
||||
System.loadLibrary(libraryName);
|
||||
handle = Native.open(libraryPath, openFlags);
|
||||
}
|
||||
@@ -182,9 +207,15 @@ public class NativeLibrary {
|
||||
//
|
||||
// Failed to load the library normally - try to match libfoo.so.*
|
||||
//
|
||||
if (Native.DEBUG_LOAD) {
|
||||
System.out.println("Looking for version variants");
|
||||
}
|
||||
libraryPath = matchLibrary(libraryName, searchPath);
|
||||
if (libraryPath != null) {
|
||||
try {
|
||||
if (Native.DEBUG_LOAD) {
|
||||
System.out.println("Trying " + libraryPath);
|
||||
}
|
||||
try {
|
||||
handle = Native.open(libraryPath, openFlags);
|
||||
}
|
||||
catch(UnsatisfiedLinkError e2) { e = e2; }
|
||||
@@ -193,9 +224,15 @@ public class NativeLibrary {
|
||||
// Search framework libraries on OS X
|
||||
else if (Platform.isMac()
|
||||
&& !libraryName.endsWith(".dylib")) {
|
||||
if (Native.DEBUG_LOAD) {
|
||||
System.out.println("Looking for matching frameworks");
|
||||
}
|
||||
libraryPath = matchFramework(libraryName);
|
||||
if (libraryPath != null) {
|
||||
try {
|
||||
if (Native.DEBUG_LOAD) {
|
||||
System.out.println("Trying " + libraryPath);
|
||||
}
|
||||
handle = Native.open(libraryPath, openFlags);
|
||||
}
|
||||
catch(UnsatisfiedLinkError e2) { e = e2; }
|
||||
@@ -203,9 +240,17 @@ public class NativeLibrary {
|
||||
}
|
||||
// Try the same library with a "lib" prefix
|
||||
else if (Platform.isWindows() && !isAbsolutePath) {
|
||||
if (Native.DEBUG_LOAD) {
|
||||
System.out.println("Looking for lib- prefix");
|
||||
}
|
||||
libraryPath = findLibraryPath("lib" + libraryName, searchPath);
|
||||
try { handle = Native.open(libraryPath, openFlags); }
|
||||
catch(UnsatisfiedLinkError e2) { e = e2; }
|
||||
if (libraryPath != null) {
|
||||
if (Native.DEBUG_LOAD) {
|
||||
System.out.println("Trying " + libraryPath);
|
||||
}
|
||||
try { handle = Native.open(libraryPath, openFlags); }
|
||||
catch(UnsatisfiedLinkError e2) { e = e2; }
|
||||
}
|
||||
}
|
||||
// As a last resort, try to extract the library from the class
|
||||
// path, using the current context class loader.
|
||||
@@ -213,6 +258,7 @@ public class NativeLibrary {
|
||||
try {
|
||||
File embedded = Native.extractFromResourcePath(libraryName, (ClassLoader)options.get(Library.OPTION_CLASSLOADER));
|
||||
handle = Native.open(embedded.getAbsolutePath());
|
||||
libraryPath = embedded.getAbsolutePath();
|
||||
// Don't leave temporary files around
|
||||
if (Native.isUnpacked(embedded)) {
|
||||
Native.deleteLibrary(embedded);
|
||||
@@ -226,6 +272,9 @@ public class NativeLibrary {
|
||||
+ e.getMessage());
|
||||
}
|
||||
}
|
||||
if (Native.DEBUG_LOAD) {
|
||||
System.out.println("Found library '" + libraryName + "' at " + libraryPath);
|
||||
}
|
||||
return new NativeLibrary(libraryName, libraryPath, handle, options);
|
||||
}
|
||||
|
||||
@@ -382,7 +431,8 @@ public class NativeLibrary {
|
||||
|
||||
/**
|
||||
* Add a path to search for the specified library, ahead of any system
|
||||
* paths.
|
||||
* paths. This is similar to setting <code>jna.library.path</code>, but
|
||||
* only extends the search path for a single library.
|
||||
*
|
||||
* @param libraryName The name of the library to use the path for
|
||||
* @param path The path to use when trying to load the library
|
||||
@@ -421,12 +471,24 @@ public class NativeLibrary {
|
||||
* function from the library.
|
||||
*
|
||||
* @param name
|
||||
* Name of the native function to be linked with
|
||||
* Name of the native function to be linked with. Uses a
|
||||
* function mapper option if one was provided to
|
||||
* transform the name.
|
||||
* @param method
|
||||
* Method to which the native function is to be mapped
|
||||
* @throws UnsatisfiedLinkError if the function is not found
|
||||
*/
|
||||
Function getFunction(String name, Method method) {
|
||||
FunctionMapper mapper = (FunctionMapper)
|
||||
options.get(Library.OPTION_FUNCTION_MAPPER);
|
||||
if (mapper != null) {
|
||||
name = mapper.getFunctionName(this, method);
|
||||
}
|
||||
// If there's native method profiler prefix, strip it
|
||||
String prefix = System.getProperty("jna.profiler.prefix", "$$YJP$$");
|
||||
if (name.startsWith(prefix)) {
|
||||
name = name.substring(prefix.length());
|
||||
}
|
||||
int flags = this.callFlags;
|
||||
Class[] etypes = method.getExceptionTypes();
|
||||
for (int i=0;i < etypes.length;i++) {
|
||||
@@ -448,7 +510,7 @@ public class NativeLibrary {
|
||||
* @throws UnsatisfiedLinkError if the function is not found
|
||||
*/
|
||||
public Function getFunction(String functionName, int callFlags) {
|
||||
return getFunction(functionName, callFlags, Native.getDefaultStringEncoding());
|
||||
return getFunction(functionName, callFlags, encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -687,13 +749,13 @@ public class NativeLibrary {
|
||||
searchPath = Arrays.asList(new String[] { lib.getParent() });
|
||||
}
|
||||
FilenameFilter filter = new FilenameFilter() {
|
||||
public boolean accept(File dir, String filename) {
|
||||
return (filename.startsWith("lib" + libName + ".so")
|
||||
|| (filename.startsWith(libName + ".so")
|
||||
&& libName.startsWith("lib")))
|
||||
&& isVersionedName(filename);
|
||||
}
|
||||
};
|
||||
public boolean accept(File dir, String filename) {
|
||||
return (filename.startsWith("lib" + libName + ".so")
|
||||
|| (filename.startsWith(libName + ".so")
|
||||
&& libName.startsWith("lib")))
|
||||
&& isVersionedName(filename);
|
||||
}
|
||||
};
|
||||
|
||||
List matches = new LinkedList();
|
||||
for (Iterator it = searchPath.iterator(); it.hasNext(); ) {
|
||||
|
||||
@@ -262,10 +262,16 @@ public final class Platform {
|
||||
osPrefix = "sunos-" + arch;
|
||||
break;
|
||||
case Platform.FREEBSD:
|
||||
osPrefix = "freebsd-" + arch;
|
||||
break;
|
||||
case Platform.OPENBSD:
|
||||
osPrefix = "openbsd-" + arch;
|
||||
break;
|
||||
case Platform.NETBSD:
|
||||
osPrefix = "netbsd-" + arch;
|
||||
break;
|
||||
case Platform.KFREEBSD:
|
||||
osPrefix = "bsd-" + arch;
|
||||
osPrefix = "kfreebsd-" + arch;
|
||||
break;
|
||||
default:
|
||||
osPrefix = name.toLowerCase();
|
||||
|
||||
@@ -1207,7 +1207,7 @@ v * @param wide whether to convert from a wide or standard C string
|
||||
* <code>char</code> using the encoding indicated by {@link
|
||||
* Native#getDefaultStringEncoding()}.
|
||||
*
|
||||
* @deprecated use {@link setWideString(long,String)} instead.
|
||||
* @deprecated use {@link #setWideString(long,String)} instead.
|
||||
*/
|
||||
public void setString(long offset, String value, boolean wide) {
|
||||
if (wide) {
|
||||
@@ -1239,7 +1239,7 @@ v * @param wide whether to convert from a wide or standard C string
|
||||
* @param value <code>WString</code> value to set
|
||||
*/
|
||||
public void setString(long offset, WString value) {
|
||||
setWideString(offset, value.toString());
|
||||
setWideString(offset, value == null ? null : value.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1308,6 +1308,12 @@ v * @param wide whether to convert from a wide or standard C string
|
||||
private static class Opaque extends Pointer {
|
||||
private Opaque(long peer) { super(peer); }
|
||||
private final String MSG = "This pointer is opaque: " + this;
|
||||
public Pointer share(long offset, long size) {
|
||||
throw new UnsupportedOperationException(MSG);
|
||||
}
|
||||
public void clear(long size) {
|
||||
throw new UnsupportedOperationException(MSG);
|
||||
}
|
||||
public long indexOf(long offset, byte value) {
|
||||
throw new UnsupportedOperationException(MSG);
|
||||
}
|
||||
@@ -1332,6 +1338,9 @@ v * @param wide whether to convert from a wide or standard C string
|
||||
public void read(long bOff, double[] buf, int index, int length) {
|
||||
throw new UnsupportedOperationException(MSG);
|
||||
}
|
||||
public void read(long bOff, Pointer[] buf, int index, int length) {
|
||||
throw new UnsupportedOperationException(MSG);
|
||||
}
|
||||
public void write(long bOff, byte[] buf, int index, int length) {
|
||||
throw new UnsupportedOperationException(MSG);
|
||||
}
|
||||
@@ -1353,6 +1362,12 @@ v * @param wide whether to convert from a wide or standard C string
|
||||
public void write(long bOff, double[] buf, int index, int length) {
|
||||
throw new UnsupportedOperationException(MSG);
|
||||
}
|
||||
public void write(long bOff, Pointer[] buf, int index, int length) {
|
||||
throw new UnsupportedOperationException(MSG);
|
||||
}
|
||||
public ByteBuffer getByteBuffer(long offset, long length) {
|
||||
throw new UnsupportedOperationException(MSG);
|
||||
}
|
||||
public byte getByte(long bOff) {
|
||||
throw new UnsupportedOperationException(MSG);
|
||||
}
|
||||
@@ -1413,8 +1428,11 @@ v * @param wide whether to convert from a wide or standard C string
|
||||
public void setWideString(long offset, String value) {
|
||||
throw new UnsupportedOperationException(MSG);
|
||||
}
|
||||
public void setMemory(long offset, long size, byte value) {
|
||||
throw new UnsupportedOperationException(MSG);
|
||||
}
|
||||
public String toString() {
|
||||
return "opaque@0x" + Long.toHexString(peer);
|
||||
return "const@0x" + Long.toHexString(peer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,10 +106,6 @@ public abstract class Structure {
|
||||
*/
|
||||
public interface ByReference { }
|
||||
|
||||
static final boolean isPPC = Platform.isPPC();
|
||||
static final boolean isSPARC = Platform.isSPARC();
|
||||
static final boolean isARM = Platform.isARM();
|
||||
|
||||
/** Use the platform default alignment. */
|
||||
public static final int ALIGN_DEFAULT = 0;
|
||||
/** No alignment, place all fields on nearest 1-byte boundary */
|
||||
@@ -126,12 +122,6 @@ public abstract class Structure {
|
||||
/** Align to an 8-byte boundary. */
|
||||
//public static final int ALIGN_8 = 6;
|
||||
|
||||
static final int MAX_GNUC_ALIGNMENT =
|
||||
isSPARC
|
||||
|| ((isPPC || isARM)
|
||||
&& (Platform.isLinux() || Platform.isAndroid()))
|
||||
|| Platform.isAIX()
|
||||
? 8 : Native.LONG_SIZE;
|
||||
protected static final int CALCULATE_SIZE = -1;
|
||||
static final Map layoutInfo = new WeakHashMap();
|
||||
static final Map fieldOrder = new WeakHashMap();
|
||||
@@ -217,10 +207,7 @@ public abstract class Structure {
|
||||
*/
|
||||
private void initializeTypeMapper(TypeMapper mapper) {
|
||||
if (mapper == null) {
|
||||
Class declaring = getClass().getDeclaringClass();
|
||||
if (declaring != null) {
|
||||
mapper = Native.getTypeMapper(declaring);
|
||||
}
|
||||
mapper = Native.getTypeMapper(getClass());
|
||||
}
|
||||
this.typeMapper = mapper;
|
||||
layoutChanged();
|
||||
@@ -261,9 +248,7 @@ public abstract class Structure {
|
||||
protected void setAlignType(int alignType) {
|
||||
this.alignType = alignType;
|
||||
if (alignType == ALIGN_DEFAULT) {
|
||||
Class declaring = getClass().getDeclaringClass();
|
||||
if (declaring != null)
|
||||
alignType = Native.getStructureAlignment(declaring);
|
||||
alignType = Native.getStructureAlignment(getClass());
|
||||
if (alignType == ALIGN_DEFAULT) {
|
||||
if (Platform.isWindows())
|
||||
alignType = ALIGN_MSVC;
|
||||
@@ -621,12 +606,16 @@ public abstract class Structure {
|
||||
Structure s1 = (Structure)reading().get(address);
|
||||
if (s1 != null && type.equals(s1.getClass())) {
|
||||
s = s1;
|
||||
s.autoRead();
|
||||
}
|
||||
else {
|
||||
s = newInstance(type, address);
|
||||
s.conditionalAutoRead();
|
||||
}
|
||||
}
|
||||
s.autoRead();
|
||||
else {
|
||||
s.autoRead();
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
@@ -635,7 +624,7 @@ public abstract class Structure {
|
||||
* updated from the contents of native memory.
|
||||
*/
|
||||
// TODO: make overridable method with calculated native type, offset, etc
|
||||
Object readField(StructField structField) {
|
||||
protected Object readField(StructField structField) {
|
||||
|
||||
// Get the offset of the field
|
||||
int offset = structField.offset;
|
||||
@@ -745,7 +734,7 @@ public abstract class Structure {
|
||||
writeField(structField);
|
||||
}
|
||||
|
||||
void writeField(StructField structField) {
|
||||
protected void writeField(StructField structField) {
|
||||
|
||||
if (structField.isReadOnly)
|
||||
return;
|
||||
@@ -1154,6 +1143,9 @@ public abstract class Structure {
|
||||
}
|
||||
|
||||
// Align fields as appropriate
|
||||
if (fieldAlignment == 0) {
|
||||
throw new Error("Field alignment is zero for field '" + structField.name + "' within " + getClass());
|
||||
}
|
||||
info.alignment = Math.max(info.alignment, fieldAlignment);
|
||||
if ((calculatedSize % fieldAlignment) != 0) {
|
||||
calculatedSize += fieldAlignment - (calculatedSize % fieldAlignment);
|
||||
@@ -1312,10 +1304,10 @@ public abstract class Structure {
|
||||
else if (actualAlignType == 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 (!isFirstElement || !(Platform.isMac() && isPPC)) {
|
||||
alignment = Math.min(MAX_GNUC_ALIGNMENT, alignment);
|
||||
if (!isFirstElement || !(Platform.isMac() && Platform.isPPC())) {
|
||||
alignment = Math.min(Native.MAX_ALIGNMENT, alignment);
|
||||
}
|
||||
if (!isFirstElement && Platform.isAIX() && (type.getName().equals("double"))) {
|
||||
if (!isFirstElement && Platform.isAIX() && (type == double.class || type == Double.class)) {
|
||||
alignment = 4;
|
||||
}
|
||||
}
|
||||
@@ -1577,15 +1569,21 @@ public abstract class Structure {
|
||||
}
|
||||
|
||||
/** Called from native code only; same as {@link
|
||||
* #newInstance(Class,Pointer)}, except that it additionally performs
|
||||
* #newInstance(Class,Pointer)}, except that it additionally calls
|
||||
* {@link #conditionalAutoRead()}.
|
||||
*/
|
||||
private static Structure newInstance(Class type, long init) throws IllegalArgumentException {
|
||||
Structure s = newInstance(type, init == 0 ? PLACEHOLDER_MEMORY : new Pointer(init));
|
||||
if (init != 0) {
|
||||
s.conditionalAutoRead();
|
||||
private static Structure newInstance(Class type, long init) {
|
||||
try {
|
||||
Structure s = newInstance(type, init == 0 ? PLACEHOLDER_MEMORY : new Pointer(init));
|
||||
if (init != 0) {
|
||||
s.conditionalAutoRead();
|
||||
}
|
||||
return s;
|
||||
}
|
||||
catch(Throwable e) {
|
||||
System.err.println("JNA: Error creating structure: " + e);
|
||||
return null;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/** Create a new Structure instance of the given type, initialized with
|
||||
@@ -1665,7 +1663,7 @@ public abstract class Structure {
|
||||
return null;
|
||||
}
|
||||
|
||||
static class StructField extends Object {
|
||||
protected static class StructField extends Object {
|
||||
public String name;
|
||||
public Class type;
|
||||
public Field field;
|
||||
|
||||
@@ -191,7 +191,7 @@ public abstract class Union extends Structure {
|
||||
}
|
||||
|
||||
/** Only the currently selected field will be written. */
|
||||
void writeField(StructField field) {
|
||||
protected void writeField(StructField field) {
|
||||
if (field == activeField) {
|
||||
super.writeField(field);
|
||||
}
|
||||
@@ -201,7 +201,7 @@ public abstract class Union extends Structure {
|
||||
* selected. Structures may contain pointer-based fields which can
|
||||
* crash the VM if not properly initialized.
|
||||
*/
|
||||
Object readField(StructField field) {
|
||||
protected Object readField(StructField field) {
|
||||
if (field == activeField
|
||||
|| (!Structure.class.isAssignableFrom(field.type)
|
||||
&& !String.class.isAssignableFrom(field.type)
|
||||
@@ -209,8 +209,9 @@ public abstract class Union extends Structure {
|
||||
return super.readField(field);
|
||||
}
|
||||
// Field not accessible
|
||||
// TODO: read structure, to the extent possible; need a "recursive"
|
||||
// flag to "read" to indicate we want to avoid pointer-based fields
|
||||
// TODO: read by-value structures, to the extent possible; need a
|
||||
// "read cautiously" method to "read" to indicate we want to avoid
|
||||
// pointer-based fields
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -406,6 +406,29 @@ public class ArgumentsMarshalTest extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public void testRejectIncompatibleStructureArrayArgument() {
|
||||
TestLibrary.CheckFieldAlignment s1 = new TestLibrary.CheckFieldAlignment.ByReference();
|
||||
TestLibrary.CheckFieldAlignment[] autoArray = (TestLibrary.CheckFieldAlignment[])s1.toArray(3);
|
||||
try {
|
||||
lib.modifyStructureArray(autoArray, autoArray.length);
|
||||
}
|
||||
catch(IllegalArgumentException e) {
|
||||
}
|
||||
TestLibrary.CheckFieldAlignment.ByReference[] byRefArray =
|
||||
(TestLibrary.CheckFieldAlignment.ByReference[])s1.toArray(3);
|
||||
try {
|
||||
lib.modifyStructureArray(byRefArray, byRefArray.length);
|
||||
}
|
||||
catch(IllegalArgumentException e) {
|
||||
}
|
||||
TestLibrary.CheckFieldAlignment[] arrayWithRefElements = { autoArray[0], autoArray[1], autoArray[2] };
|
||||
try {
|
||||
lib.modifyStructureArray(arrayWithRefElements, arrayWithRefElements.length);
|
||||
}
|
||||
catch(IllegalArgumentException e) {
|
||||
}
|
||||
}
|
||||
|
||||
/** When passing an array of <code>struct*</code> to native, be sure to
|
||||
invoke <code>Structure.write()</code> on each of the elements. */
|
||||
public void testWriteStructureByReferenceArrayArgumentMemory() {
|
||||
@@ -482,7 +505,7 @@ public class ArgumentsMarshalTest extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public void testInvalidArgument() {
|
||||
public void testUnsupportedJavaObjectArgument() {
|
||||
try {
|
||||
lib.returnBooleanArgument(this);
|
||||
fail("Unsupported Java objects should be rejected");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2007-2008 Timothy Wall, All Rights Reserved
|
||||
/* Copyright (c) 2007-2013 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
|
||||
@@ -13,6 +13,7 @@
|
||||
package com.sun.jna;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.PrintStream;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Arrays;
|
||||
@@ -28,19 +29,23 @@ import junit.framework.TestCase;
|
||||
import com.sun.jna.Callback.UncaughtExceptionHandler;
|
||||
import com.sun.jna.CallbacksTest.TestLibrary.CbCallback;
|
||||
import com.sun.jna.ptr.IntByReference;
|
||||
import com.sun.jna.ptr.PointerByReference;
|
||||
import com.sun.jna.win32.W32APIOptions;
|
||||
|
||||
/** Exercise callback-related functionality.
|
||||
*
|
||||
* @author twall@users.sf.net
|
||||
*/
|
||||
//@SuppressWarnings("unused")
|
||||
public class CallbacksTest extends TestCase {
|
||||
public class CallbacksTest extends TestCase implements Paths {
|
||||
|
||||
private static final String UNICODE = "[\u0444]";
|
||||
|
||||
private static final double DOUBLE_MAGIC = -118.625d;
|
||||
private static final float FLOAT_MAGIC = -118.625f;
|
||||
|
||||
private static final int THREAD_TIMEOUT = 5000;
|
||||
|
||||
public static class SmallTestStructure extends Structure {
|
||||
public double value;
|
||||
public static int allocations = 0;
|
||||
@@ -86,7 +91,7 @@ public class CallbacksTest extends TestCase {
|
||||
void callback();
|
||||
}
|
||||
void callVoidCallback(VoidCallback c);
|
||||
void callVoidCallbackThreaded(VoidCallback c, int count, int ms);
|
||||
void callVoidCallbackThreaded(VoidCallback c, int count, int ms, String name);
|
||||
interface VoidCallbackCustom extends Callback {
|
||||
void customMethodName();
|
||||
}
|
||||
@@ -184,6 +189,7 @@ public class CallbacksTest extends TestCase {
|
||||
}
|
||||
|
||||
TestLibrary lib;
|
||||
|
||||
protected void setUp() {
|
||||
lib = (TestLibrary)Native.loadLibrary("testlib", TestLibrary.class);
|
||||
}
|
||||
@@ -232,9 +238,20 @@ public class CallbacksTest extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public void testThrowOnMultiplyMappedCallback() {
|
||||
try {
|
||||
Pointer p = new Pointer(getName().hashCode());
|
||||
CallbackReference.getCallback(TestLibrary.VoidCallback.class, p);
|
||||
CallbackReference.getCallback(TestLibrary.ByteCallback.class, p);
|
||||
fail("Multiply-mapped callback should fail");
|
||||
}
|
||||
catch(IllegalStateException e) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testNoMethodCallback() {
|
||||
try {
|
||||
CallbackReference.getCallback(TestLibrary.NoMethodCallback.class, new Pointer(1));
|
||||
CallbackReference.getCallback(TestLibrary.NoMethodCallback.class, new Pointer(getName().hashCode()));
|
||||
fail("Callback with no callback method should fail");
|
||||
}
|
||||
catch(IllegalArgumentException e) {
|
||||
@@ -242,12 +259,12 @@ public class CallbacksTest extends TestCase {
|
||||
}
|
||||
|
||||
public void testCustomMethodCallback() {
|
||||
CallbackReference.getCallback(TestLibrary.CustomMethodCallback.class, new Pointer(1));
|
||||
CallbackReference.getCallback(TestLibrary.CustomMethodCallback.class, new Pointer(getName().hashCode()));
|
||||
}
|
||||
|
||||
public void testTooManyMethodsCallback() {
|
||||
try {
|
||||
CallbackReference.getCallback(TestLibrary.TooManyMethodsCallback.class, new Pointer(1));
|
||||
CallbackReference.getCallback(TestLibrary.TooManyMethodsCallback.class, new Pointer(getName().hashCode()));
|
||||
fail("Callback lookup with too many methods should fail");
|
||||
}
|
||||
catch(IllegalArgumentException e) {
|
||||
@@ -255,19 +272,19 @@ public class CallbacksTest extends TestCase {
|
||||
}
|
||||
|
||||
public void testMultipleMethodsCallback() {
|
||||
CallbackReference.getCallback(TestLibrary.MultipleMethodsCallback.class, new Pointer(1));
|
||||
CallbackReference.getCallback(TestLibrary.MultipleMethodsCallback.class, new Pointer(getName().hashCode()));
|
||||
}
|
||||
|
||||
public void testNativeFunctionPointerStringValue() {
|
||||
Callback cb = CallbackReference.getCallback(TestLibrary.VoidCallback.class, new Pointer(1));
|
||||
Callback cb = CallbackReference.getCallback(TestLibrary.VoidCallback.class, new Pointer(getName().hashCode()));
|
||||
Class cls = CallbackReference.findCallbackClass(cb.getClass());
|
||||
assertTrue("toString should include Java Callback type: " + cb + " ("
|
||||
+ cls + ")", cb.toString().indexOf(cls.getName()) != -1);
|
||||
}
|
||||
|
||||
public void testLookupSameCallback() {
|
||||
Callback cb = CallbackReference.getCallback(TestLibrary.VoidCallback.class, new Pointer(1));
|
||||
Callback cb2 = CallbackReference.getCallback(TestLibrary.VoidCallback.class, new Pointer(1));
|
||||
Callback cb = CallbackReference.getCallback(TestLibrary.VoidCallback.class, new Pointer(getName().hashCode()));
|
||||
Callback cb2 = CallbackReference.getCallback(TestLibrary.VoidCallback.class, new Pointer(getName().hashCode()));
|
||||
|
||||
assertEquals("Callback lookups for same pointer should return same Callback object", cb, cb2);
|
||||
}
|
||||
@@ -883,6 +900,24 @@ public class CallbacksTest extends TestCase {
|
||||
assertTrue("Callback with custom method name not called", called[0]);
|
||||
}
|
||||
|
||||
public void testDisallowDetachFromJVMThread() {
|
||||
final boolean[] called = {false};
|
||||
final boolean[] exceptionThrown = {true};
|
||||
TestLibrary.VoidCallback cb = new TestLibrary.VoidCallback() {
|
||||
public void callback() {
|
||||
called[0] = true;
|
||||
try {
|
||||
Native.detach(true);
|
||||
}
|
||||
catch(IllegalStateException e) {
|
||||
}
|
||||
}
|
||||
};
|
||||
lib.callVoidCallback(cb);
|
||||
assertTrue("Callback not called", called[0]);
|
||||
assertTrue("Native.detach(true) should throw IllegalStateException when called from JVM thread", exceptionThrown[0]);
|
||||
}
|
||||
|
||||
public void testCustomCallbackVariedInheritance() {
|
||||
final boolean[] called = {false};
|
||||
TestLibrary.VoidCallbackCustom cb =
|
||||
@@ -995,15 +1030,22 @@ public class CallbacksTest extends TestCase {
|
||||
CallbackThreadInitializer cti,
|
||||
int repeat, int sleepms,
|
||||
int[] called) throws Exception {
|
||||
callThreadedCallback(cb, cti, repeat, sleepms, called, repeat);
|
||||
}
|
||||
|
||||
protected void callThreadedCallback(TestLibrary.VoidCallback cb,
|
||||
CallbackThreadInitializer cti,
|
||||
int repeat, int sleepms,
|
||||
int[] called, int returnAfter) throws Exception {
|
||||
if (cti != null) {
|
||||
Native.setCallbackThreadInitializer(cb, cti);
|
||||
}
|
||||
lib.callVoidCallbackThreaded(cb, repeat, sleepms);
|
||||
lib.callVoidCallbackThreaded(cb, repeat, sleepms, getName());
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
while (called[0] < repeat) {
|
||||
while (called[0] < returnAfter) {
|
||||
Thread.sleep(10);
|
||||
if (System.currentTimeMillis() - start > 5000) {
|
||||
if (System.currentTimeMillis() - start > THREAD_TIMEOUT) {
|
||||
fail("Timed out waiting for callback, invoked " + called[0] + " times so far");
|
||||
}
|
||||
}
|
||||
@@ -1063,7 +1105,7 @@ public class CallbacksTest extends TestCase {
|
||||
}
|
||||
}
|
||||
};
|
||||
callThreadedCallback(cb, init, 1, 5000, called);
|
||||
callThreadedCallback(cb, init, 2, 2000, called, 1);
|
||||
|
||||
assertTrue("Callback thread not attached as daemon", daemon[0]);
|
||||
assertEquals("Callback thread name not applied", tname, name[0]);
|
||||
@@ -1073,6 +1115,22 @@ public class CallbacksTest extends TestCase {
|
||||
throw new Error("VM incorrectly reports Thread.isAlive() == false within callback");
|
||||
}
|
||||
assertTrue("Thread should still be alive", t[0].isAlive());
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
while (called[0] < 2) {
|
||||
Thread.sleep(10);
|
||||
if (System.currentTimeMillis() - start > THREAD_TIMEOUT) {
|
||||
fail("Timed out waiting for second callback invocation, which indicates detach");
|
||||
}
|
||||
}
|
||||
|
||||
start = System.currentTimeMillis();
|
||||
while (t[0].isAlive()) {
|
||||
Thread.sleep(10);
|
||||
if (System.currentTimeMillis() - start > THREAD_TIMEOUT) {
|
||||
fail("Timed out waiting for thread to detach and terminate");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Detach preference is indicated by the initializer. Thread is attached
|
||||
@@ -1084,7 +1142,7 @@ public class CallbacksTest extends TestCase {
|
||||
final int COUNT = 5;
|
||||
CallbackThreadInitializer init = new CallbackThreadInitializer(true, false) {
|
||||
public String getName(Callback cb) {
|
||||
return CallbacksTest.this.getName() + " thread " + called[0];
|
||||
return "Test thread (native) for " + CallbacksTest.this.getName() + " (call count: " + called[0] + ")";
|
||||
}
|
||||
};
|
||||
TestLibrary.VoidCallback cb = new TestLibrary.VoidCallback() {
|
||||
@@ -1100,31 +1158,47 @@ public class CallbacksTest extends TestCase {
|
||||
}
|
||||
|
||||
// Thread object is never GC'd on linux-amd64 and darwin-amd64 (w/openjdk7)
|
||||
public void testAttachedThreadCleanupOnExit() throws Exception {
|
||||
public void testCleanupUndetachedThreadOnThreadExit() throws Exception {
|
||||
final Set threads = new HashSet();
|
||||
final int[] called = { 0 };
|
||||
TestLibrary.VoidCallback cb = new TestLibrary.VoidCallback() {
|
||||
public void callback() {
|
||||
threads.add(new WeakReference(Thread.currentThread()));
|
||||
if (++called[0] == 1) {
|
||||
Thread.currentThread().setName("Thread to be cleaned up");
|
||||
Thread.currentThread().setName(getName() + " (Thread to be cleaned up)");
|
||||
}
|
||||
Native.detach(false);
|
||||
Native.detach(false);
|
||||
}
|
||||
};
|
||||
CallbackThreadInitializer asDaemon = new CallbackThreadInitializer(true);
|
||||
callThreadedCallback(cb, asDaemon, 1, 0, called);
|
||||
while (threads.size() == 0) {
|
||||
// Always attach as daemon to ensure tests will exit
|
||||
CallbackThreadInitializer asDaemon = new CallbackThreadInitializer(true) {
|
||||
public String getName(Callback cb) {
|
||||
return "Test thread (native) for " + CallbacksTest.this.getName();
|
||||
}
|
||||
};
|
||||
callThreadedCallback(cb, asDaemon, 2, 100, called);
|
||||
// Wait for it to start up
|
||||
while (threads.size() == 0 && called[0] == 0) {
|
||||
Thread.sleep(10);
|
||||
}
|
||||
long start = System.currentTimeMillis();
|
||||
WeakReference ref = (WeakReference)threads.iterator().next();
|
||||
|
||||
while (ref.get() != null) {
|
||||
System.gc();
|
||||
Thread.sleep(10);
|
||||
if (System.currentTimeMillis() - start > 10000) {
|
||||
Thread.sleep(100);
|
||||
Thread[] remaining = new Thread[Thread.activeCount()];
|
||||
Thread.enumerate(remaining);
|
||||
if (System.currentTimeMillis() - start > THREAD_TIMEOUT) {
|
||||
Thread t = (Thread)ref.get();
|
||||
fail("Timed out waiting for attached thread to be detached on exit and disposed: " + t + " alive: " + t.isAlive() + " daemon " + t.isDaemon());
|
||||
Pointer terminationFlag = Native.getTerminationFlag(t);
|
||||
assertNotNull("Native thread termination flag is missing", terminationFlag);
|
||||
if (terminationFlag.getInt(0) == 0) {
|
||||
fail("Timed out waiting for native attached thread to be GC'd: " + t + " alive: "
|
||||
+ t.isAlive() + " daemon: " + t.isDaemon() + "\n" + Arrays.asList(remaining));
|
||||
}
|
||||
System.err.println("Warning: JVM did not GC Thread mapping after native thread terminated");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1142,6 +1216,7 @@ public class CallbacksTest extends TestCase {
|
||||
// detach on final invocation
|
||||
int count = called[0] + 1;
|
||||
if (count == 1) {
|
||||
Thread.currentThread().setName("Native thread for " + getName());
|
||||
Native.detach(false);
|
||||
}
|
||||
else if (count == COUNT) {
|
||||
@@ -1152,25 +1227,16 @@ public class CallbacksTest extends TestCase {
|
||||
};
|
||||
callThreadedCallback(cb, null, COUNT, 100, called);
|
||||
|
||||
assertEquals("Multiple callbacks in the same native thread should use the same Thread mapping: " + threads,
|
||||
1, threads.size());
|
||||
assertEquals("Multiple callbacks in the same native thread should use the same Thread mapping: "
|
||||
+ threads, 1, threads.size());
|
||||
Thread thread = (Thread)threads.iterator().next();
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
while (thread.isAlive()) {
|
||||
System.gc();
|
||||
Thread.sleep(10);
|
||||
if (System.currentTimeMillis() - start > 5000) {
|
||||
PrintStream ps = System.err;
|
||||
ByteArrayOutputStream s = new ByteArrayOutputStream();
|
||||
System.setErr(new PrintStream(s));
|
||||
try {
|
||||
thread.dumpStack();
|
||||
}
|
||||
finally {
|
||||
System.setErr(ps);
|
||||
}
|
||||
fail("Timed out waiting for callback thread " + thread + " to die: " + s);
|
||||
if (System.currentTimeMillis() - start > THREAD_TIMEOUT) {
|
||||
fail("Timed out waiting for native thread " + thread + " to finish");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1191,6 +1257,26 @@ public class CallbacksTest extends TestCase {
|
||||
lib.callVoidCallback(cb);
|
||||
assertTrue("Callback not called", called[0]);
|
||||
|
||||
// Check module information
|
||||
Pointer fp = CallbackReference.getFunctionPointer(cb);
|
||||
NativeLibrary kernel32 = NativeLibrary.getInstance("kernel32", W32APIOptions.DEFAULT_OPTIONS);
|
||||
Function f = kernel32.getFunction("GetModuleHandleExW");
|
||||
final int GET_MODULE_HANDLE_FROM_ADDRESS = 0x4;
|
||||
PointerByReference pref = new PointerByReference();
|
||||
int result = f.invokeInt(new Object[] { new Integer(GET_MODULE_HANDLE_FROM_ADDRESS), fp, pref });
|
||||
assertTrue("GetModuleHandleEx(fptr) failed: " + Native.getLastError(), result != 0);
|
||||
|
||||
f = kernel32.getFunction("GetModuleFileNameW");
|
||||
char[] buf = new char[1024];
|
||||
result = f.invokeInt(new Object[] { pref.getValue(), buf, buf.length });
|
||||
assertTrue("GetModuleFileName(fptr) failed: " + Native.getLastError(), result != 0);
|
||||
|
||||
f = kernel32.getFunction("GetModuleHandleW");
|
||||
Pointer handle = f.invokePointer(new Object[] { Native.jnidispatchPath != null ? Native.jnidispatchPath : "jnidispatch" });
|
||||
assertNotNull("GetModuleHandle(\"jnidispatch\") failed: " + Native.getLastError(), handle);
|
||||
assertEquals("Wrong module HANDLE for DLL function pointer", handle, pref.getValue());
|
||||
|
||||
// Check slot re-use
|
||||
Map refs = new WeakHashMap(callbackCache());
|
||||
assertTrue("Callback not cached", refs.containsKey(cb));
|
||||
CallbackReference ref = (CallbackReference)refs.get(cb);
|
||||
@@ -1226,7 +1312,8 @@ public class CallbacksTest extends TestCase {
|
||||
cbstruct = ref.cbstruct;
|
||||
|
||||
assertTrue("Callback not called", called[0]);
|
||||
assertEquals("Same (in-DLL) address should be re-used for DLL callbacks", first_fptr, cbstruct.getPointer(0));
|
||||
assertEquals("Same (in-DLL) address should be re-used for DLL callbacks after callback is GCd",
|
||||
first_fptr, cbstruct.getPointer(0));
|
||||
}
|
||||
|
||||
public void testThrowOutOfMemoryWhenDLLCallbacksExhausted() throws Exception {
|
||||
|
||||
@@ -124,6 +124,7 @@ public class DirectArgumentsMarshalTest extends ArgumentsMarshalTest {
|
||||
public void testWriteStructureArrayArgumentMemory() { }
|
||||
public void testUninitializedStructureArrayArgument() { }
|
||||
public void testRejectNoncontiguousStructureArrayArgument() { }
|
||||
public void testRejectIncompatibleStructureArrayArgument() { }
|
||||
public void testWideStringArrayArgument() { }
|
||||
public void testPointerArrayArgument() { }
|
||||
public void testNativeMappedArrayArgument() { }
|
||||
|
||||
@@ -42,7 +42,7 @@ public class DirectCallbacksTest extends CallbacksTest {
|
||||
public native Int32CallbackX returnCallback();
|
||||
public native Int32CallbackX returnCallbackArgument(Int32CallbackX cb);
|
||||
public native void callVoidCallback(VoidCallback c);
|
||||
public native void callVoidCallbackThreaded(VoidCallback c, int count, int ms);
|
||||
public native void callVoidCallbackThreaded(VoidCallback c, int count, int ms, String name);
|
||||
|
||||
public native int callInt32Callback(CustomCallback cb, int arg1, int arg2);
|
||||
public native void callCallbackInStruct(CbStruct s);
|
||||
|
||||
@@ -16,10 +16,15 @@ import junit.framework.*;
|
||||
import com.sun.jna.*;
|
||||
import com.sun.jna.ptr.PointerByReference;
|
||||
import java.lang.ref.*;
|
||||
import java.lang.reflect.Method;
|
||||
import java.io.File;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
//@SuppressWarnings("unused")
|
||||
public class DirectTest extends TestCase implements Paths {
|
||||
@@ -125,7 +130,6 @@ public class DirectTest extends TestCase implements Paths {
|
||||
}
|
||||
}
|
||||
|
||||
// Fails under clover
|
||||
public void testRegisterMethods() throws Exception {
|
||||
// Use a dedicated class loader to ensure the class can be gc'd
|
||||
String name = "com.sun.jna.DirectTest$MathLibrary";
|
||||
@@ -159,20 +163,138 @@ public class DirectTest extends TestCase implements Paths {
|
||||
public void testFindNativeClass() {
|
||||
class UnregisterLibrary {
|
||||
class Inner {
|
||||
public Class getNativeClass() {
|
||||
return getNativeClassInner();
|
||||
public Class findDirectMappedClass() {
|
||||
return findDirectMappedClassInner();
|
||||
}
|
||||
public Class getNativeClassInner() {
|
||||
return Native.getNativeClass(Native.getCallingClass());
|
||||
public Class findDirectMappedClassInner() {
|
||||
return Native.findDirectMappedClass(Native.getCallingClass());
|
||||
};
|
||||
}
|
||||
public native double cos(double x);
|
||||
public Class getNativeClass() {
|
||||
return new Inner().getNativeClass();
|
||||
public Class findDirectMappedClass() {
|
||||
return new Inner().findDirectMappedClass();
|
||||
};
|
||||
}
|
||||
assertEquals("Wrong native class found",
|
||||
UnregisterLibrary.class, new UnregisterLibrary().getNativeClass());
|
||||
UnregisterLibrary.class, new UnregisterLibrary().findDirectMappedClass());
|
||||
}
|
||||
|
||||
public static class DirectMapping {
|
||||
public static class DirectStructure extends Structure {
|
||||
public int field;
|
||||
protected List getFieldOrder() {
|
||||
return Arrays.asList(new String[] { "field" });
|
||||
}
|
||||
}
|
||||
public static interface DirectCallback extends Callback {
|
||||
void invoke();
|
||||
}
|
||||
public DirectMapping(Map options) {
|
||||
Native.register(getClass(), NativeLibrary.getInstance("testlib", options));
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetOptionsForDirectMappingWithMemberInitializer() {
|
||||
Class[] classes = {
|
||||
DirectMapping.class,
|
||||
DirectMapping.DirectStructure.class,
|
||||
DirectMapping.DirectCallback.class,
|
||||
};
|
||||
final TypeMapper mapper = new DefaultTypeMapper();
|
||||
final int alignment = Structure.ALIGN_NONE;
|
||||
final String encoding = System.getProperty("file.encoding");
|
||||
Map options = new HashMap();
|
||||
options.put(Library.OPTION_TYPE_MAPPER, mapper);
|
||||
options.put(Library.OPTION_STRUCTURE_ALIGNMENT, alignment);
|
||||
options.put(Library.OPTION_STRING_ENCODING, encoding);
|
||||
DirectMapping lib = new DirectMapping(options);
|
||||
for (int i=0;i < classes.length;i++) {
|
||||
assertEquals("Wrong type mapper for direct mapping " + classes[i],
|
||||
mapper, Native.getTypeMapper(classes[i]));
|
||||
assertEquals("Wrong alignment for direct mapping " + classes[i],
|
||||
alignment, Native.getStructureAlignment(classes[i]));
|
||||
assertEquals("Wrong encoding for direct mapping " + classes[i],
|
||||
encoding, Native.getStringEncoding(classes[i]));
|
||||
Object last = Native.getLibraryOptions(classes[i]);;
|
||||
assertSame("Options not cached", last, Native.getLibraryOptions(classes[i]));
|
||||
}
|
||||
}
|
||||
|
||||
public static class DirectMappingStatic {
|
||||
final static TypeMapper TEST_MAPPER = new DefaultTypeMapper();
|
||||
final static int TEST_ALIGNMENT = Structure.ALIGN_DEFAULT;
|
||||
final static String TEST_ENCODING = System.getProperty("file.encoding");
|
||||
final static Map TEST_OPTIONS = new HashMap() {
|
||||
{
|
||||
put(Library.OPTION_TYPE_MAPPER, TEST_MAPPER);
|
||||
put(Library.OPTION_STRUCTURE_ALIGNMENT, TEST_ALIGNMENT);
|
||||
put(Library.OPTION_STRING_ENCODING, TEST_ENCODING);
|
||||
}
|
||||
};
|
||||
static {
|
||||
Native.register(DirectMappingStatic.class, NativeLibrary.getInstance("testlib", TEST_OPTIONS));
|
||||
}
|
||||
public static class DirectStructure extends Structure {
|
||||
public int field;
|
||||
protected List getFieldOrder() {
|
||||
return Arrays.asList(new String[] { "field" });
|
||||
}
|
||||
}
|
||||
public static interface DirectCallback extends Callback {
|
||||
void invoke();
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetOptionsForDirectMappingWithStaticInitializer() {
|
||||
Class[] classes = {
|
||||
DirectMappingStatic.class,
|
||||
DirectMappingStatic.DirectStructure.class,
|
||||
DirectMappingStatic.DirectCallback.class,
|
||||
};
|
||||
for (int i=0;i < classes.length;i++) {
|
||||
assertEquals("Wrong type mapper for direct mapping " + classes[i],
|
||||
DirectMappingStatic.TEST_MAPPER, Native.getTypeMapper(classes[i]));
|
||||
assertEquals("Wrong alignment for direct mapping " + classes[i],
|
||||
DirectMappingStatic.TEST_ALIGNMENT, Native.getStructureAlignment(classes[i]));
|
||||
assertEquals("Wrong encoding for direct mapping " + classes[i],
|
||||
DirectMappingStatic.TEST_ENCODING, Native.getStringEncoding(classes[i]));
|
||||
Object last = Native.getLibraryOptions(classes[i]);;
|
||||
assertSame("Options not cached", last, Native.getLibraryOptions(classes[i]));
|
||||
}
|
||||
}
|
||||
|
||||
static class RemappedCLibrary {
|
||||
public static native int $$YJP$$strlen(String s);
|
||||
public static native int _prefixed_strlen(String s);
|
||||
}
|
||||
|
||||
public void testDirectMappingFunctionMapper() {
|
||||
FunctionMapper MAPPER = new FunctionMapper() {
|
||||
public String getFunctionName(NativeLibrary lib, Method method) {
|
||||
String name = method.getName();
|
||||
if (name.startsWith("_prefixed_")) {
|
||||
return name.substring(10);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
};
|
||||
Map options = new HashMap();
|
||||
options.put(Library.OPTION_FUNCTION_MAPPER, MAPPER);
|
||||
try {
|
||||
Native.register(RemappedCLibrary.class,
|
||||
NativeLibrary.getInstance(Platform.C_LIBRARY_NAME, options));
|
||||
final String VALUE = getName();
|
||||
int len;
|
||||
|
||||
len = RemappedCLibrary.$$YJP$$strlen(VALUE);
|
||||
assertEquals(VALUE.length(), len);
|
||||
|
||||
len = RemappedCLibrary._prefixed_strlen(VALUE);
|
||||
assertEquals(VALUE.length(), len);
|
||||
}
|
||||
catch(Exception e) {
|
||||
fail("Native method was not properly mapped: " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Alguns arquivos não foram exibidos porque demasiados arquivos foram alterados neste diff Mostrar Mais
Referência em uma Nova Issue
Bloquear um usuário