Comparar commits

..

107 Commits

Autor SHA1 Mensagem Data
Timothy Wall d42863603e fix Structure equals/hashcode
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@964 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-07-26 16:53:26 +00:00
Timothy Wall 2c19cf3e31 fix definition of HWND_BROADCAST
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@963 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-07-25 14:42:35 +00:00
Timothy Wall e7dc918c6a use non-null conversion context
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@962 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-07-21 14:02:58 +00:00
Timothy Wall 64c9e8212a update docs
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@961 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-07-21 13:45:43 +00:00
Timothy Wall 499c39f13d build linux/i386 against older glibc (2.3.4) for compatibility
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@959 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-07-17 18:12:48 +00:00
Timothy Wall bccdae735b rename native method according to Java class rename
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@958 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-07-17 02:52:47 +00:00
Timothy Wall 58120730a5 update notes on direct mapping
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@957 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-07-16 20:08:09 +00:00
Timothy Wall 5b8db8a680 add direct mapping note
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@956 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-07-15 13:50:54 +00:00
Timothy Wall 0acfd583c8 add jnaerator note
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@955 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-07-15 13:40:27 +00:00
Timothy Wall 402b7ef67e add marc strapetz' patch
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@954 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-07-15 13:05:36 +00:00
Timothy Wall 6944871c42 fix issue #121
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@953 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-07-15 13:03:53 +00:00
Timothy Wall b60da35689 update direct mapping info
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@952 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-07-14 19:24:16 +00:00
Timothy Wall 5204feddb1 update javadoc
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@951 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-07-14 18:10:29 +00:00
Timothy Wall 68156df66b update native libraries
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@949 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-07-14 18:03:48 +00:00
Timothy Wall a9e8b27285 ensure proper method selection when java callback returns NativeMapped
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@948 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-07-14 17:46:01 +00:00
Timothy Wall b8f470ddbd fix compilation warnings/errors on win64
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@947 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-07-14 15:28:36 +00:00
Timothy Wall 9d075dd1d1 revert configury changes, incompatible w/ windows build
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@946 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-07-14 13:30:49 +00:00
Timothy Wall 4b802c6f60 update configury
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@945 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-07-13 20:50:27 +00:00
Timothy Wall 8ce9344dd0 update from libffi CVS (local patches applied upstream)
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@944 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-07-13 14:15:02 +00:00
Timothy Wall cb2b386791 document getProcess usage
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@943 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-07-08 01:25:01 +00:00
Timothy Wall 7ee4681c10 enable accessing current process on w32
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@942 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-07-07 16:37:27 +00:00
Timothy Wall 82c0ea9df2 add test for NativeLibrary.getProcess()
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@941 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-07-07 15:39:16 +00:00
Timothy Wall 9070d80880 re-throw errors as errors
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@940 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-07-07 12:57:18 +00:00
Timothy Wall 45c53caf94 increase JWS timeout
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@939 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-07-07 11:56:17 +00:00
Timothy Wall c4947618c1 distinguish expected web start error from other errors
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@938 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-07-07 11:28:05 +00:00
Timothy Wall 941ed59c37 make structure read/write recursion detection thread-local
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@937 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-07-07 11:13:32 +00:00
Timothy Wall d76bbec1ab fix web start test for IBM J9
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@936 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-07-07 10:54:37 +00:00
Timothy Wall f5a1d98cf9 ensure clover.jar is signed
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@935 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-07-06 23:56:57 +00:00
Timothy Wall b0e6d837f0 provide toByteArray with String encoding option
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@934 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-07-06 13:28:28 +00:00
Timothy Wall b1cfb1b733 fix web start test on linux
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@933 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-07-06 13:15:04 +00:00
Timothy Wall 26a1212546 bump version, md5
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@932 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-07-06 10:49:59 +00:00
Timothy Wall 03b05aaae9 add test for callbacks w/type mapper w/differently-sized return types
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@931 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-07-06 10:29:59 +00:00
Timothy Wall f41c87d7c9 fix failing test on osx
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@930 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-07-06 10:21:13 +00:00
Timothy Wall b74deb5e35 narrow direct callback test failure
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@929 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-07-06 02:36:34 +00:00
Timothy Wall 240e2db637 improve test coverage, structure field error messages
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@928 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-07-06 01:09:07 +00:00
Timothy Wall 441947b6a4 ensure direct library mappings used in direct tests
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@927 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-07-06 01:06:40 +00:00
Timothy Wall 194bdaffcd add unicode equivalents
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@926 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-07-02 12:23:00 +00:00
Timothy Wall db6e9ff4c6 fix compiler warnings
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@925 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-07-01 15:47:09 +00:00
Timothy Wall 57261a1164 more performance notes
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@924 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-07-01 12:25:53 +00:00
Timothy Wall 0b116bb409 throw call errors *after* any cleanup
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@923 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-30 19:00:47 +00:00
Timothy Wall a5ad2e5de2 enable web start test on windows
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@922 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-26 20:06:25 +00:00
Timothy Wall b6928ff6c0 add test for auto-write of Structure.ByReference arrays
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@921 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-26 18:17:12 +00:00
Timothy Wall 4b03dd321c fix placement of exception throw
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@920 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-26 02:48:09 +00:00
Timothy Wall f7eefbd3d7 avoid making JNI calls after thrown exceptions
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@919 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-25 22:49:15 +00:00
Timothy Wall b23f7f9b27 fix setjmp/longjmp compiler warnings
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@918 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-25 15:41:37 +00:00
Timothy Wall b95bc7e4c4 remove redundant (and unreliable) test
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@917 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-25 15:29:27 +00:00
Timothy Wall 1593c0c347 add IBM J9 notes
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@916 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-25 15:26:13 +00:00
Timothy Wall c154663455 fix tests on windows
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@915 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-25 15:24:00 +00:00
Timothy Wall 13bc1901dc merge direct branch to trunk
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@913 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-25 13:58:15 +00:00
Timothy Wall 4f28322ac2 add ignores, update eclipse classpath
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@909 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-25 13:07:34 +00:00
Timothy Wall 756e2ced8b add web-start tests and test support
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@908 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-25 13:06:16 +00:00
Timothy Wall 1dc78b5209 fix typo
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@907 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-24 21:45:49 +00:00
Timothy Wall 3464093273 fix exception type
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@905 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-23 18:51:11 +00:00
Timothy Wall 4487214494 attempt to delete temporary native library in test
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@901 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-22 17:49:09 +00:00
Timothy Wall 6d7e222946 add direct mapping note
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@900 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-22 17:27:15 +00:00
Timothy Wall d12a6a3178 improve test coverage
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@899 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-21 19:50:29 +00:00
Timothy Wall ed9d609c35 provide more info in test failures
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@898 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-20 19:04:06 +00:00
Timothy Wall b86f359d93 Fix memory test on IBM J9
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@897 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-20 02:01:36 +00:00
Timothy Wall 02080dfcf8 fix tests on IBM J9 (windows) VM
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@896 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-20 01:54:37 +00:00
Timothy Wall 2768d25884 Fix test failures on IBM J9
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@895 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-20 00:11:21 +00:00
Timothy Wall 7bdf9896d2 Fix test failures on IBM J9
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@894 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-20 00:08:59 +00:00
Timothy Wall 3b4f84ded8 allow NativeMapped[] as function arguments
respect autoread/write structure setting in direct calls

git-svn-id: https://svn.java.net/svn/jna~svn/trunk@893 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-19 17:05:57 +00:00
Timothy Wall 69abc52731 make tests independent of load order
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@892 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-19 01:40:43 +00:00
Timothy Wall 1671b1fb8b allow types derived from Buffer as Structure fields
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@891 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-18 21:26:24 +00:00
Timothy Wall 8735f4ef5c fix kernel32 function lookup
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@890 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-18 18:55:46 +00:00
Timothy Wall 86967b5786 fix w32 compilation errors
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@889 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-18 16:23:32 +00:00
Timothy Wall ca8ceeb130 remove debug output
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@888 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-18 15:15:24 +00:00
Timothy Wall 41d6f8eeea add last error exception for direct calls
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@887 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-18 14:34:57 +00:00
Timothy Wall 27b7805608 Handle last error as an exception if declared
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@886 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-18 14:12:18 +00:00
Timothy Wall fef39f7013 replace atexit example
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@885 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-16 10:31:24 +00:00
Timothy Wall b414b54c6b fix callback example
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@884 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-15 20:19:46 +00:00
Timothy Wall ccdbb20ad0 facilitate struct members pointing to arrays of struct
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@877 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-10 13:26:57 +00:00
Timothy Wall eb7e47bf29 doc various structure type mappings
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@876 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-10 13:23:53 +00:00
Timothy Wall 53988c7184 update clover library
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@874 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-08 13:45:15 +00:00
Timothy Wall 9092b2bdc5 add VM information to build output
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@873 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-07 12:19:29 +00:00
Timothy Wall 068353aa5b ensure temp test unicode-named library deleted
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@872 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-07 12:07:27 +00:00
Timothy Wall 95a17ddbf0 attempt to find cause of w32 cleanup failure
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@869 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-06 11:45:09 +00:00
Timothy Wall 6c8c455f5b fix compiler warnings
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@868 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-06 00:31:18 +00:00
Timothy Wall 282032e178 give FS more time to delete native lib
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@867 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-05 22:31:54 +00:00
Timothy Wall af63e6a80d account for VM implementations returning 'null' as a classloader
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@866 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-05 19:52:06 +00:00
Timothy Wall a46ba0da29 restrict installation of shudown hook
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@865 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-05 19:37:56 +00:00
Timothy Wall f7738bf65b Add tests for library unloading and loading from jar
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@864 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-05 17:18:08 +00:00
Timothy Wall bb11d1fe37 unload native library unpacked from jar if Native class unloaded
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@863 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-05 15:33:51 +00:00
Timothy Wall d02a2deb52 update front page
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@859 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-04 14:52:04 +00:00
Timothy Wall 46105d849d add link to IAXClient applet
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@854 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-06-02 16:09:09 +00:00
Timothy Wall f16b6c3482 Omit JNA+AWT load test on headless systems
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@849 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-05-28 16:55:23 +00:00
Timothy Wall a9cb497045 allow callbacks in direct mappings
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@848 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-05-28 16:12:39 +00:00
Timothy Wall d529a34ecb revert last change
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@847 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-05-28 13:31:45 +00:00
Timothy Wall 5394029dc5 dynamically load libjsig if available
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@846 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-05-28 13:07:04 +00:00
Timothy Wall 28247737ca fix typo
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@845 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-05-27 20:01:14 +00:00
Timothy Wall 6448c2d8fb pass options to native library at interface definition
update javadoc to include direct mapping info

git-svn-id: https://svn.java.net/svn/jna~svn/trunk@844 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-05-27 20:00:02 +00:00
Timothy Wall 4460ccc8ec fix SIGBUS/SIGSEGV on sparc
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@843 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-05-27 13:02:46 +00:00
Timothy Wall 2b02a3c533 fix direct struct by value mapping
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@842 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-05-27 12:57:07 +00:00
Timothy Wall 6705513b86 add structure, string, NIO Buffer and primitive array support to direct type mapping
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@841 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-05-26 20:09:05 +00:00
Timothy Wall 4bd8d12481 use more appropriate exception types
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@840 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-05-26 19:55:15 +00:00
Timothy Wall ccaf3c283b avoid premature GC of Memory with NIO Buffers extant
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@839 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-05-26 19:54:26 +00:00
Timothy Wall ce4276a0cb fix layout
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@838 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-05-21 17:17:27 +00:00
Timothy Wall 709e316e56 fix layout
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@837 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-05-21 17:16:30 +00:00
Timothy Wall e46635d6ab fix layout
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@836 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-05-21 17:15:57 +00:00
Timothy Wall 0af8677ba4 fix layout
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@835 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-05-21 17:13:40 +00:00
Timothy Wall 9ab13daf09 fix layout
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@834 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-05-21 17:04:42 +00:00
Timothy Wall 17977fbabc fix layout
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@833 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-05-21 17:02:42 +00:00
xylo 83854047b7 reverted inadvertently adding another file in last commit
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@832 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-05-21 14:27:04 +00:00
xylo 28e56fd587 added a note that Xevie has been removed from xserver
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@831 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-05-21 14:21:49 +00:00
Timothy Wall 29fc6308b8 doc tweaks
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@830 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-05-21 13:35:23 +00:00
Timothy Wall 14a7df128d add missing header
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@829 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-05-21 13:27:15 +00:00
Timothy Wall dd4ef89d0a update main page w/direct calling info
git-svn-id: https://svn.java.net/svn/jna~svn/trunk@828 2f8a963e-d2e4-e7d0-97bf-ccb7fcea9d80
2009-05-21 13:23:33 +00:00
350 arquivos alterados com 9327 adições e 2943 exclusões
+8 -8
Ver Arquivo
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" output="build.eclipse/test-classes" path="test"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JDK 1.5"/>
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3"/>
<classpathentry kind="output" path="build.eclipse/classes"/>
</classpath>
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<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="output" path="build.eclipse/classes"/>
</classpath>
+54 -46
Ver Arquivo
@@ -22,7 +22,22 @@
# TODO
* make native dll extraction from jar public
* make direct calls call back *once* to Java where conversion is required,
and process all arguments from there (instead of potentially swapping back
and forth multipel 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
* combine direct and interface mapping calling code where possible
* make native dll extraction from jar public, to use with user dlls packaged
in a jar
* Callback.PostCallWrite.write() cf PostCallRead; do Structure.write for any
arguments as well
@@ -38,28 +53,7 @@
Requires separate compilation of annotation handling.
* parser (gluegen? swig? others?) to auto-generate JNA interfaces from headers;
ideally get the native library build system to output preprocessed headers,
otherwise CPP crap is a nightmare to get right.
o write SWIG transformer to auto-generate interfaces from header files
o see JNAerator
* should structure offsets be 64-bit? technically yes, but in practice I don't
think a structure that big actually works.
* (maybe) move all native functions into Native (limit header files, easier
management)
* Does it make sense to define Int16/UInt16, Int32/UInt32, etc? Probably not
the signed versions, but maybe the unsigned ones, to facilitate generating
unsigned values (maybe just provide utilities to pack an unsigned int into a
signed int). What about size_t, off_t, et al.? Would either need a
bunch of native lookup functions (more accurate) or java-side conditionals
(less robust but easier to change).
o bounds checking is handled by IntegerType (pass in a long, get an
exception if the value is out of bounds).
o when used as struct fields, could allow detection of field order by order
of initialization (requires all-or-nothing usage, though)
* ditch type conversion context.
* packaging: 'types', 'convert/marshal' subpackages?
note: marshal/unmarshal vs to/fromnative: to/fromnative is more
@@ -69,12 +63,6 @@
Pointer into a types subpackage (which would leave just a few top-level
classes). Javadoc is cluttered by example classes anyway.
* Make a separate jar file for all OS-specific headers
Maybe make interfaces per-header file (winbase, winnt, stdlib, etc),
aggregated per-library (interface CLibrary extends stdlib, stdio, etc)
(how useful would it really be, or is this just sorting legos?)
o same for windowutils, fileutils, etc.
* support annotations of parameters and return values w/o breaking
1.4 compatibility (retroweaver?), e.g.
-- retroweaver (requires retroweaver runtime classes to provide annotation
@@ -89,14 +77,6 @@
this only really applies to NativeLong/IntegerType types that want to use a
primitive value instead of creating an object instance.
* Allow Buffer in Structures (and callbacks) (auto-wrap in direct byte buffer)?
o this gets tricky when reading structs from native memory; we don't know if
the value is already mapped to a buffer (cf CallbackReference)
* standard types for various platforms: posix/types.h, w32 (DWORD, HANDLE)
* StringBuffer/StringBuilder as mutable char*/wchar_t* argument
NOTE: byte[]/char[] is probably better; it's trivial to convert to String
and native code can't change the size anyway
* flag string(/wstring)-returning methods which need to free their result
to avoid leaking memory whan auto-creating strings from the result
(since normally we don't take explicit ownership of any returned pointers)
@@ -113,9 +93,6 @@
"pointer-requiring-free" (which is just Memory). For now, leave it up to
the user to manage the pointer, since they have to define the free method
anyway. use could always put a finalizer on a PointerType-derived type.
* provide library load/unload hooks (Runnables in options?). Examples:
o GetLastError (no longer needed)
o WSAInit?
* if method has "GetLastErrorException/ErrnoException" in its signature, use
result codes + GetLastError/errno/errstr to auto-generate
runtime exceptions? (cf P/Invoke; also useful for X11 return types)
@@ -127,21 +104,22 @@
if nonzero ?
o otherwise, need an ExceptionOnZero, ExceptionOnNonZero runtime, from which
derive GetLastError/ErrnoExceptionOnZero/NZ
* determine X11 display name from current java program (if any); null is ok
since it uses getenv(DISPLAY), which is what java would do
note: DISPLAY may be available in GraphicsDevice->getIDstring
* universal GCC build w/cross-compile (needs cross compilers...)
* return Pointer.SIZE/LONG_SIZE/WCHAR_SIZE in bits (for consistency with 1.5)
Long.SIZE, Integer.SIZE, et al.
* interface "lvalue", which can provide a pointer to itself (reference() or
addressOf())?
* verify get/set methods vs read/write for performance (Pointer)?
* bitfields for structs (how?)
# DONE
* verify get/set methods vs read/write for performance (Pointer)?
(see RawTest for performance comparisons)
* Allow Buffer in Structures (and callbacks) (auto-wrap in direct byte buffer)?
o this gets tricky when reading structs from native memory; we don't know if
the value is already mapped to a buffer (cf CallbackReference)
* standard types for various platforms: posix/types.h, w32 (DWORD, HANDLE)
* embed version in DLL ('depends'-done)/so (symlink?)
* use libffi closure allocation/deallocation
@@ -261,5 +239,35 @@ transient callbacks, and require callback+dispose for most callbacks?
void setWindowMask(Window w, Shape clip);
// needs:
int findNativeWindow(Window w);
#MAYBE NOT
* should structure offsets be 64-bit? technically yes, but in practice I don't
think a structure that big actually works.
* (maybe) move all native functions into Native (limit header files, easier
management)
* Does it make sense to define Int16/UInt16, Int32/UInt32, etc? Probably not
the signed versions, but maybe the unsigned ones, to facilitate generating
unsigned values (maybe just provide utilities to pack an unsigned int into a
signed int). What about size_t, off_t, et al.? Would either need a
bunch of native lookup functions (more accurate) or java-side conditionals
(less robust but easier to change).
o bounds checking is handled by IntegerType (pass in a long, get an
exception if the value is out of bounds).
o when used as struct fields, could allow detection of field order by order
of initialization (requires all-or-nothing usage, though)
* Make a separate jar file for all OS-specific headers
Maybe make interfaces per-header file (winbase, winnt, stdlib, etc),
aggregated per-library (interface CLibrary extends stdlib, stdio, etc)
(how useful would it really be, or is this just sorting legos?)
o same for windowutils, fileutils, etc. (not useful)
* StringBuffer/StringBuilder as mutable char*/wchar_t* argument
NOTE: byte[]/char[] is probably better; it's trivial to convert to String
and native code can't change the size anyway
* provide library load/unload hooks (Runnables in options?). Examples:
o GetLastError (no longer needed)
o WSAInit?
* determine X11 display name from current java program (if any); null is ok
since it uses getenv(DISPLAY), which is what java would do
note: DISPLAY may be available in GraphicsDevice->getIDstring
+29 -8
Ver Arquivo
@@ -15,6 +15,7 @@
<!-- (all build-related props should go in -dynamic-properties) -->
<property name="name" value="jna"/>
<property name="jar" value="${name}.jar"/>
<property name="testjar" value="${name}-test.jar"/>
<property name="debug" value="true"/>
<property name="debug.native" value="false"/>
<property name="cflags_extra.native" value=""/>
@@ -28,21 +29,21 @@
<property name="stylesheet" location="${javadoc}/doc/css/javadoc.css"/>
<property name="vendor" value="JNA Development Team"/>
<property name="copyright"
value="Copyright &amp;copy; 2007-2008 Timothy Wall. All Rights Reserved."/>
value="Copyright &amp;copy; 2007-2009 Timothy Wall. All Rights Reserved."/>
<buildnumber/>
<!-- JNA library release version -->
<property name="jna.major" value="3"/>
<property name="jna.minor" value="1"/>
<property name="jna.revision" value="0"/>
<property name="jna.minor" value="2"/>
<property name="jna.revision" value="1"/>
<property name="jna.build" value="${build.number}"/>
<property name="jna.version" value="${jna.major}.${jna.minor}.${jna.revision}"/>
<!-- jnidispatch library release version -->
<property name="jni.major" value="3"/>
<property name="jni.minor" value="1"/>
<property name="jni.minor" value="2"/>
<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="816e53324203bcffe46f43e482e5c286"/>
<property name="jni.md5" value="c870290c36c8d3fdf85db7c782febc3f"/>
<property name="spec.title" value="Java Native Access (JNA)"/>
<property name="spec.vendor" value="${vendor}"/>
<property name="spec.version" value="${jna.major}"/>
@@ -64,8 +65,11 @@
<target name="compile-single" depends="compile"/>
<target name="-dynamic-properties">
<echo>Java version: ${java.version}, compatibility: ${compatibility}</echo>
<echo>JNA version ${jna.version}, native API version ${jni.version}</echo>
<echo>Java version ${java.version}, compatibility: ${compatibility}</echo>
<echo>JNA version ${jna.version}, native ${jni.version}</echo>
<echo>${java.vm.name} (${java.vm.vendor}, ${java.vm.version})</echo>
<echo>java.home=${java.home}</echo>
<echo>java.library.path=${java.library.path}</echo>
<replaceregexp match="(&lt;version&gt;).*(&lt;/version&gt;)"
replace="\1${jna.version}\2"
@@ -77,6 +81,7 @@
<condition property="vm.arch" value="-d64" else="">
<or>
<equals arg1="${sun.arch.data.model}" arg2="64" trim="true"/>
<equals arg1="${com.ibm.vm.bitmode}" arg2="64" trim="true"/>
<os arch="x86_64"/>
<os arch="ppc64"/>
<os arch="sparcv9"/>
@@ -391,7 +396,7 @@
</jar>
</target>
<target name="compile-tests" depends="compile,native"
<target name="compile-tests" depends="compile,native,jar"
description="Compile all test code">
<javac classpathref="compile-test.path"
source="${test.compatibility}"
@@ -400,6 +405,22 @@
deprecation="on" debug="${debug}">
<src path="${test.src}"/>
</javac>
<jar jarfile="${build}/${testjar}">
<fileset dir="${test.classes}">
<patternset refid="jar-compiled"/>
</fileset>
</jar>
<mkdir dir="${build}/jws"/>
<copy todir="${build}/jws" file="${build}/${jar}"/>
<copy todir="${build}/jws" file="${build}/${testjar}"/>
<copy todir="${build}/jws" file="lib/junit.jar"/>
<copy todir="${build}/jws" file="lib/clover.jar"/>
<jar jarfile="${build}/jws/jnidispatch.jar">
<fileset dir="${build.native}" includes="*jnidispatch.*"/>
</jar>
<signjar alias="jna" keystore="jna.keystore" storepass="jnadev" lazy="true">
<fileset dir="${build}/jws" includes="jna.jar,jna-test.jar,junit.jar,jnidispatch.jar,clover.jar"/>
</signjar>
</target>
<!-- When running tests from an IDE, be sure to set jna.library.path -->
BIN
Ver Arquivo
Arquivo binário não exibido.
BIN
Ver Arquivo
Arquivo binário não exibido.
BIN
Ver Arquivo
Arquivo binário não exibido.
Arquivo binário não exibido.
BIN
Ver Arquivo
Arquivo binário não exibido.
BIN
Ver Arquivo
Arquivo binário não exibido.
BIN
Ver Arquivo
Arquivo binário não exibido.
BIN
Ver Arquivo
Arquivo binário não exibido.
BIN
Ver Arquivo
Arquivo binário não exibido.
BIN
Ver Arquivo
Arquivo binário não exibido.
BIN
Ver Arquivo
Arquivo binário não exibido.
Arquivo binário não exibido.
BIN
Ver Arquivo
Arquivo binário não exibido.
BIN
Ver Arquivo
Arquivo binário não exibido.
BIN
Ver Arquivo
Arquivo binário não exibido.
Arquivo binário não exibido.
Arquivo binário não exibido.
+5 -5
Ver Arquivo
@@ -1,5 +1,5 @@
nQMpVtdkeiLDhkfVhlebsGWVMnsDeqDAmHuaUJSRUxwraf
mi2K4SaejnjOrPDIm3nJq8<b2Ke>wQwCu3>RYeCLGxFda>
PRoQxwONRmmnMpmQRPQvuNmQoQpMQRMpOnSSTxXMvwWmvu
VtqwVvXwqqRnmqmUUnnvuvvqqmmmmmUUnnvuvvqqmmmmmU
UgkXkabskgXsXkkbqUUnmm
qRNQnmsMoNMDGXUenVfHVPuFPrNBGUUdBvfgtIdgVQWSbAa
mj2KW7Oo9ud83ZbEKfK2xx922L04T>gYjDdLjGld4Wa6MPW
NrqPtxROppqOmmqROMPSTnMmRqNOMnMnoPVSXswPsVXQwXV
SPVVUtUNQmnmqmUUnopmqsvommmmmUUnopmqsvommmmmUUg
kXkabskgXsXkkbqUUnmm
+10 -8
Ver Arquivo
@@ -27,8 +27,8 @@ OS=$(shell uname | sed -e 's/\(CYGWIN\|MINGW32\).*/win32/g' \
-e 's/Darwin.*/darwin/g' \
-e 's/Linux.*/linux/g')
VERSION=3.1.0 # auto-generated by ant
CHECKSUM=816e53324203bcffe46f43e482e5c286 # auto-generated by ant
VERSION=3.2.0 # auto-generated by ant
CHECKSUM=c870290c36c8d3fdf85db7c782febc3f # auto-generated by ant
JAVA_INCLUDES=-I"$(JAVA_HOME)/include" \
-I"$(JAVA_HOME)/include/$(OS)"
@@ -42,7 +42,7 @@ ifneq ($(DYNAMIC_LIBFFI),true)
FFI_SRC=$(shell pwd)/libffi
FFI_BUILD=$(BUILD)/libffi
FFI_LIB=$(FFI_BUILD)/.libs/libffi$(ARSFX)
FFI_ENV=CC="$(CC)" CFLAGS="$(CDEBUG)" CPPFLAGS="$(CDEFINES)"
FFI_ENV=CC="$(CC)" CFLAGS="$(COPT) $(CDEBUG)" CPPFLAGS="$(CDEFINES)"
FFI_CONFIG=--enable-static --disable-shared --with-pic=yes
endif
LIBRARY=$(BUILD)/$(LIBPFX)jnidispatch$(JNISFX)
@@ -58,8 +58,7 @@ CC=gcc
LD=gcc
LIBS=
# Default to Sun recommendations for JNI compilation
#COPT=-O2 -fomit-frame-pointer
COPT=-fno-omit-frame-pointer -fno-strict-aliasing
COPT=-O2 -fno-omit-frame-pointer -fno-strict-aliasing
CASM=-S
ifeq ($(DEBUG),true)
CDEBUG=-g
@@ -87,7 +86,8 @@ STRIP=strip -x
ifeq ($(OS),win32)
ARCH=$(shell uname -m | sed 's/i.86/i386/g')
CDEFINES=-DHAVE_PROTECTION
CDEFINES=-DHAVE_PROTECTION -DPSAPI_VERSION=1
LIBS=-lpsapi
WINDRES=windres
EXTRAOBJS=$(RSRC)
STRIP=@echo
@@ -104,18 +104,20 @@ ifeq ($(ARCH),amd64)
WINDRES=/usr/local/mingw64-cross/bin/x86_64-pc-mingw32-windres
# Uncomment to enable MINGW64 cross compiler
# Last build attempt has too many runtime problems (alloca broken) (080831)
# Should build properly as of 090601, but lacks SEH, so MSVC build is preferred
#MINGW = x86_64-pc-mingw32-gcc
ifneq ($(MINGW),)
CC = $(MINGW) -m64 -mno-cygwin
LD = $(CC)
LDFLAGS=-o $@ -shared
LIBS= -lmingwex -lkernel32 -lmsvcrt
LIBS= -lmingwex -lpsapi -lkernel32 -lmsvcrt
FFI_CONFIG += --host=x86_64-pc-mingw32
else
# MSVC (wrapper scripts)
CC=$(FFI_SRC)/../cc.sh -m64
LD=$(FFI_SRC)/../ld.sh -m64
COPT=
LIBS=psapi.lib
ARSFX=.lib
FFI_CONFIG += --host=x86_64-pc-mingw32 && rm -f include/ffitarget.h && cp $(FFI_SRC)/include/*.h $(FFI_SRC)/src/x86/ffitarget.h include
FFI_ENV += LD="$(LD)" CPP=cpp
+248 -44
Ver Arquivo
@@ -37,89 +37,177 @@ static jclass classObject;
callback*
create_callback(JNIEnv* env, jobject obj, jobject method,
jobjectArray param_types, jclass return_type,
callconv_t calling_convention) {
callconv_t calling_convention, jboolean direct) {
callback* cb;
ffi_abi abi = FFI_DEFAULT_ABI;
ffi_abi java_abi = FFI_DEFAULT_ABI;
ffi_type* ffi_rtype;
ffi_status status;
jsize argc;
JavaVM* vm;
char rtype;
int rtype;
char msg[64];
int i;
int cvt = 0;
const char* throw_type = NULL;
const char* throw_msg = NULL;
if ((*env)->GetJavaVM(env, &vm) != JNI_OK) {
throwByName(env, EUnsatisfiedLink, "Can't get Java VM");
return NULL;
}
argc = (*env)->GetArrayLength(env, param_types);
cb = (callback *)malloc(sizeof(callback));
cb->ffi_closure = ffi_closure_alloc(sizeof(ffi_closure), &cb->x_closure);
cb->closure = ffi_closure_alloc(sizeof(ffi_closure), &cb->x_closure);
cb->object = (*env)->NewWeakGlobalRef(env, obj);
cb->methodID = (*env)->FromReflectedMethod(env, method);
cb->vm = vm;
cb->arg_types = (ffi_type**)malloc(sizeof(ffi_type*) * argc);
cb->java_arg_types = (ffi_type**)malloc(sizeof(ffi_type*) * (argc + 3));
cb->arg_jtypes = (char*)malloc(sizeof(char) * argc);
cb->flags = (int *)malloc(sizeof(int) * argc);
cb->rflag = CVT_DEFAULT;
cb->arg_classes = (jobject*)malloc(sizeof(jobject) * argc);
cb->direct = direct;
cb->java_arg_types[0] = cb->java_arg_types[1] = cb->java_arg_types[2] = &ffi_type_pointer;
for (i=0;i < argc;i++) {
int jtype;
jclass cls = (*env)->GetObjectArrayElement(env, param_types, i);
cb->param_jtypes[i] = get_jtype(env, cls);
cb->ffi_args[i] = get_ffi_type(env, cls, cb->param_jtypes[i]);
if (!cb->param_jtypes[i]) {
snprintf(msg, sizeof(msg), "Unsupported type at parameter %d", i);
throwByName(env, EIllegalArgument, msg);
if ((cb->flags[i] = get_conversion_flag(env, cls)) != CVT_DEFAULT) {
cb->arg_classes[i] = (*env)->NewWeakGlobalRef(env, cls);
cvt = 1;
}
jtype = get_jtype(env, cls);
if (jtype == -1) {
snprintf(msg, sizeof(msg), "Unsupported argument at index %d", i);
throw_type = EIllegalArgument;
throw_msg = msg;
goto failure_cleanup;
}
cb->arg_jtypes[i] = (char)jtype;
cb->java_arg_types[i+3] = cb->arg_types[i] = get_ffi_type(env, cls, cb->arg_jtypes[i]);
if (cb->flags[i] == CVT_NATIVE_MAPPED
|| cb->flags[i] == CVT_POINTER_TYPE
|| cb->flags[i] == CVT_INTEGER_TYPE) {
jclass ncls;
ncls = getNativeType(env, cls);
jtype = get_jtype(env, ncls);
if (jtype == -1) {
snprintf(msg, sizeof(msg), "Unsupported NativeMapped argument native type at argument %d", i);
throw_type = EIllegalArgument;
throw_msg = msg;
goto failure_cleanup;
}
cb->arg_jtypes[i] = (char)jtype;
cb->java_arg_types[i+3] = &ffi_type_pointer;
cb->arg_types[i] = get_ffi_type(env, ncls, cb->arg_jtypes[i]);
}
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->flags[i] = CVT_FLOAT;
cvt = 1;
}
else if (cb->java_arg_types[i+3]->type == FFI_TYPE_STRUCT) {
// All callback structure arguments are passed as a jobject
cb->java_arg_types[i+3] = &ffi_type_pointer;
}
}
if (!direct || !cvt) {
free(cb->flags);
cb->flags = NULL;
free(cb->arg_classes);
cb->arg_classes = NULL;
}
if (direct) {
cb->rflag = get_conversion_flag(env, return_type);
if (cb->rflag == CVT_NATIVE_MAPPED
|| cb->rflag == CVT_INTEGER_TYPE
|| cb->rflag == CVT_POINTER_TYPE) {
return_type = getNativeType(env, return_type);
}
}
#if defined(_WIN32) && !defined(_WIN64)
if (calling_convention == CALLCONV_STDCALL) {
abi = FFI_STDCALL;
}
java_abi = FFI_STDCALL;
#endif // _WIN32
rtype = get_jtype(env, return_type);
if (!rtype) {
throwByName(env, EIllegalArgument, "Unsupported return type");
if (rtype == -1) {
throw_type = EIllegalArgument;
throw_msg = "Unsupported return type";
goto failure_cleanup;
}
ffi_rtype = get_ffi_rtype(env, return_type, rtype);
ffi_rtype = get_ffi_rtype(env, return_type, (char)rtype);
if (!ffi_rtype) {
throwByName(env, EIllegalArgument, "Error in return type");
throw_type = EIllegalArgument;
throw_msg = "Error in return type";
goto failure_cleanup;
}
status = ffi_prep_cif(&cb->ffi_cif, abi, argc, ffi_rtype, &cb->ffi_args[0]);
status = ffi_prep_cif(&cb->cif, abi, argc, ffi_rtype, cb->arg_types);
if (!ffi_error(env, "callback setup", status)) {
ffi_type* java_ffi_rtype = ffi_rtype;
switch(status) {
case FFI_BAD_ABI:
snprintf(msg, sizeof(msg),
"Invalid calling convention: %d", (int)calling_convention);
throwByName(env, EIllegalArgument, msg);
break;
case FFI_BAD_TYPEDEF:
snprintf(msg, sizeof(msg),
"Invalid structure definition (native typedef error)");
throwByName(env, EIllegalArgument, msg);
break;
case FFI_OK:
ffi_prep_closure_loc(cb->ffi_closure, &cb->ffi_cif, callback_dispatch, cb,
cb->x_closure);
return cb;
default:
snprintf(msg, sizeof(msg),
"Native callback setup failure: error code %d", status);
throwByName(env, EIllegalArgument, msg);
break;
if (cb->rflag == CVT_STRUCTURE_BYVAL
|| cb->rflag == CVT_NATIVE_MAPPED
|| cb->rflag == CVT_POINTER_TYPE
|| cb->rflag == CVT_INTEGER_TYPE) {
// Java method returns a jobject, not a struct
java_ffi_rtype = &ffi_type_pointer;
rtype = '*';
}
switch(rtype) {
case 'V': cb->fptr = (*env)->CallVoidMethod; break;
case 'Z': cb->fptr = (*env)->CallBooleanMethod; break;
case 'B': cb->fptr = (*env)->CallByteMethod; break;
case 'S': cb->fptr = (*env)->CallShortMethod; break;
case 'C': cb->fptr = (*env)->CallCharMethod; break;
case 'I': cb->fptr = (*env)->CallIntMethod; break;
case 'J': cb->fptr = (*env)->CallLongMethod; break;
case 'F': cb->fptr = (*env)->CallFloatMethod; break;
case 'D': cb->fptr = (*env)->CallDoubleMethod; break;
default: cb->fptr = (*env)->CallObjectMethod; break;
}
status = ffi_prep_cif(&cb->java_cif, java_abi, 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);
return cb;
}
}
failure_cleanup:
free_callback(env, cb);
if (throw_type) {
throwByName(env, throw_type, msg);
}
return NULL;
}
void
free_callback(JNIEnv* env, callback *cb) {
(*env)->DeleteWeakGlobalRef(env, cb->object);
ffi_closure_free(cb->ffi_closure);
ffi_closure_free(cb->closure);
free(cb->arg_types);
if (cb->arg_classes) {
unsigned i;
for (i=0;i < cb->cif.nargs;i++) {
(*env)->DeleteWeakGlobalRef(env, cb->arg_classes[i]);
}
free(cb->arg_classes);
}
free(cb->java_arg_types);
if (cb->flags)
free(cb->flags);
free(cb->arg_jtypes);
free(cb);
}
@@ -140,7 +228,9 @@ handle_exception(JNIEnv* env, jobject cb, jthrowable throwable) {
if (!(*env)->IsSameObject(env, handler, NULL)) {
(*env)->CallVoidMethod(env, handler, mid, cb, throwable);
}
return (*env)->ExceptionCheck(env) == 0;
if ((*env)->ExceptionCheck(env) == 0) {
return 1;
}
}
}
}
@@ -154,12 +244,124 @@ handle_exception(JNIEnv* env, jobject cb, jthrowable throwable) {
static void
callback_invoke(JNIEnv* env, callback *cb, ffi_cif* cif, void *resp, void **cbargs) {
jobject self;
void *oldresp = resp;
self = (*env)->NewLocalRef(env, cb->object);
// Avoid calling back to a GC'd object
if ((*env)->IsSameObject(env, self, NULL)) {
fprintf(stderr, "JNA: callback object has been garbage collected\n");
memset(resp, 0, cif->rtype->size);
if (cif->rtype->type != FFI_TYPE_VOID)
memset(resp, 0, cif->rtype->size);
}
else if (cb->direct) {
unsigned int i;
void **args = alloca((cif->nargs + 3) * sizeof(void *));
args[0] = (void *)&env;
args[1] = &self;
args[2] = &cb->methodID;
memcpy(&args[3], cbargs, cif->nargs * sizeof(void *));
if (cb->flags) {
for (i=0;i < cif->nargs;i++) {
switch(cb->flags[i]) {
case CVT_INTEGER_TYPE:
case CVT_POINTER_TYPE:
case CVT_NATIVE_MAPPED:
*((void **)args[i+3]) = fromNative(env, cb->arg_classes[i], cif->arg_types[i], args[i+3], JNI_FALSE);
break;
case CVT_POINTER:
*((void **)args[i+3]) = newJavaPointer(env, *(void **)args[i+3]);
break;
case CVT_STRING:
*((void **)args[i+3]) = newJavaString(env, *(void **)args[i+3], JNI_FALSE);
break;
case CVT_WSTRING:
*((void **)args[i+3]) = newJavaWString(env, *(void **)args[i+3]);
break;
case CVT_STRUCTURE:
*((void **)args[i+3]) = newJavaStructure(env, *(void **)args[i+3], cb->arg_classes[i], JNI_FALSE);
break;
case CVT_STRUCTURE_BYVAL:
{
void *ptr = args[i+3];
args[i+3] = alloca(sizeof(void *));
*((void **)args[i+3]) = newJavaStructure(env, ptr, cb->arg_classes[i], JNI_TRUE);
}
break;
case CVT_CALLBACK:
*((void **)args[i+3]) = newJavaCallback(env, *(void **)args[i+3], cb->arg_classes[i]);
break;
case CVT_FLOAT:
{
void *ptr = alloca(sizeof(double));
*(double *)ptr = *(float*)args[i+3];
args[i+3] = ptr;
}
break;
}
}
}
if (cb->rflag == CVT_STRUCTURE_BYVAL) {
resp = alloca(sizeof(jobject));
}
else if (cb->cif.rtype->size > cif->rtype->size) {
resp = alloca(cb->cif.rtype->size);
}
ffi_call(&cb->java_cif, FFI_FN(cb->fptr), resp, args);
if ((*env)->ExceptionCheck(env)) {
jthrowable throwable = (*env)->ExceptionOccurred(env);
(*env)->ExceptionClear(env);
if (!handle_exception(env, self, throwable)) {
fprintf(stderr, "JNA: error handling callback exception, continuing\n");
}
if (cif->rtype->type != FFI_TYPE_VOID)
memset(oldresp, 0, cif->rtype->size);
}
else switch(cb->rflag) {
case CVT_INTEGER_TYPE:
if (cb->cif.rtype->size > sizeof(ffi_arg)) {
*(jlong *)oldresp = getIntegerTypeValue(env, *(void **)resp);
}
else {
*(ffi_arg *)oldresp = (ffi_arg)getIntegerTypeValue(env, *(void **)resp);
}
break;
case CVT_POINTER_TYPE:
*(void **)resp = getPointerTypeAddress(env, *(void **)resp);
break;
case CVT_NATIVE_MAPPED:
toNative(env, *(void **)resp, oldresp, cb->cif.rtype->size, JNI_TRUE);
break;
case CVT_POINTER:
*(void **)resp = getNativeAddress(env, *(void **)resp);
break;
case CVT_STRING:
*(void **)resp = getNativeString(env, *(void **)resp, JNI_FALSE);
break;
case CVT_WSTRING:
*(void **)resp = getNativeString(env, *(void **)resp, JNI_TRUE);
break;
case CVT_STRUCTURE:
writeStructure(env, *(void **)resp);
*(void **)resp = getStructureAddress(env, *(void **)resp);
break;
case CVT_STRUCTURE_BYVAL:
writeStructure(env, *(void **)resp);
memcpy(oldresp, getStructureAddress(env, *(void **)resp), cb->cif.rtype->size);
break;
case CVT_CALLBACK:
*(void **)resp = getCallbackAddress(env, *(void **)resp);
break;
default: break;
}
if (cb->flags) {
for (i=0;i < cif->nargs;i++) {
if (cb->flags[i] == CVT_STRUCTURE) {
writeStructure(env, *(void **)args[i+3]);
}
}
}
}
else {
jobject result;
@@ -168,7 +370,7 @@ callback_invoke(JNIEnv* env, callback *cb, ffi_cif* cif, void *resp, void **cbar
unsigned int i;
for (i=0;i < cif->nargs;i++) {
jobject arg = new_object(env, cb->param_jtypes[i], cbargs[i]);
jobject arg = new_object(env, cb->arg_jtypes[i], cbargs[i], JNI_FALSE);
(*env)->SetObjectArrayElement(env, array, i, arg);
}
result = (*env)->CallObjectMethod(env, self, cb->methodID, array);
@@ -178,10 +380,11 @@ callback_invoke(JNIEnv* env, callback *cb, ffi_cif* cif, void *resp, void **cbar
if (!handle_exception(env, self, throwable)) {
fprintf(stderr, "JNA: error handling callback exception, continuing\n");
}
memset(resp, 0, cif->rtype->size);
if (cif->rtype->type != FFI_TYPE_VOID)
memset(resp, 0, cif->rtype->size);
}
else {
extract_value(env, result, resp, cif->rtype->size);
extract_value(env, result, resp, cif->rtype->size, JNI_TRUE);
}
}
}
@@ -204,11 +407,12 @@ callback_dispatch(ffi_cif* cif, void* resp, void** cbargs, void* user_data) {
// are properly disposed
if ((*env)->PushLocalFrame(env, 16) < 0) {
fprintf(stderr, "JNA: Out of memory: Can't allocate local frame");
return;
}
callback_invoke(env, (callback *)user_data, cif, resp, cbargs);
(*env)->PopLocalFrame(env, NULL);
else {
callback_invoke(env, (callback *)user_data, cif, resp, cbargs);
(*env)->PopLocalFrame(env, NULL);
}
if (!attached) {
(*jvm)->DetachCurrentThread(jvm);
}
+1 -1
Ver Arquivo
@@ -41,7 +41,7 @@ do
shift 1
;;
-O*)
args="$args /O1"
args="$args $i"
shift 1
;;
-g)
+1018 -265
Ver Arquivo
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+76 -12
Ver Arquivo
@@ -15,6 +15,22 @@
#include "ffi.h"
#include "com_sun_jna_Function.h"
#include "com_sun_jna_Native.h"
#ifdef sun
# include <alloca.h>
#endif
#ifdef _WIN32
#ifdef _MSC_VER
#define alloca _alloca
#pragma warning( disable : 4152 ) /* function/data conversion */
#pragma warning( disable : 4054 ) /* cast function pointer to data pointer */
#pragma warning( disable : 4055 ) /* cast data pointer to function pointer */
#pragma warning( disable : 4204 ) /* structure initializer */
#pragma warning( disable : 4710 ) /* swprintf not inlined */
#else
#include <malloc.h>
#endif /* _MSC_VER */
#endif /* _WIN32 */
#ifdef __cplusplus
extern "C" {
@@ -31,21 +47,50 @@ typedef enum _callconv {
/* Maximum number of allowed arguments in libffi. */
#define MAX_NARGS com_sun_jna_Function_MAX_NARGS
enum {
CVT_DEFAULT = com_sun_jna_Native_CVT_DEFAULT,
CVT_POINTER = com_sun_jna_Native_CVT_POINTER,
CVT_STRING = com_sun_jna_Native_CVT_STRING,
CVT_STRUCTURE = com_sun_jna_Native_CVT_STRUCTURE,
CVT_STRUCTURE_BYVAL = com_sun_jna_Native_CVT_STRUCTURE_BYVAL,
CVT_BUFFER = com_sun_jna_Native_CVT_BUFFER,
CVT_ARRAY_BYTE = com_sun_jna_Native_CVT_ARRAY_BYTE,
CVT_ARRAY_SHORT = com_sun_jna_Native_CVT_ARRAY_SHORT,
CVT_ARRAY_CHAR = com_sun_jna_Native_CVT_ARRAY_CHAR,
CVT_ARRAY_INT = com_sun_jna_Native_CVT_ARRAY_INT,
CVT_ARRAY_LONG = com_sun_jna_Native_CVT_ARRAY_LONG,
CVT_ARRAY_FLOAT = com_sun_jna_Native_CVT_ARRAY_FLOAT,
CVT_ARRAY_DOUBLE = com_sun_jna_Native_CVT_ARRAY_DOUBLE,
CVT_ARRAY_BOOLEAN = com_sun_jna_Native_CVT_ARRAY_BOOLEAN,
CVT_BOOLEAN = com_sun_jna_Native_CVT_BOOLEAN,
CVT_CALLBACK = com_sun_jna_Native_CVT_CALLBACK,
CVT_FLOAT = com_sun_jna_Native_CVT_FLOAT,
CVT_NATIVE_MAPPED = com_sun_jna_Native_CVT_NATIVE_MAPPED,
CVT_WSTRING = com_sun_jna_Native_CVT_WSTRING,
CVT_INTEGER_TYPE = com_sun_jna_Native_CVT_INTEGER_TYPE,
CVT_POINTER_TYPE = com_sun_jna_Native_CVT_POINTER_TYPE,
CVT_TYPE_MAPPER = com_sun_jna_Native_CVT_TYPE_MAPPER,
};
typedef struct _callback {
// Location of this field must agree with CallbackReference.getTrampoline()
void* x_closure;
ffi_closure* ffi_closure;
ffi_cif ffi_cif;
ffi_type* ffi_args[MAX_NARGS];
ffi_closure* closure;
ffi_cif cif;
ffi_cif java_cif;
ffi_type** arg_types;
ffi_type** java_arg_types;
jobject* arg_classes;
int* flags;
int rflag;
JavaVM* vm;
jobject object;
jmethodID methodID;
char param_jtypes[MAX_NARGS];
char* arg_jtypes;
jboolean direct;
void* fptr;
} callback;
// Size of a register
typedef long word_t;
#if defined(SOLARIS2) || defined(__GNUC__)
#if defined(_WIN64)
#define L2A(X) ((void *)(long long)(X))
@@ -87,22 +132,41 @@ typedef long word_t;
#define EUnsatisfiedLink "java/lang/UnsatisfiedLinkError"
#define EIllegalState "java/lang/IllegalStateException"
#define EUnsupportedOperation "java/lang/UnsupportedOperationException"
#define ERuntime "java/lang/RuntimeException"
#define EError "java/lang/Error"
#define ELastError "com/sun/jna/LastErrorException"
extern void throwByName(JNIEnv *env, const char *name, const char *msg);
extern jobject newJavaPointer(JNIEnv *, void *);
extern char get_jtype(JNIEnv*, jclass);
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* jnidispatch_callback_init(JNIEnv*);
extern void jnidispatch_callback_dispose(JNIEnv*);
extern callback* create_callback(JNIEnv*, jobject, jobject,
jobjectArray, jclass,
callconv_t);
callconv_t, jboolean);
extern void free_callback(JNIEnv*, callback*);
extern void extract_value(JNIEnv*, jobject, void*, size_t size);
extern jobject new_object(JNIEnv*, char, void*);
extern void extract_value(JNIEnv*, jobject, void*, size_t, jboolean);
extern jobject new_object(JNIEnv*, char, void*, jboolean);
extern jboolean is_protected();
extern int get_conversion_flag(JNIEnv*, jclass);
extern jboolean ffi_error(JNIEnv*,const char*,ffi_status);
extern jobject newJavaPointer(JNIEnv*, void*);
extern jstring newJavaString(JNIEnv*, const char*, jboolean);
extern jobject newJavaWString(JNIEnv*, const wchar_t*);
extern jobject newJavaStructure(JNIEnv*, void*, jclass, jboolean);
extern jobject newJavaCallback(JNIEnv*, void*, jclass);
extern void* getNativeString(JNIEnv*, jstring, jboolean);
extern void* getNativeAddress(JNIEnv*, jobject);
extern void* getStructureAddress(JNIEnv*, jobject);
extern void* getCallbackAddress(JNIEnv*, jobject);
extern jlong getIntegerTypeValue(JNIEnv*, jobject);
extern void* getPointerTypeAddress(JNIEnv*, jobject);
extern void writeStructure(JNIEnv*, jobject);
extern jclass getNativeType(JNIEnv*, jclass);
extern void toNative(JNIEnv*, jobject, void*, size_t, jboolean);
extern jclass fromNative(JNIEnv*, jclass, ffi_type*, void*, jboolean);
/* Native memory fault protection */
#ifdef HAVE_PROTECTION
+125
Ver Arquivo
@@ -1,3 +1,66 @@
2009-06-16 Wim Lewis <wiml@hhhh.org>
* src/powerpc/ffi.c: Avoid clobbering cr3 and cr4, which are
supposed to be callee-saved.
* src/powerpc/sysv.S (small_struct_return_value): Fix overrun of
return buffer for odd-size structs.
2009-06-16 Andreas Tobler <a.tobler@schweiz.org>
PR libffi/40444
* testsuite/lib/libffi-dg.exp (libffi_target_compile): Add
allow_stack_execute for Darwin.
2009-06-16 Andrew Haley <aph@redhat.com>
* configure.ac (TARGETDIR): Add missing blank lines.
* configure: Regenerate.
2009-06-16 Andrew Haley <aph@redhat.com>
* testsuite/libffi.call/err_bad_typedef.c: xfail everywhere.
* testsuite/libffi.call/err_bad_abi.c: Likewise.
2009-06-11 Kaz Kojima <kkojima@gcc.gnu.org>
* testsuite/libffi.call/cls_longdouble_va.c: Add xfail sh*-*-linux-*.
* testsuite/libffi.call/err_bad_abi.c: Add xfail sh*-*-*.
* testsuite/libffi.call/err_bad_typedef.c: Likewise.
2009-06-08 Andrew Haley <aph@redhat.com>
* testsuite/libffi.call/err_bad_abi.c: Add xfails.
* testsuite/libffi.call/cls_longdouble_va.c: Add xfails.
* testsuite/libffi.call/cls_dbls_struct.c: Add xfail x86_64-*-linux-*.
* testsuite/libffi.call/err_bad_typedef.c: Add xfails.
* testsuite/libffi.call/stret_medium2.c: Add __UNUSED__ to args.
* testsuite/libffi.call/stret_medium.c: Likewise.
* testsuite/libffi.call/stret_large2.c: Likewise.
* testsuite/libffi.call/stret_large.c: Likewise.
2009-06-05 Andrew Haley <aph@redhat.com>
* src/x86/win32.S (_ffi_closure_STDCALL): Import from gcc.
2009-05-22 Dave Korn <dave.korn.cygwin@gmail.com>
* src/x86/win32.S (_ffi_closure_STDCALL): New function.
(.eh_frame): Add FDE for it.
2009-05-22 Dave Korn <dave.korn.cygwin@gmail.com>
* configure.ac: Also check if assembler supports pc-relative
relocs on X86_WIN32 targets.
* configure: Regenerate.
* src/x86/win32.S (ffi_prep_args): Declare extern, not global.
(_ffi_call_SYSV): Add missing function type symbol .def and
add EH markup labels.
(_ffi_call_STDCALL): Likewise.
(_ffi_closure_SYSV): Likewise.
(_ffi_closure_raw_SYSV): Likewise.
(.eh_frame): Add hand-crafted EH data.
2008-12-18 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
PR libffi/26048
@@ -12,6 +75,68 @@
(.Lload_table): Likewise.
(.eh_frame): Only use SYMBOL-. iff HAVE_AS_X86_PCREL.
2008-11-21 Eric Botcazou <ebotcazou@adacore.com>
* src/sparc/ffi.c (ffi_prep_cif_machdep): Add support for
signed/unsigned int8/16 return values.
* src/sparc/v8.S (ffi_call_v8): Likewise.
(ffi_closure_v8): Likewise.
2008-08-25 Andreas Tobler <a.tobler@schweiz.org>
* src/powerpc/ffitarget.h (ffi_abi): Add FFI_LINUX and
FFI_LINUX_SOFT_FLOAT to the POWERPC_FREEBSD enum.
Add note about flag bits used for FFI_SYSV_TYPE_SMALL_STRUCT.
Adjust copyright notice.
* src/powerpc/ffi.c: Add two new flags to indicate if we have one
register or two register to use for FFI_SYSV structs.
(ffi_prep_cif_machdep): Pass the right register flag introduced above.
(ffi_closure_helper_SYSV): Fix the return type for
FFI_SYSV_TYPE_SMALL_STRUCT. Comment.
Adjust copyright notice.
2008-07-16 Kaz Kojima <kkojima@gcc.gnu.org>
* src/sh/ffi.c (ffi_prep_closure_loc): Turn INSN into an unsigned
int.
2008-03-26 Kaz Kojima <kkojima@gcc.gnu.org>
* src/sh/sysv.S: Add .note.GNU-stack on Linux.
* src/sh64/sysv.S: Likewise.
2008-03-26 Daniel Jacobowitz <dan@debian.org>
* src/arm/sysv.S: Fix ARM comment marker.
2008-03-26 Jakub Jelinek <jakub@redhat.com>
* src/alpha/osf.S: Add .note.GNU-stack on Linux.
* src/s390/sysv.S: Likewise.
* src/powerpc/ppc_closure.S: Likewise.
* src/powerpc/sysv.S: Likewise.
* src/x86/unix64.S: Likewise.
* src/x86/sysv.S: Likewise.
* src/sparc/v8.S: Likewise.
* src/sparc/v9.S: Likewise.
* src/m68k/sysv.S: Likewise.
* src/arm/sysv.S: Likewise.
2008-02-12 Bjoern Koenig <bkoenig@alpha-tierchen.de>
Andreas Tobler <a.tobler@schweiz.org>
* configure.ac: Add amd64-*-freebsd* target.
* configure: Regenerate.
2008-01-30 H.J. Lu <hongjiu.lu@intel.com>
PR libffi/34612
* src/x86/sysv.S (ffi_closure_SYSV): Pop 4 byte from stack when
returning struct.
* testsuite/libffi.call/call.exp: Add "-O2 -fomit-frame-pointer"
tests.
2008-01-24 David Edelsohn <edelsohn@gnu.org>
* configure: Regenerate.
+3 -3
Ver Arquivo
@@ -1,4 +1,4 @@
This is doc/libffi.info, produced by makeinfo version 4.13 from
This is doc/libffi.info, produced by makeinfo version 4.12 from
./doc/libffi.texi.
This manual is for Libffi, a portable foreign-function interface
@@ -510,8 +510,8 @@ Index
* ffi_type_ushort: Primitive Types. (line 53)
* ffi_type_void: Primitive Types. (line 10)
* Foreign Function Interface: Introduction. (line 31)
* void <1>: The Basics. (line 43)
* void: The Closure API. (line 27)
* void <1>: The Closure API. (line 20)
* void: The Basics. (line 43)

+8 -8
Ver Arquivo
@@ -14,14 +14,14 @@
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#define LIBFFI_ASM
+8 -8
Ver Arquivo
@@ -14,14 +14,14 @@
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#define LIBFFI_ASM
+8 -7
Ver Arquivo
@@ -43,11 +43,12 @@ enum {
FLAG_RETURNS_64BITS = 1 << (31-28),
FLAG_RETURNS_128BITS = 1 << (31-27), /* cr6 */
FLAG_SYSV_SMST_R4 = 1 << (31-26), /* use r4 for FFI_SYSV 8 byte
structs. */
FLAG_SYSV_SMST_R3 = 1 << (31-25), /* use r3 for FFI_SYSV 4 byte
structs. */
/* Bits (31-24) through (31-19) store shift value for SMST */
FLAG_SYSV_SMST_R4 = 1 << (31-16), /* cr4, use r4 for FFI_SYSV 8 byte
structs. */
FLAG_SYSV_SMST_R3 = 1 << (31-15), /* cr3, use r3 for FFI_SYSV 4 byte
structs. */
FLAG_ARG_NEEDS_COPY = 1 << (31- 7),
FLAG_FP_ARGUMENTS = 1 << (31- 6), /* cr1.eq; specified by ABI */
FLAG_4_GPR_ARGUMENTS = 1 << (31- 5),
@@ -685,14 +686,14 @@ ffi_prep_cif_machdep (ffi_cif *cif)
if (size <= 4)
{
flags |= FLAG_SYSV_SMST_R3;
flags |= 8 * (4 - size) << 4;
flags |= 8 * (4 - size) << 8;
break;
}
/* These structs are returned in r3 and r4. See above. */
if (size <= 8)
{
flags |= FLAG_SYSV_SMST_R4;
flags |= 8 * (8 - size) << 4;
flags |= FLAG_SYSV_SMST_R3 | FLAG_SYSV_SMST_R4;
flags |= 8 * (8 - size) << 8;
break;
}
}
+3 -3
Ver Arquivo
@@ -95,12 +95,12 @@ typedef enum ffi_abi {
/* For additional types like the below, take care about the order in
ppc_closures.S. They must follow after the FFI_TYPE_LAST. */
/* Needed for soft-float long-double-128 support. */
#define FFI_TYPE_UINT128 (FFI_TYPE_LAST + 1)
/* Needed for FFI_SYSV small structure returns.
We use two flag bits, (FLAG_SYSV_SMST_R3, FLAG_SYSV_SMST_R4) which are
defined in ffi.c, to determine the exact return type and its size. */
#define FFI_TYPE_UINT128 (FFI_TYPE_LAST + 1)
/* Needed for FFI_SYSV small structure returns. */
#define FFI_SYSV_TYPE_SMALL_STRUCT (FFI_TYPE_LAST + 2)
#if defined(POWERPC64) || defined(POWERPC_AIX)
+12 -23
Ver Arquivo
@@ -136,29 +136,18 @@ L(float_return_value):
b L(done_return_value)
L(small_struct_return_value):
mtcrf 0x10,%r31 /* cr3 */
bt- 15,L(smst_one_register)
mtcrf 0x08,%r31 /* cr4 */
bt- 16,L(smst_two_register)
b L(done_return_value)
L(smst_one_register):
rlwinm %r5,%r31,5+23,32-5,31 /* Extract the value to shift. */
slw %r3,%r3,%r5
stw %r3,0(%r30)
b L(done_return_value)
L(smst_two_register):
rlwinm %r5,%r31,5+23,32-5,31 /* Extract the value to shift. */
cmpwi %r5,0
subfic %r9,%r5,32
slw %r29,%r3,%r5
srw %r9,%r4,%r9
beq- L(smst_8byte)
or %r3,%r9,%r29
slw %r4,%r4,%r5
L(smst_8byte):
stw %r3,0(%r30)
stw %r4,4(%r30)
extrwi %r6,%r31,2,19 /* number of bytes padding = shift/8 */
mtcrf 0x02,%r31 /* copy flags to cr[24:27] (cr6) */
extrwi %r5,%r31,5,19 /* r5 <- number of bits of padding */
subfic %r6,%r6,4 /* r6 <- number of useful bytes in r3 */
bf- 25,L(done_return_value) /* struct in r3 ? if not, done. */
/* smst_one_register: */
slw %r3,%r3,%r5 /* Left-justify value in r3 */
mtxer %r6 /* move byte count to XER ... */
stswx %r3,0,%r30 /* ... and store that many bytes */
bf+ 26,L(done_return_value) /* struct in r3:r4 ? */
add %r6,%r6,%r30 /* adjust pointer */
stswi %r4,%r6,4 /* store last four bytes */
b L(done_return_value)
.LFE1:
+3 -11
Ver Arquivo
@@ -39,11 +39,9 @@ static ffi_status initialize_aggregate(ffi_type *arg)
FFI_ASSERT(arg != NULL);
FFI_ASSERT(arg->elements != NULL);
FFI_ASSERT(arg->size == 0);
if (arg->elements == NULL || arg->alignment != 0) {
return FFI_BAD_TYPEDEF;
}
FFI_ASSERT(arg->alignment == 0);
ptr = &(arg->elements[0]);
@@ -95,13 +93,7 @@ ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs,
ffi_type **ptr;
FFI_ASSERT(cif != NULL);
// FIXME: most targets have a broken definition of FFI_LAST_ABI
/*
if (abi <= FFI_FIRST_ABI || abi >= FFI_LAST_ABI) {
return FFI_BAD_ABI;
}
*/
FFI_ASSERT((abi > FFI_FIRST_ABI) && (abi <= FFI_DEFAULT_ABI));
cif->abi = abi;
cif->arg_types = atypes;
+8 -8
Ver Arquivo
@@ -14,14 +14,14 @@
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#define LIBFFI_ASM
+37 -22
Ver Arquivo
@@ -1,5 +1,5 @@
/* -----------------------------------------------------------------------
ffi.c - Copyright (c) 2003, 2004 Kaz Kojima
ffi.c - Copyright (c) 2003, 2004, 2006, 2007 Kaz Kojima
Copyright (c) 2008 Anthony Green
SuperH SHmedia Foreign Function Interface
@@ -56,9 +56,7 @@ return_type (ffi_type *arg)
/* ffi_prep_args is called by the assembly routine once stack space
has been allocated for the function's arguments */
/*@-exportheader@*/
void ffi_prep_args(char *stack, extended_cif *ecif)
/*@=exportheader@*/
{
register unsigned int i;
register unsigned int avn;
@@ -162,6 +160,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
int n, m;
int greg;
int freg;
int fpair = -1;
greg = (return_type (cif->rtype) == FFI_TYPE_STRUCT ? 1 : 0);
freg = 0;
@@ -177,7 +176,13 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
cif->bytes += sizeof (UINT64) - sizeof (float);
if (freg >= NFREGARG - 1)
continue;
freg++;
if (fpair < 0)
{
fpair = freg;
freg += 2;
}
else
fpair = -1;
cif->flags2 += ((cif->arg_types)[i]->type) << (2 * j++);
break;
@@ -186,7 +191,6 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
continue;
if ((freg + 1) < NFREGARG)
{
freg = (freg + 1) & ~1;
freg += 2;
cif->flags2 += ((cif->arg_types)[i]->type) << (2 * j++);
}
@@ -264,9 +268,7 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
else if ((rvalue == NULL) &&
(cif->rtype->type == FFI_TYPE_STRUCT))
{
/*@-sysunrecog@*/
ecif.rvalue = alloca(cif->rtype->size);
/*@=sysunrecog@*/
}
else
ecif.rvalue = rvalue;
@@ -274,10 +276,8 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
switch (cif->abi)
{
case FFI_SYSV:
/*@-usedef@*/
ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes,
cif->flags, cif->flags2, ecif.rvalue, fn);
/*@=usedef@*/
ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, cif->flags2,
ecif.rvalue, fn);
break;
default:
FFI_ASSERT(0);
@@ -294,10 +294,11 @@ extern void ffi_closure_SYSV (void);
extern void __ic_invalidate (void *line);
ffi_status
ffi_prep_closure (ffi_closure *closure,
ffi_cif *cif,
void (*fun)(ffi_cif*, void*, void**, void*),
void *user_data)
ffi_prep_closure_loc (ffi_closure *closure,
ffi_cif *cif,
void (*fun)(ffi_cif*, void*, void**, void*),
void *user_data,
void *codeloc)
{
unsigned int *tramp;
@@ -321,8 +322,8 @@ ffi_prep_closure (ffi_closure *closure,
tramp[2] = 0xcc000010 | (((UINT32) ffi_closure_SYSV) >> 16) << 10;
tramp[3] = 0xc8000010 | (((UINT32) ffi_closure_SYSV) & 0xffff) << 10;
tramp[4] = 0x6bf10600;
tramp[5] = 0xcc000010 | (((UINT32) closure) >> 16) << 10;
tramp[6] = 0xc8000010 | (((UINT32) closure) & 0xffff) << 10;
tramp[5] = 0xcc000010 | (((UINT32) codeloc) >> 16) << 10;
tramp[6] = 0xc8000010 | (((UINT32) codeloc) & 0xffff) << 10;
tramp[7] = 0x4401fff0;
closure->cif = cif;
@@ -330,7 +331,8 @@ ffi_prep_closure (ffi_closure *closure,
closure->user_data = user_data;
/* Flush the icache. */
asm volatile ("ocbwb %0,0; synco; icbi %0,0; synci" : : "r" (tramp));
asm volatile ("ocbwb %0,0; synco; icbi %1,0; synci" : : "r" (tramp),
"r"(codeloc));
return FFI_OK;
}
@@ -352,6 +354,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure, UINT64 *rvalue,
int i, avn;
int greg, freg;
ffi_cif *cif;
int fpair = -1;
cif = closure->cif;
avalue = alloca (cif->nargs * sizeof (void *));
@@ -360,7 +363,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure, UINT64 *rvalue,
returns the data directly to the caller. */
if (return_type (cif->rtype) == FFI_TYPE_STRUCT)
{
rvalue = *pgr;
rvalue = (UINT64 *) *pgr;
greg = 1;
}
else
@@ -404,11 +407,24 @@ ffi_closure_helper_SYSV (ffi_closure *closure, UINT64 *rvalue,
if ((*p_arg)->type == FFI_TYPE_FLOAT)
{
if (freg < NFREGARG - 1)
{
if (fpair >= 0)
{
avalue[i] = (UINT32 *) pfr + fpair;
fpair = -1;
}
else
{
#ifdef __LITTLE_ENDIAN__
avalue[i] = (UINT32 *) pfr + (1 ^ freg++);
fpair = freg;
avalue[i] = (UINT32 *) pfr + (1 ^ freg);
#else
avalue[i] = (UINT32 *) pfr + freg++;
fpair = 1 ^ freg;
avalue[i] = (UINT32 *) pfr + freg;
#endif
freg += 2;
}
}
else
#ifdef __LITTLE_ENDIAN__
avalue[i] = pgr + greg;
@@ -430,7 +446,6 @@ ffi_closure_helper_SYSV (ffi_closure *closure, UINT64 *rvalue,
avalue[i] = pgr + greg;
else
{
freg = (freg + 1) & ~1;
avalue[i] = pfr + (freg >> 1);
freg += 2;
}
+22 -13
Ver Arquivo
@@ -1,5 +1,5 @@
/* -----------------------------------------------------------------------
sysv.S - Copyright (c) 2003, 2004, 2008 Kaz Kojima
sysv.S - Copyright (c) 2003, 2004, 2006, 2008 Kaz Kojima
SuperH SHmedia Foreign Function Interface
@@ -14,14 +14,15 @@
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#define LIBFFI_ASM
@@ -85,6 +86,7 @@ ENTRY(ffi_call_SYSV)
addi r15, 64, r22
movi 0, r0
movi 0, r1
movi -1, r23
pt/l 1f, tr1
bnei/l r29, FFI_TYPE_STRUCT, tr1
@@ -107,9 +109,6 @@ ENTRY(ffi_call_SYSV)
.L_pass_d:
addi r0, 1, r0
addi r1, 1, r1
andi r1, ~1, r1
pt/l 3f, tr0
movi 12, r20
bge/l r1, r20, tr0
@@ -159,13 +158,23 @@ ENTRY(ffi_call_SYSV)
addi.l r15, 8, r15
3:
pt/l .L_pass, tr0
addi r1, 1, r1
blink tr0, r63
.L_pop_f:
pt/l .L_pop_f_tbl, tr1
pt/l 5f, tr2
gettr tr1, r20
bge/l r23, r63, tr2
add r1, r63, r23
shlli r1, 3, r21
addi r1, 2, r1
add r20, r21, r20
ptabs/l r20, tr1
blink tr1, r63
5:
addi r23, 1, r21
movi -1, r23
shlli r21, 3, r21
add r20, r21, r20
ptabs/l r20, tr1
blink tr1, r63
+16 -6
Ver Arquivo
@@ -308,14 +308,24 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
cif->flags = FFI_TYPE_STRUCT;
break;
case FFI_TYPE_SINT8:
case FFI_TYPE_UINT8:
case FFI_TYPE_SINT16:
case FFI_TYPE_UINT16:
if (cif->abi == FFI_V9)
cif->flags = FFI_TYPE_INT;
else
cif->flags = cif->rtype->type;
break;
case FFI_TYPE_SINT64:
case FFI_TYPE_UINT64:
if (cif->abi != FFI_V9)
{
cif->flags = FFI_TYPE_SINT64;
break;
}
/* FALLTHROUGH */
if (cif->abi == FFI_V9)
cif->flags = FFI_TYPE_INT;
else
cif->flags = FFI_TYPE_SINT64;
break;
default:
cif->flags = FFI_TYPE_INT;
break;
+56 -15
Ver Arquivo
@@ -73,21 +73,63 @@ _ffi_call_v8:
be,a done
st %f0, [%i4+0] ! (delay)
cmp %i3, FFI_TYPE_SINT64
be longlong
cmp %i3, FFI_TYPE_DOUBLE
bne done
nop
st %f0, [%i4+0]
st %f1, [%i4+4]
be,a double
st %f0, [%i4+0] ! (delay)
cmp %i3, FFI_TYPE_SINT8
be,a sint8
sll %o0, 24, %o0 ! (delay)
cmp %i3, FFI_TYPE_UINT8
be,a uint8
sll %o0, 24, %o0 ! (delay)
cmp %i3, FFI_TYPE_SINT16
be,a sint16
sll %o0, 16, %o0 ! (delay)
cmp %i3, FFI_TYPE_UINT16
be,a uint16
sll %o0, 16, %o0 ! (delay)
cmp %i3, FFI_TYPE_SINT64
be,a longlong
st %o0, [%i4+0] ! (delay)
done:
ret
restore
longlong:
double:
st %f1, [%i4+4]
ret
restore
sint8:
sra %o0, 24, %o0
st %o0, [%i4+0]
ret
restore
uint8:
srl %o0, 24, %o0
st %o0, [%i4+0]
ret
restore
sint16:
sra %o0, 16, %o0
st %o0, [%i4+0]
ret
restore
uint16:
srl %o0, 16, %o0
st %o0, [%i4+0]
ret
restore
longlong:
st %o1, [%i4+4]
ret
restore
@@ -148,7 +190,8 @@ ffi_closure_v8:
be done1
cmp %o0, FFI_TYPE_INT
be integer
be done1
ld [%fp-8], %i0
cmp %o0, FFI_TYPE_FLOAT
be,a done1
@@ -166,13 +209,11 @@ ffi_closure_v8:
cmp %o0, FFI_TYPE_STRUCT
be done2
! FFI_TYPE_SINT64
! FFI_TYPE_UINT64
ld [%fp-4], %i1
cmp %o0, FFI_TYPE_SINT64
be,a done1
ldd [%fp-8], %i0
integer:
ld [%fp-8], %i0
done1:
jmp %i7+8
restore
+10 -9
Ver Arquivo
@@ -15,15 +15,16 @@
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
-----------------------------------------------------------------------
*/
#ifndef __x86_64__
+7 -7
Ver Arquivo
@@ -277,16 +277,16 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
/* value address then we need to make one */
#ifdef X86_WIN64
if ((rvalue == NULL) &&
(cif->flags == FFI_TYPE_STRUCT
&& cif->rtype->size != 1 && cif->rtype->size != 2
&& cif->rtype->size != 4 && cif->rtype->size != 8))
if (rvalue == NULL
&& cif->flags == FFI_TYPE_STRUCT
&& cif->rtype->size != 1 && cif->rtype->size != 2
&& cif->rtype->size != 4 && cif->rtype->size != 8)
{
ecif.rvalue = alloca((cif->rtype->size + 0xF) & ~0xF);
}
#else
if ((rvalue == NULL) &&
cif->flags == FFI_TYPE_STRUCT)
if (rvalue == NULL
&& cif->flags == FFI_TYPE_STRUCT)
{
ecif.rvalue = alloca(cif->rtype->size);
}
@@ -450,7 +450,7 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
size_t z;
/* Align if necessary */
if ((sizeof(void *) - 1) & (size_t) argp) {
if ((sizeof(void*) - 1) & (size_t) argp) {
argp = (char *) ALIGN(argp, sizeof(void*));
}
+299 -39
Ver Arquivo
@@ -1,5 +1,5 @@
/* -----------------------------------------------------------------------
win32.S - Copyright (c) 1996, 1998, 2001, 2002 Red Hat, Inc.
win32.S - Copyright (c) 1996, 1998, 2001, 2002, 2009 Red Hat, Inc.
Copyright (c) 2001 John Beniton
Copyright (c) 2002 Ranjit Mathew
@@ -17,30 +17,33 @@
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
-----------------------------------------------------------------------
*/
#define LIBFFI_ASM
#include <fficonfig.h>
#include <ffi.h>
.text
.text
# This assumes we are using gas.
.balign 16
.globl _ffi_call_SYSV
.globl _ffi_call_SYSV
.def _ffi_call_SYSV; .scl 2; .type 32; .endef
_ffi_call_SYSV:
.LFB1:
pushl %ebp
.LCFI0:
movl %esp,%ebp
.LCFI1:
# Make room for all of the new args.
movl 16(%ebp),%ecx
subl %ecx,%esp
@@ -143,17 +146,19 @@ epilogue:
movl %ebp,%esp
popl %ebp
ret
.ffi_call_SYSV_end:
.LFE1:
# This assumes we are using gas.
.balign 16
.globl _ffi_call_STDCALL
.globl _ffi_call_STDCALL
.def _ffi_call_STDCALL; .scl 2; .type 32; .endef
_ffi_call_STDCALL:
.LFB2:
pushl %ebp
.LCFI2:
movl %esp,%ebp
.LCFI3:
# Make room for all of the new args.
movl 16(%ebp),%ecx
subl %ecx,%esp
@@ -254,29 +259,19 @@ sc_epilogue:
movl %ebp,%esp
popl %ebp
ret
.ffi_call_STDCALL_end:
.LFE2:
.globl _ffi_closure_STDCALL
_ffi_closure_STDCALL:
pushl %ebp
movl %esp, %ebp
subl $40, %esp
leal -24(%ebp), %edx
movl %edx, -12(%ebp) /* resp */
leal 12(%ebp), %edx /* account for stub return address on stack */
movl %edx, 4(%esp) /* args */
leal -12(%ebp), %edx
movl %edx, (%esp) /* &resp */
call _ffi_closure_SYSV_inner
movl -12(%ebp), %ecx
jmp .Lcls_return_result
.ffi_closure_STDCALL_end:
.globl _ffi_closure_SYSV
# This assumes we are using gas.
.balign 16
.globl _ffi_closure_SYSV
.def _ffi_closure_SYSV; .scl 2; .type 32; .endef
_ffi_closure_SYSV:
.LFB3:
pushl %ebp
.LCFI4:
movl %esp, %ebp
.LCFI5:
subl $40, %esp
leal -24(%ebp), %edx
movl %edx, -12(%ebp) /* resp */
@@ -286,7 +281,6 @@ _ffi_closure_SYSV:
movl %edx, (%esp) /* &resp */
call _ffi_closure_SYSV_inner
movl -12(%ebp), %ecx
.Lcls_return_result:
cmpl $FFI_TYPE_INT, %eax
je .Lcls_retint
cmpl $FFI_TYPE_FLOAT, %eax
@@ -328,6 +322,7 @@ _ffi_closure_SYSV:
movswl (%ecx), %eax
jmp .Lcls_epilogue
.ffi_closure_SYSV_end:
.LFE3:
#if !FFI_NO_RAW_API
@@ -336,12 +331,18 @@ _ffi_closure_SYSV:
#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
#define CIF_FLAGS_OFFSET 20
.balign 16
.globl _ffi_closure_raw_SYSV
# This assumes we are using gas.
.balign 16
.globl _ffi_closure_raw_SYSV
.def _ffi_closure_raw_SYSV; .scl 2; .type 32; .endef
_ffi_closure_raw_SYSV:
.LFB4:
pushl %ebp
.LCFI6:
movl %esp, %ebp
.LCFI7:
pushl %esi
.LCFI8:
subl $36, %esp
movl RAW_CLOSURE_CIF_OFFSET(%eax), %esi /* closure->cif */
movl RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
@@ -385,5 +386,264 @@ _ffi_closure_raw_SYSV:
movl -20(%ebp), %edx
jmp .Lrcls_epilogue
.ffi_closure_raw_SYSV_end:
.LFE4:
#endif /* !FFI_NO_RAW_API */
# This assumes we are using gas.
.balign 16
.globl _ffi_closure_STDCALL
.def _ffi_closure_STDCALL; .scl 2; .type 32; .endef
_ffi_closure_STDCALL:
.LFB5:
pushl %ebp
.LCFI9:
movl %esp, %ebp
.LCFI10:
subl $40, %esp
leal -24(%ebp), %edx
movl %edx, -12(%ebp) /* resp */
leal 12(%ebp), %edx /* account for stub return address on stack */
movl %edx, 4(%esp) /* args */
leal -12(%ebp), %edx
movl %edx, (%esp) /* &resp */
call _ffi_closure_SYSV_inner
movl -12(%ebp), %ecx
/* It would be nice to just share this code with the
duplicate sequence in _ffi_closure_SYSV, if only
there were some way to represent that in the EH info. */
cmpl $FFI_TYPE_INT, %eax
je .Lscls_retint
cmpl $FFI_TYPE_FLOAT, %eax
je .Lscls_retfloat
cmpl $FFI_TYPE_DOUBLE, %eax
je .Lscls_retdouble
cmpl $FFI_TYPE_LONGDOUBLE, %eax
je .Lscls_retldouble
cmpl $FFI_TYPE_SINT64, %eax
je .Lscls_retllong
cmpl $FFI_TYPE_SINT8, %eax /* 1-byte struct */
je .Lscls_retstruct1
cmpl $FFI_TYPE_SINT16, %eax /* 2-bytes struct */
je .Lscls_retstruct2
.Lscls_epilogue:
movl %ebp, %esp
popl %ebp
ret
.Lscls_retint:
movl (%ecx), %eax
jmp .Lscls_epilogue
.Lscls_retfloat:
flds (%ecx)
jmp .Lscls_epilogue
.Lscls_retdouble:
fldl (%ecx)
jmp .Lscls_epilogue
.Lscls_retldouble:
fldt (%ecx)
jmp .Lscls_epilogue
.Lscls_retllong:
movl (%ecx), %eax
movl 4(%ecx), %edx
jmp .Lscls_epilogue
.Lscls_retstruct1:
movsbl (%ecx), %eax
jmp .Lscls_epilogue
.Lscls_retstruct2:
movswl (%ecx), %eax
jmp .Lscls_epilogue
.ffi_closure_STDCALL_end:
.LFE5:
.section .eh_frame,"w"
.Lframe1:
.LSCIE1:
.long .LECIE1-.LASCIE1 /* Length of Common Information Entry */
.LASCIE1:
.long 0x0 /* CIE Identifier Tag */
.byte 0x1 /* CIE Version */
#ifdef __PIC__
.ascii "zR\0" /* CIE Augmentation */
#else
.ascii "\0" /* CIE Augmentation */
#endif
.byte 0x1 /* .uleb128 0x1; CIE Code Alignment Factor */
.byte 0x7c /* .sleb128 -4; CIE Data Alignment Factor */
.byte 0x8 /* CIE RA Column */
#ifdef __PIC__
.byte 0x1 /* .uleb128 0x1; Augmentation size */
.byte 0x1b /* FDE Encoding (pcrel sdata4) */
#endif
.byte 0xc /* DW_CFA_def_cfa CFA = r4 + 4 = 4(%esp) */
.byte 0x4 /* .uleb128 0x4 */
.byte 0x4 /* .uleb128 0x4 */
.byte 0x88 /* DW_CFA_offset, column 0x8 %eip at CFA + 1 * -4 */
.byte 0x1 /* .uleb128 0x1 */
.align 4
.LECIE1:
.LSFDE1:
.long .LEFDE1-.LASFDE1 /* FDE Length */
.LASFDE1:
.long .LASFDE1-.Lframe1 /* FDE CIE offset */
#if defined __PIC__ && defined HAVE_AS_X86_PCREL
.long .LFB1-. /* FDE initial location */
#else
.long .LFB1
#endif
.long .LFE1-.LFB1 /* FDE address range */
#ifdef __PIC__
.byte 0x0 /* .uleb128 0x0; Augmentation size */
#endif
/* DW_CFA_xxx CFI instructions go here. */
.byte 0x4 /* DW_CFA_advance_loc4 */
.long .LCFI0-.LFB1
.byte 0xe /* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */
.byte 0x8 /* .uleb128 0x8 */
.byte 0x85 /* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */
.byte 0x2 /* .uleb128 0x2 */
.byte 0x4 /* DW_CFA_advance_loc4 */
.long .LCFI1-.LCFI0
.byte 0xd /* DW_CFA_def_cfa_register CFA = r5 = %ebp */
.byte 0x5 /* .uleb128 0x5 */
/* End of DW_CFA_xxx CFI instructions. */
.align 4
.LEFDE1:
.LSFDE2:
.long .LEFDE2-.LASFDE2 /* FDE Length */
.LASFDE2:
.long .LASFDE2-.Lframe1 /* FDE CIE offset */
#if defined __PIC__ && defined HAVE_AS_X86_PCREL
.long .LFB2-. /* FDE initial location */
#else
.long .LFB2
#endif
.long .LFE2-.LFB2 /* FDE address range */
#ifdef __PIC__
.byte 0x0 /* .uleb128 0x0; Augmentation size */
#endif
/* DW_CFA_xxx CFI instructions go here. */
.byte 0x4 /* DW_CFA_advance_loc4 */
.long .LCFI2-.LFB2
.byte 0xe /* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */
.byte 0x8 /* .uleb128 0x8 */
.byte 0x85 /* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */
.byte 0x2 /* .uleb128 0x2 */
.byte 0x4 /* DW_CFA_advance_loc4 */
.long .LCFI3-.LCFI2
.byte 0xd /* DW_CFA_def_cfa_register CFA = r5 = %ebp */
.byte 0x5 /* .uleb128 0x5 */
/* End of DW_CFA_xxx CFI instructions. */
.align 4
.LEFDE2:
.LSFDE3:
.long .LEFDE3-.LASFDE3 /* FDE Length */
.LASFDE3:
.long .LASFDE3-.Lframe1 /* FDE CIE offset */
#if defined __PIC__ && defined HAVE_AS_X86_PCREL
.long .LFB3-. /* FDE initial location */
#else
.long .LFB3
#endif
.long .LFE3-.LFB3 /* FDE address range */
#ifdef __PIC__
.byte 0x0 /* .uleb128 0x0; Augmentation size */
#endif
/* DW_CFA_xxx CFI instructions go here. */
.byte 0x4 /* DW_CFA_advance_loc4 */
.long .LCFI4-.LFB3
.byte 0xe /* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */
.byte 0x8 /* .uleb128 0x8 */
.byte 0x85 /* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */
.byte 0x2 /* .uleb128 0x2 */
.byte 0x4 /* DW_CFA_advance_loc4 */
.long .LCFI5-.LCFI4
.byte 0xd /* DW_CFA_def_cfa_register CFA = r5 = %ebp */
.byte 0x5 /* .uleb128 0x5 */
/* End of DW_CFA_xxx CFI instructions. */
.align 4
.LEFDE3:
#if !FFI_NO_RAW_API
.LSFDE4:
.long .LEFDE4-.LASFDE4 /* FDE Length */
.LASFDE4:
.long .LASFDE4-.Lframe1 /* FDE CIE offset */
#if defined __PIC__ && defined HAVE_AS_X86_PCREL
.long .LFB4-. /* FDE initial location */
#else
.long .LFB4
#endif
.long .LFE4-.LFB4 /* FDE address range */
#ifdef __PIC__
.byte 0x0 /* .uleb128 0x0; Augmentation size */
#endif
/* DW_CFA_xxx CFI instructions go here. */
.byte 0x4 /* DW_CFA_advance_loc4 */
.long .LCFI6-.LFB4
.byte 0xe /* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */
.byte 0x8 /* .uleb128 0x8 */
.byte 0x85 /* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */
.byte 0x2 /* .uleb128 0x2 */
.byte 0x4 /* DW_CFA_advance_loc4 */
.long .LCFI7-.LCFI6
.byte 0xd /* DW_CFA_def_cfa_register CFA = r5 = %ebp */
.byte 0x5 /* .uleb128 0x5 */
.byte 0x4 /* DW_CFA_advance_loc4 */
.long .LCFI8-.LCFI7
.byte 0x86 /* DW_CFA_offset, column 0x6 %esi at CFA + 3 * -4 */
.byte 0x3 /* .uleb128 0x3 */
/* End of DW_CFA_xxx CFI instructions. */
.align 4
.LEFDE4:
#endif /* !FFI_NO_RAW_API */
.LSFDE5:
.long .LEFDE5-.LASFDE5 /* FDE Length */
.LASFDE5:
.long .LASFDE5-.Lframe1 /* FDE CIE offset */
#if defined __PIC__ && defined HAVE_AS_X86_PCREL
.long .LFB5-. /* FDE initial location */
#else
.long .LFB5
#endif
.long .LFE5-.LFB5 /* FDE address range */
#ifdef __PIC__
.byte 0x0 /* .uleb128 0x0; Augmentation size */
#endif
/* DW_CFA_xxx CFI instructions go here. */
.byte 0x4 /* DW_CFA_advance_loc4 */
.long .LCFI9-.LFB5
.byte 0xe /* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */
.byte 0x8 /* .uleb128 0x8 */
.byte 0x85 /* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */
.byte 0x2 /* .uleb128 0x2 */
.byte 0x4 /* DW_CFA_advance_loc4 */
.long .LCFI10-.LCFI9
.byte 0xd /* DW_CFA_def_cfa_register CFA = r5 = %ebp */
.byte 0x5 /* .uleb128 0x5 */
/* End of DW_CFA_xxx CFI instructions. */
.align 4
.LEFDE5:
@@ -181,6 +181,13 @@ proc libffi_target_compile { source dest type options } {
lappend options "additional_flags=-I${libffi_include} -I${srcdir}/../include -I${libffi_include}/.."
lappend options "additional_flags=${libffi_link_flags}"
# Darwin needs a stack execution allowed flag.
if { [istarget "*-*-darwin9*"] || [istarget "*-*-darwin1*"]
|| [istarget "*-*-darwin2*"] } {
lappend options "additional_flags=-Wl,-allow_stack_execute"
}
# If you're building the compiler with --prefix set to a place
# where it's not yet installed, then the linker won't be able to
# find the libgcc used by libffi.dylib. We could pass the
@@ -22,7 +22,7 @@ cls_struct_align cls_struct_align_fn(struct cls_struct_align a1,
result.b = a1.b + a2.b;
result.c = a1.c + a2.c;
printf("%d %" PRId64 " %d %d %" PRId64 " %d: %d %" PRId64 " %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c, result.a, result.b, result.c);
printf("%d %" PRIdLL " %d %d %" PRIdLL " %d: %d %" PRIdLL " %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c, result.a, result.b, result.c);
return result;
}
@@ -77,14 +77,14 @@ int main (void)
ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl);
/* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */
printf("res: %d %" PRId64 " %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
printf("res: %d %" PRIdLL " %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
/* { dg-output "\nres: 13 14271 140" } */
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK);
res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl);
/* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
printf("res: %d %" PRId64 " %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
printf("res: %d %" PRIdLL " %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
/* { dg-output "\nres: 13 14271 140" } */
exit(0);
@@ -23,7 +23,7 @@ cls_struct_align cls_struct_align_fn(struct cls_struct_align a1,
result.b = a1.b + a2.b;
result.c = a1.c + a2.c;
printf("%d %" PRId64 " %d %d %" PRId64 " %d: %d %" PRId64 " %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c, result.a, result.b, result.c);
printf("%d %" PRIdLL " %d %d %" PRIdLL " %d: %d %" PRIdLL " %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c, result.a, result.b, result.c);
return result;
}
@@ -78,14 +78,14 @@ int main (void)
ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl);
/* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */
printf("res: %d %" PRId64 " %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
printf("res: %d %" PRIdLL " %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
/* { dg-output "\nres: 13 14271 140" } */
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK);
res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl);
/* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
printf("res: %d %" PRId64 " %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
printf("res: %d %" PRIdLL " %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
/* { dg-output "\nres: 13 14271 140" } */
exit(0);
@@ -57,7 +57,7 @@ int main(int argc __UNUSED__, char** argv __UNUSED__)
CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_gn, NULL, code) == FFI_OK);
((void*(*)(Dbls))(code))(arg);
/* { dg-output "1.0 2.0\n" } */
/* { dg-output "1.0 2.0\n" { xfail x86_64-*-linux-* } } */
closure_test_fn(arg);
/* { dg-output "1.0 2.0\n" } */
@@ -42,9 +42,9 @@ int main (void)
args[2] = NULL;
ffi_call(&cif, FFI_FN(printf), &res, args);
// { dg-output "7.0" }
// { dg-output "7.0" { xfail i*86-*-linux-* x86_64-*-linux-* } }
printf("res: %d\n", (int) res);
// { dg-output "\nres: 4" }
// { dg-output "\nres: 4" { xfail i*86-*-linux-* x86_64-*-linux-* } }
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_longdouble_va_fn, NULL, code) == FFI_OK);
@@ -12,7 +12,7 @@ static void cls_ret_ulonglong_fn(ffi_cif* cif __UNUSED__, void* resp,
{
*(unsigned long long *)resp= *(unsigned long long *)args[0];
printf("%" PRIu64 ": %" PRIu64 "\n",*(unsigned long long *)args[0],
printf("%" PRIuLL ": %" PRIuLL "\n",*(unsigned long long *)args[0],
*(unsigned long long *)(resp));
}
typedef unsigned long long (*cls_ret_ulonglong)(unsigned long long);
@@ -34,12 +34,12 @@ int main (void)
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_ulonglong_fn, NULL, code) == FFI_OK);
res = (*((cls_ret_ulonglong)code))(214LL);
/* { dg-output "214: 214" } */
printf("res: %" PRId64 "\n", res);
printf("res: %" PRIdLL "\n", res);
/* { dg-output "\nres: 214" } */
res = (*((cls_ret_ulonglong)code))(9223372035854775808LL);
/* { dg-output "\n9223372035854775808: 9223372035854775808" } */
printf("res: %" PRId64 "\n", res);
printf("res: %" PRIdLL "\n", res);
/* { dg-output "\nres: 9223372035854775808" } */
exit(0);
@@ -4,7 +4,7 @@
PR: none.
Originator: Blake Chaffin 6/6/2007 */
/* { dg-do run { xfail mips*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
/* { dg-do run { xfail *-*-* } } */
#include "ffitest.h"
static void
@@ -4,7 +4,7 @@
PR: none.
Originator: Blake Chaffin 6/6/2007 */
/* { dg-do run { xfail mips*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
/* { dg-do run { xfail *-*-* } } */
#include "ffitest.h"
int main (void)
@@ -45,6 +45,15 @@
#endif
/* MinGW kludge. */
#ifdef WIN64
#define PRIdLL "PRId64"
#define PRIuLL "PRIu64"
#else
#define PRIdLL "lld"
#define PRIuLL "llu"
#endif
#ifdef USING_MMAP
static inline void *
allocate_mmap (size_t size)
@@ -4,7 +4,7 @@
PR: none.
Originator: From the original ffitest.c */
/* { dg-excess-errors { target x86_64-*-mingw* x86_64-*-cygwin* } } */
/* { dg-excess-errors "" { target x86_64-*-mingw* x86_64-*-cygwin* } } */
/* { dg-do run { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */
#include "ffitest.h"
@@ -5,10 +5,10 @@
Originator: Blake Chaffin 6/18/2007
*/
/* { dg-excess-errors { target x86_64-*-mingw* x86_64-*-cygwin* } } */
/* { dg-excess-errors "" { target x86_64-*-mingw* x86_64-*-cygwin* i*86-*-linux-* x86_64-*-linux-* } } */
/* { dg-do run { xfail mips*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
/* { dg-options -mlong-double-128 { target powerpc64*-*-* } } */
/* { dg-output "" { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */
/* { dg-output "" { xfail x86_64-*-mingw* x86_64-*-cygwin* i*86-*-linux-* x86_64-*-linux-* } } */
#include <stdint.h>
@@ -36,7 +36,7 @@ int main (void)
ll2 = 11111111;
ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
printf("res: %" PRId64 ", %" PRId64 "\n", rlonglong, ll0 + ll1 + ll2);
printf("res: %" PRIdLL ", %" PRIdLL "\n", rlonglong, ll0 + ll1 + ll2);
/* { dg-output "res: 11111133333222, 11111133333222" } */
exit(0);
}
@@ -6,7 +6,7 @@
PR: none.
Originator: Blake Chaffin 6/21/2007 */
/* { dg-do run { xfail mips*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
/* { dg-do run { xfail mips*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
#include "ffitest.h"
// 13 FPRs: 104 bytes
@@ -6,7 +6,7 @@
PR: none.
Originator: Blake Chaffin 6/21/2007 */
/* { dg-do run { xfail mips*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
/* { dg-do run { xfail mips*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
#include "ffitest.h"
// 13 FPRs: 104 bytes
@@ -6,7 +6,7 @@
PR: none.
Originator: Blake Chaffin 6/21/2007 */
/* { dg-do run { xfail mips*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
/* { dg-do run { xfail mips*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
#include "ffitest.h"
typedef struct struct_72byte {
@@ -6,7 +6,7 @@
PR: none.
Originator: Blake Chaffin 6/21/2007 */
/* { dg-do run { xfail mips*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
/* { dg-do run { xfail mips*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
#include "ffitest.h"
typedef struct struct_72byte {
@@ -39,7 +39,7 @@ struct_72byte cls_struct_72byte_fn(
result.h = b0.h + b1.h + b2.h + b3.h;
result.i = b0.i + b1.i + b2.i + b3.i;
printf("%g %g %g %g %g %g %g %g %" PRId64 "\n", result.a, result.b, result.c,
printf("%g %g %g %g %g %g %g %g %" PRIdLL "\n", result.a, result.b, result.c,
result.d, result.e, result.f, result.g, result.h, result.i);
return result;
@@ -107,7 +107,7 @@ int main (void)
ffi_call(&cif, FFI_FN(cls_struct_72byte_fn), &res_dbl, args_dbl);
/* { dg-output "22 15 17 25 6 13 19 18 16" } */
printf("res: %g %g %g %g %g %g %g %g %" PRId64 "\n", res_dbl.a, res_dbl.b, res_dbl.c,
printf("res: %g %g %g %g %g %g %g %g %" PRIdLL "\n", res_dbl.a, res_dbl.b, res_dbl.c,
res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h, res_dbl.i);
/* { dg-output "\nres: 22 15 17 25 6 13 19 18 16" } */
@@ -116,7 +116,7 @@ int main (void)
res_dbl = ((struct_72byte(*)(struct_72byte, struct_72byte,
struct_72byte, struct_72byte))(code))(e_dbl, f_dbl, g_dbl, h_dbl);
/* { dg-output "\n22 15 17 25 6 13 19 18 16" } */
printf("res: %g %g %g %g %g %g %g %g %" PRId64 "\n", res_dbl.a, res_dbl.b, res_dbl.c,
printf("res: %g %g %g %g %g %g %g %g %" PRIdLL "\n", res_dbl.a, res_dbl.b, res_dbl.c,
res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h, res_dbl.i);
/* { dg-output "\nres: 22 15 17 25 6 13 19 18 16" } */
@@ -43,6 +43,16 @@
#endif
/* MinGW kludge. */
#ifdef WIN64
#define PRIdLL "PRId64"
#define PRIuLL "PRIu64"
#else
#define PRIdLL "lld"
#define PRIuLL "llu"
#endif
#ifdef USING_MMAP
static inline void *
allocate_mmap (size_t size)
@@ -6,6 +6,7 @@
/* { dg-do run } */
#include "ffitestcxx.h"
#include <stdint.h>
void
closure_test_fn(ffi_cif* cif __UNUSED__, void* resp __UNUSED__,
+4 -8
Ver Arquivo
@@ -77,11 +77,7 @@ _exc_handler(struct _EXCEPTION_RECORD* exception_record,
#define PROTECTED_END(ONERR) } __except((PROTECT)?EXCEPTION_EXECUTE_HANDLER:EXCEPTION_CONTINUE_SEARCH) { ONERR; }
#else
#ifdef _WIN64
// FIXME: mingw64 is untested
#define SEH_TRY(ER) \
__asm__ ("pushq %0;pushq %%gs:0;movq %%rsp,%%gs:0;" : : "g" (&(ER)))
#define SEH_CATCH(ER) \
__asm__ ("movq (%%rsp),%%rax;movq %%rax,%%gs:0;addq $16,%%rsp" : : : "%rax")
#error "GCC does not implement SEh"
#else
#define SEH_TRY(ER) \
__asm__ ("movl %%fs:0, %0" : "=r" ((ER).ex_reg.prev)); \
@@ -115,11 +111,14 @@ _exc_handler(struct _EXCEPTION_RECORD* exception_record,
#endif /* !_MSC_VER */
#else // _WIN32
// Most other platforms support signals
// Catch both SIGSEGV and SIGBUS
#include <signal.h>
#include <setjmp.h>
static jmp_buf _context;
static void* _old_segv_handler = NULL;
static void* _old_bus_handler = NULL;
static volatile int _error;
static void _exc_handler(int sig) {
if (sig == SIGSEGV || sig == SIGBUS) {
@@ -128,9 +127,6 @@ static void _exc_handler(int sig) {
}
#define PROTECTED_START() \
void* _old_segv_handler; \
void* _old_bus_handler; \
int _error = 0; \
if (PROTECT) { \
_old_segv_handler = signal(SIGSEGV, _exc_handler); \
_old_bus_handler = signal(SIGBUS, _exc_handler); \
+43 -1
Ver Arquivo
@@ -19,6 +19,7 @@ extern "C" {
#include <wchar.h>
#include <stdio.h>
#include <stdarg.h>
#include <errno.h>
#ifdef _MSC_VER
typedef signed char int8_t;
@@ -30,6 +31,11 @@ typedef __int64 int64_t;
#endif
#ifdef _WIN32
#ifndef UNICODE
#define UNICODE
#endif
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define EXPORT __declspec(dllexport)
#else
#define EXPORT
@@ -66,6 +72,15 @@ struct CheckFieldAlignment {
static int _callCount;
EXPORT void
setLastError(int err) {
#ifdef _WIN32
SetLastError(err);
#else
errno = err;
#endif
}
EXPORT int
callCount() {
return ++_callCount;
@@ -331,6 +346,11 @@ incrementInt32ByReference(int32_t *arg) {
if (arg) ++*arg;
}
EXPORT void
incrementNativeLongByReference(long *arg) {
if (arg) ++*arg;
}
EXPORT void
incrementInt64ByReference(int64_t *arg) {
if (arg) ++*arg;
@@ -553,6 +573,28 @@ callInt32Callback(int32_t (*func)(int32_t arg, int32_t arg2),
return (*func)(arg, arg2);
}
EXPORT int32_t
callInt32CallbackRepeatedly(int32_t (*func)(int32_t arg, int32_t arg2),
int32_t arg, int32_t arg2, int32_t count) {
int i;
int sum = 0;
for (i=0;i < count;i++) {
sum += (*func)(arg, arg2);
}
return sum;
}
EXPORT long
callLongCallbackRepeatedly(long (*func)(long arg, long arg2),
long arg, long arg2, int32_t count) {
int i;
long sum = 0;
for (i=0;i < count;i++) {
sum += (*func)(arg, arg2);
}
return sum;
}
EXPORT long
callNativeLongCallback(long (*func)(long arg, long arg2),
long arg, long arg2) {
@@ -768,7 +810,7 @@ callInt32StdCallCallback(int32_t (__stdcall *func)(int32_t arg, int32_t arg2),
#include <jni.h>
#include <math.h>
JNIEXPORT jdouble JNICALL
Java_com_sun_jna_RawTest_00024JNI_cos(JNIEnv *env, jclass cls, jdouble x) {
Java_com_sun_jna_DirectTest_00024JNI_cos(JNIEnv *env, jclass cls, jdouble x) {
return cos(x);
}
+2 -1
Ver Arquivo
@@ -6,7 +6,7 @@
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<packaging>jar</packaging>
<version>3.1.0</version>
<version>3.2.1</version>
<name>Java Native Access</name>
<distributionManagement>
@@ -33,6 +33,7 @@
<tasks>
<!--<ant dir="." target="dist" />-->
<attachArtifact file="dist/jna.jar" />
<attachArtifact file="dist/examples.jar" />
<attachArtifact file="dist/src-mvn.zip" classifier="sources" type="jar"/>
</tasks>
</configuration>
+37 -1
Ver Arquivo
@@ -1,10 +1,46 @@
<a name="top"></a>
<h2>Release 3.2.1</h2>
<b>Features</b><br>
<ul>
<li>Add HRESULT, LONG mapping to W32API (marc strapetz).
</ul>
<b>Bug Fixes</b><br>
<ul>
<li>Fix definition of HWND_BROADCAST in W32API.
<li>Fix memory alignment checking (<a href="https://jna.dev.java.net/issues/show_bug.cgi?id=121">Issue 121</a>).
<li>Fix
Structure <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html#equals(java.lang.Object)">equals/hashCode</a>
implementation, based on current Java fields rather than strictly native
memory contents. Avoid using equals/hashCode when avoiding recursive
reads/writes.
</ul>
<h2>Release 3.2.0</h2>
<b>Features</b><br>
<ul>
<li>Handle String, Structure, Callback, Buffer, and primitive arrays in direct
mappings. Handle NativeMapped and TypeMapper, with optimized paths for
IntegerType and PointerType.
<li>Optionally throw errno/GetLastError as an exception. This is preferred to
(and more efficient than) calling Native.getLastError().
<li>Unload/delete native library unpacked from jna.jar if Native class is garbage collected. Only install shutdown hook if using the system class loader.
<li>Auto-write contiguous Structure arrays when first element is written.
<li>Support NativeMapped[] as function arguments for interface-mapped
libraries (<a href="https://jna.dev.java.net/issues/show_bug.cgi?id=90">Issue 90</a>).
<li>Enable function lookup within current process on Windows.
</ul>
<b>Bug Fixes</b><br>
<ul>
<li>Restrict recursive structure reads/writes by thread instead of globally.
This avoids potentially missed reads/writes with concurrent access (<a href="https://jna.dev.java.net/issues/show_bug.cgi?id=120">Issue 120</a>).
<li>Ensure Memory is not GC'd and freed if direct NIO buffers mapped to it are extant.
<li>Allow types derived from java.nio.Buffer as Structure fields.
</ul>
<h2>Release 3.1.0</h2>
<b>Features</b><br>
<ul>
<li>Add raw JNI mapping of static Java methods. Performance is about 10X that of traditional JNA interface mapping, although with less type conversion functionality.
<li>Add library option to allow passing/return of Java Objects.
<li>Allow handling of uncaught callback exceptions (<a href="https://jna.dev.java.net/issues/show_bug.cgi?id=63">Issue 63)</a>.
<li>Allow handling of uncaught callback exceptions (<a href="https://jna.dev.java.net/issues/show_bug.cgi?id=63">Issue 63</a>).
<li>Object oriented interface to X server (see contrib/x11)
<li>Make Memory class more accessible.
<li>Provide Structure ctor with Pointer argument (<a href="https://jna.dev.java.net/issues/show_bug.cgi?id=102">issue 102</a>).
+181 -91
Ver Arquivo
@@ -32,7 +32,7 @@ import java.util.WeakHashMap;
class CallbackReference extends WeakReference {
static final Map callbackMap = new WeakHashMap();
static final Map altCallbackMap = new WeakHashMap();
static final Map directCallbackMap = new WeakHashMap();
static final Map allocations = new WeakHashMap();
private static final Method PROXY_CALLBACK_METHOD;
@@ -51,83 +51,133 @@ class CallbackReference extends WeakReference {
* Java Callback. Otherwise, return a proxy to the native function pointer.
*/
public static Callback getCallback(Class type, Pointer p) {
if (p != null) {
if (!type.isInterface())
throw new IllegalArgumentException("Callback type must be an interface");
Map map = AltCallingConvention.class.isAssignableFrom(type)
? altCallbackMap : callbackMap;
synchronized(map) {
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;
}
return getCallback(type, p, false);
}
private static Callback getCallback(Class type, Pointer p, boolean direct) {
if (p == null) {
return null;
}
if (!type.isInterface())
throw new IllegalArgumentException("Callback type must be an interface");
Map map = direct ? directCallbackMap : callbackMap;
synchronized(map) {
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;
}
}
int ctype = AltCallingConvention.class.isAssignableFrom(type)
? Function.ALT_CONVENTION : Function.C_CONVENTION;
Map options = Native.getLibraryOptions(type);
NativeFunctionHandler h = new NativeFunctionHandler(p, ctype, options);
Callback cb = (Callback)Proxy.newProxyInstance(type.getClassLoader(), new Class[] { type }, h);
h.options.put(Function.OPTION_INVOKING_METHOD, getCallbackMethod(cb));
map.put(cb, null);
return cb;
}
int ctype = AltCallingConvention.class.isAssignableFrom(type)
? Function.ALT_CONVENTION : Function.C_CONVENTION;
Map foptions = new HashMap();
Map options = Native.getLibraryOptions(type);
if (options != null) {
foptions.putAll(options);
}
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);
map.put(cb, null);
return cb;
}
return null;
}
Pointer cbstruct;
// Keep a reference to avoid premature GC
// Keep a reference to the proxy to avoid premature GC of it
CallbackProxy proxy;
private CallbackReference(Callback callback, int callingConvention) {
Method method;
private CallbackReference(Callback callback, int callingConvention, boolean direct) {
super(callback);
TypeMapper mapper = Native.getTypeMapper(Native.findCallbackClass(callback.getClass()));
if (callback instanceof CallbackProxy) {
proxy = (CallbackProxy)callback;
}
else {
proxy = new DefaultCallbackProxy(getCallbackMethod(callback), mapper);
}
TypeMapper mapper = Native.getTypeMapper(callback.getClass());
Class[] nativeParamTypes;
Class returnType;
// Generate a list of parameter types that the native code can
// handle. Let the CallbackProxy do any further conversion
// to match the true Java callback method signature
Class[] nativeParamTypes = proxy.getParameterTypes();
Class returnType = proxy.getReturnType();
if (mapper != null) {
for (int i=0;i < nativeParamTypes.length;i++) {
FromNativeConverter rc = mapper.getFromNativeConverter(nativeParamTypes[i]);
if (rc != null) {
nativeParamTypes[i] = rc.nativeType();
// Check whether direct mapping may be used, or whether
// we need to fall back to conventional mapping
String arch = System.getProperty("os.arch").toLowerCase();
boolean ppc = "ppc".equals(arch) || "powerpc".equals(arch);
if (direct) {
Method m = getCallbackMethod(callback);
Class[] ptypes = m.getParameterTypes();
for (int i=0;i < ptypes.length;i++) {
// varargs w/FP args via ffi_call fails on ppc (darwin)
if (ppc && (ptypes[i] == float.class
|| ptypes[i] == double.class)) {
direct = false;
break;
}
// No TypeMapper support in native callback code
if (mapper != null
&& mapper.getFromNativeConverter(ptypes[i]) != null) {
direct = false;
break;
}
}
ToNativeConverter tn = mapper.getToNativeConverter(returnType);
if (tn != null) {
returnType = tn.nativeType();
if (mapper != null
&& mapper.getToNativeConverter(m.getReturnType()) != null) {
direct = false;
}
}
for (int i=0;i < nativeParamTypes.length;i++) {
nativeParamTypes[i] = getNativeType(nativeParamTypes[i]);
if (!isAllowableNativeType(nativeParamTypes[i])) {
String msg = "Callback argument " + nativeParamTypes[i]
if (direct) {
method = getCallbackMethod(callback);
nativeParamTypes = method.getParameterTypes();
returnType = method.getReturnType();
cbstruct = createNativeCallback(callback, method,
nativeParamTypes, returnType,
callingConvention, true);
}
else {
if (callback instanceof CallbackProxy) {
proxy = (CallbackProxy)callback;
}
else {
proxy = new DefaultCallbackProxy(getCallbackMethod(callback), mapper);
}
nativeParamTypes = proxy.getParameterTypes();
returnType = proxy.getReturnType();
// Generate a list of parameter types that the native code can
// handle. Let the CallbackProxy do any further conversion
// to match the true Java callback method signature
if (mapper != null) {
for (int i=0;i < nativeParamTypes.length;i++) {
FromNativeConverter rc = mapper.getFromNativeConverter(nativeParamTypes[i]);
if (rc != null) {
nativeParamTypes[i] = rc.nativeType();
}
}
ToNativeConverter tn = mapper.getToNativeConverter(returnType);
if (tn != null) {
returnType = tn.nativeType();
}
}
for (int i=0;i < nativeParamTypes.length;i++) {
nativeParamTypes[i] = getNativeType(nativeParamTypes[i]);
if (!isAllowableNativeType(nativeParamTypes[i])) {
String msg = "Callback argument " + nativeParamTypes[i]
+ " requires custom type conversion";
throw new IllegalArgumentException(msg);
}
}
returnType = getNativeType(returnType);
if (!isAllowableNativeType(returnType)) {
String msg = "Callback return type " + returnType
+ " requires custom type conversion";
throw new IllegalArgumentException(msg);
}
cbstruct = createNativeCallback(proxy, PROXY_CALLBACK_METHOD,
nativeParamTypes, returnType,
callingConvention, false);
}
returnType = getNativeType(returnType);
if (!isAllowableNativeType(returnType)) {
String msg = "Callback return type " + returnType
+ " requires custom type conversion";
throw new IllegalArgumentException(msg);
}
cbstruct = createNativeCallback(proxy, PROXY_CALLBACK_METHOD,
nativeParamTypes, returnType,
callingConvention);
}
private Class getNativeType(Class cls) {
@@ -154,14 +204,47 @@ class CallbackReference extends WeakReference {
if (m.getParameterTypes().length > Function.MAX_NARGS) {
String msg = "Method signature exceeds the maximum "
+ "parameter count: " + m;
throw new IllegalArgumentException(msg);
throw new UnsupportedOperationException(msg);
}
return m;
}
/** Find the first instance of an interface which implements the Callback
* interface or an interface derived from Callback, which defines an
* appropriate callback method.
*/
static Class findCallbackClass(Class type) {
if (!Callback.class.isAssignableFrom(type)) {
throw new IllegalArgumentException(type.getName() + " is not derived from com.sun.jna.Callback");
}
if (type.isInterface()) {
return type;
}
Class[] ifaces = type.getInterfaces();
for (int i=0;i < ifaces.length;i++) {
if (Callback.class.isAssignableFrom(ifaces[i])) {
try {
// Make sure it's got a recognizable callback method
getCallbackMethod(ifaces[i]);
return ifaces[i];
}
catch(IllegalArgumentException e) {
break;
}
}
}
if (Callback.class.isAssignableFrom(type.getSuperclass())) {
return findCallbackClass(type.getSuperclass());
}
return type;
}
private static Method getCallbackMethod(Callback callback) {
return getCallbackMethod(findCallbackClass(callback.getClass()));
}
private static Method getCallbackMethod(Class cls) {
// Look at only public methods defined by the Callback class
Class cls = Native.findCallbackClass(callback.getClass());
Method[] pubMethods = cls.getDeclaredMethods();
Method[] classMethods = cls.getMethods();
Set pmethods = new HashSet(Arrays.asList(pubMethods));
@@ -218,19 +301,25 @@ class CallbackReference extends WeakReference {
* given callback.
*/
public static Pointer getFunctionPointer(Callback cb) {
return getFunctionPointer(cb, false);
}
/** Native code calls this with direct=true. */
private static Pointer getFunctionPointer(Callback cb, boolean direct) {
Pointer fp = null;
if (cb == null) return null;
if (cb == null) {
return null;
}
if ((fp = getNativeFunctionPointer(cb)) != null) {
return fp;
}
int callingConvention = cb instanceof AltCallingConvention
? Function.ALT_CONVENTION : Function.C_CONVENTION;
Map map = callingConvention == Function.ALT_CONVENTION
? altCallbackMap : callbackMap;
Map map = direct ? directCallbackMap : callbackMap;
synchronized(map) {
CallbackReference cbref = (CallbackReference)map.get(cb);
if (cbref == null) {
cbref = new CallbackReference(cb, callingConvention);
cbref = new CallbackReference(cb, callingConvention, direct);
map.put(cb, cbref);
}
return cbref.getTrampoline();
@@ -281,9 +370,11 @@ class CallbackReference extends WeakReference {
if (fromNative[i] != null) {
FromNativeContext context =
new CallbackParameterContext(type, callbackMethod, args, i);
arg = fromNative[i].fromNative(arg, context);
callbackArgs[i] = fromNative[i].fromNative(arg, context);
}
else {
callbackArgs[i] = convertArgument(arg, type);
}
callbackArgs[i] = convertArgument(arg, type);
}
Object result = null;
@@ -379,10 +470,7 @@ class CallbackReference extends WeakReference {
Function.INTEGER_TRUE : Function.INTEGER_FALSE;
}
else if (cls == String.class || cls == WString.class) {
NativeString ns = new NativeString(value.toString(), cls == WString.class);
// Delay GC until string itself is GC'd.
allocations.put(value, ns);
return ns.getPointer();
return getNativeString(value, cls == WString.class);
}
else if (cls == String[].class || cls == WString.class) {
StringArray sa = cls == String[].class
@@ -413,28 +501,20 @@ class CallbackReference extends WeakReference {
private Function function;
private Map options;
public NativeFunctionHandler(Pointer address, int callingConvention, Map libOptions) {
this.function = new Function(address, callingConvention) {
public String getName() {
String str = super.getName();
if (options.containsKey(Function.OPTION_INVOKING_METHOD)) {
Method m = (Method)options.get(Function.OPTION_INVOKING_METHOD);
Class cls = Native.findCallbackClass(m.getDeclaringClass());
str += " (" + cls.getName() + ")";
}
return str;
}
};
this.options = new HashMap();
if (libOptions != null) {
options.putAll(libOptions);
}
public NativeFunctionHandler(Pointer address, int callingConvention, Map options) {
this.function = new Function(address, callingConvention);
this.options = options;
}
/** Chain invocation to the native function. */
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (Library.Handler.OBJECT_TOSTRING.equals(method)) {
return "Proxy interface to " + function;
String str = "Proxy interface to " + function;
Method m = (Method)options.get(Function.OPTION_INVOKING_METHOD);
Class cls = findCallbackClass(m.getDeclaringClass());
str += " (" + cls.getName() + ")";
return str;
}
else if (Library.Handler.OBJECT_HASHCODE.equals(method)) {
return new Integer(hashCode());
@@ -475,13 +555,23 @@ class CallbackReference extends WeakReference {
|| Pointer.class.isAssignableFrom(cls);
}
private static Pointer getNativeString(Object value, boolean wide) {
if (value != null) {
NativeString ns = new NativeString(value.toString(), wide);
// Delay GC until string itself is GC'd.
allocations.put(value, ns);
return ns.getPointer();
}
return null;
}
/** Create a native trampoline to delegate execution to the Java callback.
*/
private static synchronized native Pointer createNativeCallback(CallbackProxy callback,
private static synchronized native Pointer createNativeCallback(Callback callback,
Method method,
Class[] parameterTypes,
Class returnType,
int callingConvention);
int callingConvention, boolean direct);
/** Free the given callback trampoline. */
private static synchronized native void freeNativeCallback(long ptr);
}
+92 -90
Ver Arquivo
@@ -45,6 +45,10 @@ public class Function extends Pointer {
/** First alternate convention (currently used only for w32 stdcall). */
public static final int ALT_CONVENTION = 1;
private static final int MASK_CC = 0x3;
/** Whether to throw an exception if last error is non-zero after call. */
public static final int THROW_LAST_ERROR = (1<<2);
static final Integer INTEGER_TRUE = new Integer(-1);
static final Integer INTEGER_FALSE = new Integer(0);
@@ -79,20 +83,21 @@ public class Function extends Pointer {
* Library in which to find the function
* @param functionName
* Name of the native function to be linked with
* @param callConvention
* @param callFlags
* Call convention used by the native function
* @throws {@link UnsatisfiedLinkError} if the library is not found or
* the given function name is not found within the library.
*/
public static Function getFunction(String libraryName, String functionName, int callConvention) {
return NativeLibrary.getInstance(libraryName).getFunction(functionName, callConvention);
public static Function getFunction(String libraryName, String functionName, int callFlags) {
return NativeLibrary.getInstance(libraryName).getFunction(functionName, callFlags);
}
// Keep a reference to the NativeLibrary so it does not get garbage collected
// until the function is
private NativeLibrary library;
private final String functionName;
final int callingConvention;
int callFlags;
final Map options;
/** For internal JNA use. */
static final String OPTION_INVOKING_METHOD = "invoking-method";
@@ -109,18 +114,19 @@ public class Function extends Pointer {
* {@link NativeLibrary} in which to find the function
* @param functionName
* Name of the native function to be linked with
* @param callingConvention
* @param callFlags
* Calling convention used by the native function
* @throws {@link UnsatisfiedLinkError} if the given function name is
* not found within the library.
*/
Function(NativeLibrary library, String functionName, int callingConvention) {
checkCallingConvention(callingConvention);
Function(NativeLibrary library, String functionName, int callFlags) {
checkCallingConvention(callFlags & MASK_CC);
if (functionName == null)
throw new NullPointerException("Function name must not be null");
this.library = library;
this.functionName = functionName;
this.callingConvention = callingConvention;
this.callFlags = callFlags;
this.options = library.options;
try {
this.peer = library.getSymbolAddress(functionName);
}
@@ -141,18 +147,19 @@ public class Function extends Pointer {
*
* @param functionAddress
* Address of the native function
* @param callingConvention
* @param callFlags
* Calling convention used by the native function
*/
Function(Pointer functionAddress, int callingConvention) {
checkCallingConvention(callingConvention);
Function(Pointer functionAddress, int callFlags) {
checkCallingConvention(callFlags & MASK_CC);
if (functionAddress == null
|| functionAddress.peer == 0) {
throw new NullPointerException("Function address may not be null");
}
this.functionName = functionAddress.toString();
this.callingConvention = callingConvention;
this.callFlags = callFlags;
this.peer = functionAddress.peer;
this.options = Collections.EMPTY_MAP;
}
private void checkCallingConvention(int convention)
@@ -173,14 +180,14 @@ public class Function extends Pointer {
public int getCallingConvention() {
return callingConvention;
return callFlags & MASK_CC;
}
/** Invoke the native function with the given arguments, returning the
* native result as an Object.
*/
public Object invoke(Class returnType, Object[] inArgs) {
return invoke(returnType, inArgs, Collections.EMPTY_MAP);
return invoke(returnType, inArgs, this.options);
}
/** Invoke the native function with the given arguments, returning the
@@ -243,9 +250,7 @@ public class Function extends Pointer {
continue;
if (inArg instanceof Structure) {
if (!(inArg instanceof Structure.ByValue)) {
if (((Structure)inArg).getAutoRead()) {
((Structure)inArg).read();
}
((Structure)inArg).autoRead();
}
}
else if (args[i] instanceof PostCallRead) {
@@ -265,9 +270,7 @@ public class Function extends Pointer {
else if (Structure[].class.isAssignableFrom(inArg.getClass())) {
Structure[] ss = (Structure[])inArg;
for (int si=0;si < ss.length;si++) {
if (ss[si].getAutoRead()) {
ss[si].read();
}
ss[si].autoRead();
}
}
}
@@ -280,81 +283,77 @@ public class Function extends Pointer {
Object invoke(Object[] args, Class returnType, boolean allowObjects) {
Object result = null;
if (returnType == null || returnType==void.class || returnType==Void.class) {
invokeVoid(callingConvention, args);
invokeVoid(callFlags, args);
result = null;
}
else if (returnType==boolean.class || returnType==Boolean.class) {
result = valueOf(invokeInt(callingConvention, args) != 0);
result = valueOf(invokeInt(callFlags, args) != 0);
}
else if (returnType==byte.class || returnType==Byte.class) {
result = new Byte((byte)invokeInt(callingConvention, args));
result = new Byte((byte)invokeInt(callFlags, args));
}
else if (returnType==short.class || returnType==Short.class) {
result = new Short((short)invokeInt(callingConvention, args));
result = new Short((short)invokeInt(callFlags, args));
}
else if (returnType==char.class || returnType==Character.class) {
result = new Character((char)invokeInt(callingConvention, args));
result = new Character((char)invokeInt(callFlags, args));
}
else if (returnType==int.class || returnType==Integer.class) {
result = new Integer(invokeInt(callingConvention, args));
result = new Integer(invokeInt(callFlags, args));
}
else if (returnType==long.class || returnType==Long.class) {
result = new Long(invokeLong(callingConvention, args));
result = new Long(invokeLong(callFlags, args));
}
else if (returnType==float.class || returnType==Float.class) {
result = new Float(invokeFloat(callingConvention, args));
result = new Float(invokeFloat(callFlags, args));
}
else if (returnType==double.class || returnType==Double.class) {
result = new Double(invokeDouble(callingConvention, args));
result = new Double(invokeDouble(callFlags, args));
}
else if (returnType==String.class) {
result = invokeString(callingConvention, args, false);
result = invokeString(callFlags, args, false);
}
else if (returnType==WString.class) {
String s = invokeString(callingConvention, args, true);
String s = invokeString(callFlags, args, true);
if (s != null) {
result = new WString(s);
}
}
else if (Pointer.class.isAssignableFrom(returnType)) {
result = invokePointer(callingConvention, args);
result = invokePointer(callFlags, args);
}
else if (Structure.class.isAssignableFrom(returnType)) {
if (Structure.ByValue.class.isAssignableFrom(returnType)) {
Structure s =
invokeStructure(callingConvention, args,
invokeStructure(callFlags, args,
Structure.newInstance(returnType));
if (s.getAutoRead()) {
s.read();
}
s.autoRead();
result = s;
}
else {
result = invokePointer(callingConvention, args);
result = invokePointer(callFlags, args);
if (result != null) {
Structure s = Structure.newInstance(returnType);
s.useMemory((Pointer)result);
if (s.getAutoRead()) {
s.read();
}
s.autoRead();
result = s;
}
}
}
else if (Callback.class.isAssignableFrom(returnType)) {
result = invokePointer(callingConvention, args);
result = invokePointer(callFlags, args);
if (result != null) {
result = CallbackReference.getCallback(returnType, (Pointer)result);
}
}
else if (returnType==String[].class) {
Pointer p = invokePointer(callingConvention, args);
Pointer p = invokePointer(callFlags, args);
if (p != null) {
result = p.getStringArray(0);
}
}
else if (returnType==WString[].class) {
Pointer p = invokePointer(callingConvention, args);
Pointer p = invokePointer(callFlags, args);
if (p != null) {
String[] arr = p.getStringArray(0, true);
WString[] warr = new WString[arr.length];
@@ -365,18 +364,18 @@ public class Function extends Pointer {
}
}
else if (returnType==Pointer[].class) {
Pointer p = invokePointer(callingConvention, args);
Pointer p = invokePointer(callFlags, args);
if (p != null) {
result = p.getPointerArray(0);
}
}
else if (allowObjects) {
result = invokeObject(callingConvention, args);
result = invokeObject(callFlags, args);
if (result != null
&& !returnType.isAssignableFrom(result.getClass())) {
throw new IllegalArgumentException("Return type " + returnType
+ " does not match result "
+ result.getClass());
throw new ClassCastException("Return type " + returnType
+ " does not match result "
+ result.getClass());
}
}
else {
@@ -418,9 +417,7 @@ public class Function extends Pointer {
// Convert Structures to native pointers
if (arg instanceof Structure) {
Structure struct = (Structure)arg;
if (struct.getAutoWrite()) {
struct.write();
}
struct.autoWrite();
if (struct instanceof Structure.ByValue) {
// Double-check against the method signature, if available
Class ptype = struct.getClass();
@@ -476,6 +473,9 @@ public class Function extends Pointer {
else if (Pointer[].class == argClass) {
return new PointerArray((Pointer[])arg);
}
else if (NativeMapped[].class.isAssignableFrom(argClass)) {
return new NativeMappedArray((NativeMapped[])arg);
}
else if (Structure[].class.isAssignableFrom(argClass)) {
Structure[] ss = (Structure[])arg;
Class type = argClass.getComponentType();
@@ -483,7 +483,7 @@ public class Function extends Pointer {
if (byRef) {
Pointer[] pointers = new Pointer[ss.length + 1];
for (int i=0;i < ss.length;i++) {
pointers[i] = ss[i] != null ? ss[i].getPointer() : null;
pointers[i] = ss[i] != null ? ss[i].getPointer() : null;
}
return new PointerArray(pointers);
}
@@ -491,39 +491,25 @@ public class Function extends Pointer {
throw new IllegalArgumentException("Structure array must have non-zero length");
}
else if (ss[0] == null) {
// Initialize uninitialized arrays of Structure to point
// to a single block of memory
Structure struct = Structure.newInstance(type);
int size = struct.size();
Memory m = new Memory(size * ss.length);
struct.useMemory(m);
Structure[] tmp = struct.toArray(ss.length);
for (int si=0;si < ss.length;si++) {
ss[si] = tmp[si];
}
Structure.newInstance(type).toArray(ss);
return ss[0].getPointer();
}
else {
Pointer base = ss[0].getPointer();
int size = ss[0].size();
if (ss[0].getAutoWrite()) {
ss[0].write();
}
ss[0].autoWrite();
for (int si=1;si < ss.length;si++) {
if (ss[si].getPointer().peer != base.peer + size*si) {
String msg = "Structure array elements must use"
+ " contiguous memory (at element index " + si + ")";
throw new IllegalArgumentException(msg);
}
if (ss[si].getAutoWrite()) {
ss[si].write();
}
ss[si].autoWrite();
}
return base;
}
}
else if (argClass.isArray()){
// TODO: handle array of NativeMapped
throw new IllegalArgumentException("Unsupported array argument type: "
+ argClass.getComponentType());
}
@@ -547,22 +533,22 @@ public class Function extends Pointer {
/**
* Call the native function being represented by this object
*
* @param callingConvention calling convention to be used
* @param callFlags calling convention to be used
* @param args
* Arguments to pass to the native function
* @return The value returned by the target native function
*/
private native int invokeInt(int callingConvention, Object[] args);
private native int invokeInt(int callFlags, Object[] args);
/**
* Call the native function being represented by this object
*
* @param callingConvention calling convention to be used
* @param callFlags calling convention to be used
* @param args
* Arguments to pass to the native function
* @return The value returned by the target native function
*/
private native long invokeLong(int callingConvention, Object[] args);
private native long invokeLong(int callFlags, Object[] args);
/**
* Call the native function being represented by this object
@@ -578,44 +564,44 @@ public class Function extends Pointer {
/**
* Call the native function being represented by this object
*
* @param callingConvention calling convention to be used
* @param callFlags calling convention to be used
* @param args
* Arguments to pass to the native function
*/
private native void invokeVoid(int callingConvention, Object[] args);
private native void invokeVoid(int callFlags, Object[] args);
/**
* Call the native function being represented by this object
*
* @param callingConvention calling convention to be used
* @param callFlags calling convention to be used
* @param args
* Arguments to pass to the native function
* @return The value returned by the target native function
*/
private native float invokeFloat(int callingConvention, Object[] args);
private native float invokeFloat(int callFlags, Object[] args);
/**
* Call the native function being represented by this object
*
* @param callingConvention calling convention to be used
* @param callFlags calling convention to be used
* @param args
* Arguments to pass to the native function
* @return The value returned by the target native function
*/
private native double invokeDouble(int callingConvention, Object[] args);
private native double invokeDouble(int callFlags, Object[] args);
/**
* Call the native function being represented by this object
*
* @param callingConvention calling convention to be used
* @param callFlags calling convention to be used
* @param args
* Arguments to pass to the native function
* @param wide whether the native string uses <code>wchar_t</code>;
* if false, <code>char</code> is assumed
* @return The value returned by the target native function, as a String
*/
private String invokeString(int callingConvention, Object[] args, boolean wide) {
Pointer ptr = invokePointer(callingConvention, args);
private String invokeString(int callFlags, Object[] args, boolean wide) {
Pointer ptr = invokePointer(callFlags, args);
String s = null;
if (ptr != null) {
if (wide)
@@ -629,36 +615,36 @@ public class Function extends Pointer {
/**
* Call the native function being represented by this object
*
* @param callingConvention calling convention to be used
* @param callFlags calling convention to be used
* @param args
* Arguments to pass to the native function
* @return The native pointer returned by the target native function
*/
private native Pointer invokePointer(int callingConvention, Object[] args);
private native Pointer invokePointer(int callFlags, Object[] args);
/**
* Call the native function being represented by this object, returning
* a struct by value.
*
* @param callingConvention calling convention to be used
* @param callFlags calling convention to be used
* @param args
* Arguments to pass to the native function
* @param result Pre-allocated structure to hold the result
* @return The passed-in struct argument
*/
private native Structure invokeStructure(int callingConvention, Object[] args,
private native Structure invokeStructure(int callFlags, Object[] args,
Structure result);
/**
* Call the native function being represented by this object, returning
* a Java <code>Object</code>.
*
* @param callingConvention calling convention to be used
* @param callFlags calling convention to be used
* @param args
* Arguments to pass to the native function
* @return The returned Java <code>Object</code>
*/
private native Object invokeObject(int callingConvention, Object[] args);
private native Object invokeObject(int callFlags, Object[] args);
/** Provide a human-readable representation of this object. */
public String toString() {
@@ -730,9 +716,12 @@ public class Function extends Pointer {
* and calling convention.
*/
public boolean equals(Object o) {
if (o instanceof Function) {
if (o == this) return true;
if (o == null) return false;
if (o.getClass() == getClass()) {
Function other = (Function)o;
return other.callingConvention == this.callingConvention
return other.callFlags == this.callFlags
&& other.options.equals(this.options)
&& other.peer == this.peer;
}
return false;
@@ -784,6 +773,19 @@ public class Function extends Pointer {
return false;
}
private static class NativeMappedArray extends Memory implements PostCallRead {
private final NativeMapped[] original;
public NativeMappedArray(NativeMapped[] arg) {
super(Native.getNativeSize(arg.getClass(), arg));
this.original = arg;
Class nativeType = arg.getClass().getComponentType();
setValue(0, original, original.getClass());
}
public void read() {
getValue(0, original.getClass(), original);
}
}
private static class PointerArray extends Memory implements PostCallRead {
private final Pointer[] original;
public PointerArray(Pointer[] arg) {
+16 -14
Ver Arquivo
@@ -22,7 +22,8 @@ package com.sun.jna;
public abstract class IntegerType extends Number implements NativeMapped {
private int size;
private Number value;
private long value;
private Number number;
/** Create a zero-valued IntegerType. */
public IntegerType(int size) {
@@ -38,21 +39,22 @@ public abstract class IntegerType extends Number implements NativeMapped {
/** Change the value for this data. */
public void setValue(long value) {
long truncated = value;
this.value = value;
switch (size) {
case 1:
truncated = (byte) value;
this.value = new Byte((byte) value);
this.number = new Byte((byte) value);
break;
case 2:
truncated = (short) value;
this.value = new Short((short) value);
this.number = new Short((short) value);
break;
case 4:
truncated = (int) value;
this.value = new Integer((int) value);
this.number = new Integer((int) value);
break;
case 8:
this.value = new Long(value);
this.number = new Long(value);
break;
default:
throw new IllegalArgumentException("Unsupported size: " + size);
@@ -69,7 +71,7 @@ public abstract class IntegerType extends Number implements NativeMapped {
}
public Object toNative() {
return value;
return number;
}
public Object fromNative(Object nativeValue, FromNativeContext context) {
@@ -92,35 +94,35 @@ public abstract class IntegerType extends Number implements NativeMapped {
}
public Class nativeType() {
return value.getClass();
return number.getClass();
}
public int intValue() {
return value.intValue();
return number.intValue();
}
public long longValue() {
return value.longValue();
return number.longValue();
}
public float floatValue() {
return value.floatValue();
return number.floatValue();
}
public double doubleValue() {
return value.doubleValue();
return number.doubleValue();
}
public boolean equals(Object rhs) {
return rhs instanceof IntegerType
&& value.equals(((IntegerType) rhs).value);
&& number.equals(((IntegerType)rhs).number);
}
public String toString() {
return value.toString();
return number.toString();
}
public int hashCode() {
return value.hashCode();
return number.hashCode();
}
}
@@ -0,0 +1,46 @@
/* Copyright (c) 2009 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.
* <p/>
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package com.sun.jna;
/** Exception representing a non-zero error code returned in either
<code><a href="http://www.opengroup.org/onlinepubs/009695399/functions/errno.html">errno</a></code> or <code><a href="http://msdn.microsoft.com/en-us/library/ms679360(VS.85).aspx">GetLastError()</a></code>.
*/
public class LastErrorException extends RuntimeException {
private static String formatMessage(int code) {
return Platform.isWindows()
?"GetLastError() returned " + code
:"errno was " + code;
}
private static String parseMessage(String m) {
try {
return formatMessage(Integer.parseInt(m));
}
catch(NumberFormatException e) {
return m;
}
}
public int errorCode;
public LastErrorException(String msg) {
super(parseMessage(msg));
try {
this.errorCode = Integer.parseInt(msg);
}
catch(NumberFormatException e) {
this.errorCode = -1;
}
}
public LastErrorException(int code) {
super(formatMessage(code));
this.errorCode = code;
}
}
+11 -7
Ver Arquivo
@@ -79,7 +79,7 @@ public interface Library {
JNIEnv data structure.
*/
String OPTION_ALLOW_OBJECTS = "allow-objects";
/** Calling convention for the library. */
/** Calling convention for the entire library. */
String OPTION_CALLING_CONVENTION = "calling-convention";
static class Handler implements InvocationHandler {
@@ -120,20 +120,24 @@ public interface Library {
private FunctionMapper functionMapper;
private final InvocationMapper invocationMapper;
private final Map functions = new WeakHashMap();
private final int callingConvention;
public Handler(String libname, Class interfaceClass, Map options) {
if (libname == null || "".equals(libname.trim())) {
if ("".equals(libname.trim())) {
throw new IllegalArgumentException("Invalid library name \""
+ libname + "\"");
}
this.nativeLibrary = NativeLibrary.getInstance(libname);
this.interfaceClass = interfaceClass;
this.options = options;
this.callingConvention =
options = new HashMap(options);
int callingConvention =
AltCallingConvention.class.isAssignableFrom(interfaceClass)
? Function.ALT_CONVENTION : Function.C_CONVENTION;
if (options.get(OPTION_CALLING_CONVENTION) == null) {
options.put(OPTION_CALLING_CONVENTION,
new Integer(callingConvention));
}
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
@@ -196,7 +200,7 @@ public interface Library {
// Just in case the function mapper screwed up
methodName = method.getName();
}
f.function = nativeLibrary.getFunction(methodName, callingConvention);
f.function = nativeLibrary.getFunction(methodName, method);
f.options = new HashMap(this.options);
f.options.put(Function.OPTION_INVOKING_METHOD, method);
}
+30 -11
Ver Arquivo
@@ -11,7 +11,8 @@
package com.sun.jna;
import java.nio.ByteBuffer;
import java.util.Map;
import java.util.WeakHashMap;
/**
* A <code>Pointer</code> to memory obtained from the native heap via a
@@ -36,8 +37,17 @@ import java.nio.ByteBuffer;
*/
public class Memory extends Pointer {
private static Map buffers = new WeakHashMap();
protected long size; // Size of the malloc'ed space
/** Force cleanup of memory that has associated NIO Buffers which have
been GC'd.
*/
public static void purge() {
buffers.size();
}
/** Provide a view into the original memory. */
private class SharedMemory extends Memory {
public SharedMemory(long offset) {
@@ -105,17 +115,22 @@ public class Memory extends Pointer {
if (byteBoundary <= 0) {
throw new IllegalArgumentException("Byte boundary must be positive: " + byteBoundary);
}
long mask = ~((long)byteBoundary - 1);
if ((peer & ~mask) != peer) {
long newPeer = (peer + ~mask) & mask;
long newSize = peer + size - newPeer;
if (newSize <= 0) {
throw new IllegalArgumentException("Insufficient memory to align to the requested boundary");
for (int i=0;i < 32;i++) {
if (byteBoundary == (1<<i)) {
long mask = ~((long)byteBoundary - 1);
if ((peer & mask) != peer) {
long newPeer = (peer + byteBoundary - 1) & mask;
long newSize = peer + size - newPeer;
if (newSize <= 0) {
throw new IllegalArgumentException("Insufficient memory to align to the requested boundary");
}
return (Memory)share(newPeer - peer, newSize);
}
return this;
}
return (Memory)share(newPeer - peer, newSize);
}
return this;
throw new IllegalArgumentException("Byte boundary must be a power of two");
}
protected void finalize() {
@@ -487,7 +502,11 @@ public class Memory extends Pointer {
*/
public ByteBuffer getByteBuffer(long offset, long length) {
boundsCheck(offset, length);
return super.getByteBuffer(offset, length);
ByteBuffer b = super.getByteBuffer(offset, length);
// Ensure this Memory object will not be GC'd (and its memory freed)
// if the Buffer is still extant.
buffers.put(b, this);
return b;
}
/**
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+88 -51
Ver Arquivo
@@ -17,6 +17,7 @@ package com.sun.jna;
import java.io.File;
import java.io.FilenameFilter;
import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -29,7 +30,8 @@ import java.util.StringTokenizer;
/**
* Provides management of native library resources. One instance of this
* class corresponds to a single loaded native library.
* class corresponds to a single loaded native library. May also be used
* to map to the current process (see {@link NativeLibrary#getProcess()}).
* <p>
* <b>Library Search Paths</b>
* A search for a given library will scan the following locations:
@@ -45,10 +47,9 @@ public class NativeLibrary {
private final String libraryName;
private final String libraryPath;
private final Map functions = new HashMap();
private final int callingConvention;
private final Map options;
final int callFlags;
final Map options;
private static WeakReference currentProcess;
private static final Map libraries = new HashMap();
private static final Map searchPaths = Collections.synchronizedMap(new HashMap());
private static final List librarySearchPath = new LinkedList();
@@ -60,6 +61,10 @@ public class NativeLibrary {
throw new Error("Native library not initialized");
}
private static String functionKey(String name, int flags) {
return name + "|" + flags;
}
private NativeLibrary(String libraryName, String libraryPath, long handle, Map options) {
this.libraryName = getLibraryName(libraryName);
this.libraryPath = libraryPath;
@@ -67,7 +72,7 @@ public class NativeLibrary {
Object option = options.get(Library.OPTION_CALLING_CONVENTION);
int callingConvention = option instanceof Integer
? ((Integer)option).intValue() : Function.C_CONVENTION;
this.callingConvention = callingConvention;
this.callFlags = callingConvention;
this.options = options;
// Special workaround for w32 kernel32.GetLastError
@@ -79,7 +84,7 @@ public class NativeLibrary {
return new Integer(Native.getLastError());
}
};
functions.put("GetLastError", f);
functions.put(functionKey("GetLastError", callFlags), f);
}
}
}
@@ -109,8 +114,8 @@ public class NativeLibrary {
long handle = 0;
//
// Only search user specified paths first. This will also fall back
// to dlopen/LoadLibrary() since findLibraryPath returns the mapped name
// if it cannot find the library.
// to dlopen/LoadLibrary() since findLibraryPath returns the mapped
// name if it cannot find the library.
//
try {
handle = open(libraryPath);
@@ -206,46 +211,57 @@ public class NativeLibrary {
* Library}).
*/
public static final NativeLibrary getInstance(String libraryName, Map options) {
if (libraryName == null)
throw new NullPointerException("Library name may not be null");
options = new HashMap(options);
if (options.get(Library.OPTION_CALLING_CONVENTION) == null) {
options.put(Library.OPTION_CALLING_CONVENTION, new Integer(Function.C_CONVENTION));
}
synchronized (libraries) {
WeakReference ref = (WeakReference)libraries.get(libraryName);
WeakReference ref = (WeakReference)libraries.get(libraryName + options);
NativeLibrary library = ref != null ? (NativeLibrary)ref.get() : null;
if (library == null) {
library = loadLibrary(libraryName, options);
if (libraryName == null) {
library = new NativeLibrary("<process>", null, open(null), options);
}
else {
library = loadLibrary(libraryName, options);
}
ref = new WeakReference(library);
libraries.put(library.getName(), ref);
libraries.put(library.getFile().getAbsolutePath(), ref);
libraries.put(library.getFile().getName(), ref);
libraries.put(library.getName() + options, ref);
File file = library.getFile();
if (file != null) {
libraries.put(file.getAbsolutePath() + options, ref);
libraries.put(file.getName() + options, ref);
}
}
return library;
}
}
/**
* Returns an instance of NativeLibrary which refers to the current process.
* This is useful for accessing functions which were already mapped by some
* other mechanism, without having to reference or even know the exact
* name of the native library.
* Returns an instance of NativeLibrary which refers to the current
* process. This is useful for accessing functions which were already
* mapped by some other mechanism, without having to reference or even
* know the exact name of the native library.
*/
public static synchronized final NativeLibrary getProcess() {
NativeLibrary library = null;
if (currentProcess != null) {
library = (NativeLibrary) currentProcess.get();
}
if (library == null) {
long handle = open(null);
library = new NativeLibrary("<process>", null, handle, Collections.EMPTY_MAP);
currentProcess = new WeakReference(library);
}
return library;
return getInstance(null);
}
/**
* Add a path to search for the specified library, ahead of any system paths
* Returns an instance of NativeLibrary which refers to the current
* process. This is useful for accessing functions which were already
* mapped by some other mechanism, without having to reference or even
* know the exact name of the native library.
*/
public static synchronized final NativeLibrary getProcess(Map options) {
return getInstance(null, options);
}
/**
* Add a path to search for the specified library, ahead of any system
* paths.
*
* @param libraryName The name of the library to use the path for
* @param path The path to use when trying to load the library
@@ -263,41 +279,62 @@ public class NativeLibrary {
}
/**
* Create a new {@link Function} that is linked with a native
* function that follows the standard "C" calling convention.
* function that follows the NativeLibrary's calling convention.
*
* <p>The allocated instance represents a pointer to the named native
* function from the library, called with the standard "C" calling
* convention.
* function from the library.
*
* @param functionName
* Name of the native function to be linked with
* @throws UnsatisfiedLinkError if the function is not found
*/
public Function getFunction(String functionName) {
return getFunction(functionName, callingConvention);
return getFunction(functionName, callFlags);
}
/**
* Create a new {@link Function} that is linked with a native
* function that follows the NativeLibrary's calling convention.
*
* <p>The allocated instance represents a pointer to the named native
* function from the library.
*
* @param name
* Name of the native function to be linked with
* @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) {
int flags = this.callFlags;
Class[] etypes = method.getExceptionTypes();
for (int i=0;i < etypes.length;i++) {
if (LastErrorException.class.isAssignableFrom(etypes[i])) {
flags |= Function.THROW_LAST_ERROR;
}
}
return getFunction(name, flags);
}
/**
* Create a new @{link Function} that is linked with a native
* function that follows a given calling convention.
*
* <p>The allocated instance represents a pointer to the named native
* function from the library, called with the named calling convention.
* function that follows a given calling flags.
*
* @param functionName
* Name of the native function to be linked with
* @param callingConvention
* Calling convention used by the native function
* @param callFlags
* Flags affecting the function invocation
* @throws UnsatisfiedLinkError if the function is not found
*/
public Function getFunction(String functionName, int callingConvention) {
public Function getFunction(String functionName, int callFlags) {
if (functionName == null)
throw new NullPointerException("Function name may not be null");
synchronized (functions) {
Function function = (Function) functions.get(functionName);
String key = functionKey(functionName, callFlags);
Function function = (Function) functions.get(key);
if (function == null) {
function = new Function(this, functionName, callingConvention);
functions.put(functionName, function);
function = new Function(this, functionName, callFlags);
functions.put(key, function);
}
return function;
}
@@ -357,11 +394,11 @@ public class NativeLibrary {
public void dispose() {
synchronized(libraries) {
libraries.remove(getName());
File path = getFile();
if (path != null) {
libraries.remove(path.getAbsolutePath());
libraries.remove(path.getName());
libraries.remove(getName() + options);
File file = getFile();
if (file != null) {
libraries.remove(file.getAbsolutePath() + options);
libraries.remove(file.getName() + options);
}
}
synchronized(this) {
+12 -8
Ver Arquivo
@@ -11,14 +11,15 @@ package com.sun.jna;
/** Provide simplified platform information. */
public final class Platform {
private static final int UNSPECIFIED = -1;
private static final int MAC = 0;
private static final int LINUX = 1;
private static final int WINDOWS = 2;
private static final int SOLARIS = 3;
private static final int FREEBSD = 4;
private static final int OPENBSD = 5;
private static final int WINDOWSCE = 6;
public static final int UNSPECIFIED = -1;
public static final int MAC = 0;
public static final int LINUX = 1;
public static final int WINDOWS = 2;
public static final int SOLARIS = 3;
public static final int FREEBSD = 4;
public static final int OPENBSD = 5;
public static final int WINDOWSCE = 6;
private static final int osType;
static {
@@ -49,6 +50,9 @@ public final class Platform {
}
}
private Platform() { }
public static final int getOSType() {
return osType;
}
public static final boolean isMac() {
return osType == MAC;
}
+318 -4
Ver Arquivo
@@ -11,6 +11,8 @@
package com.sun.jna;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Array;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
@@ -73,7 +75,7 @@ public class Pointer {
}
/** Zero memory for the given number of bytes. */
void clear(long size) {
public void clear(long size) {
setMemory(0, size, (byte)0);
}
@@ -87,9 +89,9 @@ public class Pointer {
* equal. Returns false otherwise.
*/
public boolean equals(Object o) {
if (o == null)
return peer == 0;
return (o instanceof Pointer) && ((Pointer)o).peer == peer;
if (o == this) return true;
if (o == null) return false;
return o instanceof Pointer && ((Pointer)o).peer == peer;
}
/**
@@ -374,6 +376,180 @@ public class Pointer {
// Java type read methods
//////////////////////////////////////////////////////////////////////////
Object getValue(long offset, Class type, Object currentValue) {
Object result = null;
if (Structure.class.isAssignableFrom(type)) {
Structure s = (Structure)currentValue;
if (Structure.ByReference.class.isAssignableFrom(type)) {
s = Structure.updateStructureByReference(type, s, getPointer(offset));
}
else {
s.useMemory(this, (int)offset);
s.read();
}
result = s;
}
else if (type == boolean.class || type == Boolean.class) {
result = Function.valueOf(getInt(offset) != 0);
}
else if (type == byte.class || type == Byte.class) {
result = new Byte(getByte(offset));
}
else if (type == short.class || type == Short.class) {
result = new Short(getShort(offset));
}
else if (type == char.class || type == Character.class) {
result = new Character(getChar(offset));
}
else if (type == int.class || type == Integer.class) {
result = new Integer(getInt(offset));
}
else if (type == long.class || type == Long.class) {
result = new Long(getLong(offset));
}
else if (type == float.class || type == Float.class) {
result=new Float(getFloat(offset));
}
else if (type == double.class || type == Double.class) {
result = new Double(getDouble(offset));
}
else if (Pointer.class.isAssignableFrom(type)) {
Pointer p = getPointer(offset);
if (p != null) {
Pointer oldp = currentValue instanceof Pointer
? (Pointer)currentValue : null;
if (oldp == null || p.peer != oldp.peer)
result = p;
else
result = oldp;
}
}
else if (type == String.class) {
Pointer p = getPointer(offset);
result = p != null ? p.getString(0) : null;
}
else if (type == WString.class) {
Pointer p = getPointer(offset);
result = p != null ? new WString(p.getString(0, true)) : null;
}
else if (Callback.class.isAssignableFrom(type)) {
// Overwrite the Java memory if the native pointer is a different
// function pointer.
Pointer fp = getPointer(offset);
if (fp == null) {
result = null;
}
else {
Callback cb = (Callback)currentValue;
Pointer oldfp = CallbackReference.getFunctionPointer(cb);
if (!fp.equals(oldfp)) {
cb = CallbackReference.getCallback(type, fp);
}
result = cb;
}
}
else if (Buffer.class.isAssignableFrom(type)) {
Pointer bp = getPointer(offset);
if (bp == null) {
result = null;
}
else {
Pointer oldbp = currentValue == null ? null
: Native.getDirectBufferPointer((Buffer)currentValue);
if (oldbp == null || !oldbp.equals(bp)) {
throw new IllegalStateException("Can't autogenerate a direct buffers on memory read");
}
}
}
else if (NativeMapped.class.isAssignableFrom(type)) {
NativeMapped nm = (NativeMapped)currentValue;
if (nm != null) {
Object value = getValue(offset, nm.nativeType(), null);
nm.fromNative(value, new FromNativeContext(type));
}
else {
NativeMappedConverter tc = NativeMappedConverter.getInstance(type);
Object value = getValue(offset, tc.nativeType(), null);
result = tc.fromNative(value, new FromNativeContext(type));
}
}
else if (type.isArray()) {
result = currentValue;
if (result == null) {
throw new IllegalStateException("Need an initialized array");
}
getArrayValue(offset, result, type.getComponentType());
}
else {
throw new IllegalArgumentException("Reading \""
+ type + "\" from memory is not supported");
}
return result;
}
private void getArrayValue(long offset, Object o, Class cls) {
int length = 0;
length = Array.getLength(o);
Object result = o;
if (cls == byte.class) {
read(offset, (byte[])result, 0, length);
}
else if (cls == short.class) {
read(offset, (short[])result, 0, length);
}
else if (cls == char.class) {
read(offset, (char[])result, 0, length);
}
else if (cls == int.class) {
read(offset, (int[])result, 0, length);
}
else if (cls == long.class) {
read(offset, (long[])result, 0, length);
}
else if (cls == float.class) {
read(offset, (float[])result, 0, length);
}
else if (cls == double.class) {
read(offset, (double[])result, 0, length);
}
else if (Pointer.class.isAssignableFrom(cls)) {
read(offset, (Pointer[])result, 0, length);
}
else if (Structure.class.isAssignableFrom(cls)) {
Structure[] sarray = (Structure[])result;
if (Structure.ByReference.class.isAssignableFrom(cls)) {
Pointer[] parray = getPointerArray(offset, sarray.length);
for (int i=0;i < sarray.length;i++) {
sarray[i] = Structure.updateStructureByReference(cls, sarray[i], parray[i]);
}
}
else {
for (int i=0;i < sarray.length;i++) {
if (sarray[i] == null) {
sarray[i] = Structure.newInstance(cls);
}
sarray[i].useMemory(this, (int)(offset + i * sarray[i].size()));
sarray[i].read();
}
}
}
else if (NativeMapped.class.isAssignableFrom(cls)) {
NativeMapped[] array = (NativeMapped[])result;
NativeMappedConverter tc = NativeMappedConverter.getInstance(cls);
int size = Native.getNativeSize(result.getClass(), result) / array.length;
for (int i=0;i < array.length;i++) {
Object value = getValue(offset + size*i, tc.nativeType(), array[i]);
array[i] = (NativeMapped)tc.fromNative(value, new FromNativeContext(cls));
}
}
else {
throw new IllegalArgumentException("Reading array of "
+ cls
+ " from memory not supported");
}
}
/**
* Indirect the native pointer as a pointer to <code>byte</code>. This is
* equivalent to the expression
@@ -657,6 +833,144 @@ v * @param wide whether to convert from a wide or standard C string
// Java type write methods
//////////////////////////////////////////////////////////////////////////
void setValue(long offset, Object value, Class type) {
// Set the value at the offset according to its type
if (type == boolean.class || type == Boolean.class) {
setInt(offset, Boolean.TRUE.equals(value) ? -1 : 0);
}
else if (type == byte.class || type == Byte.class) {
setByte(offset, value == null ? 0 : ((Byte)value).byteValue());
}
else if (type == short.class || type == Short.class) {
setShort(offset, value == null ? 0 : ((Short)value).shortValue());
}
else if (type == char.class || type == Character.class) {
setChar(offset, value == null ? 0 : ((Character)value).charValue());
}
else if (type == int.class || type == Integer.class) {
setInt(offset, value == null ? 0 : ((Integer)value).intValue());
}
else if (type == long.class || type == Long.class) {
setLong(offset, value == null ? 0 : ((Long)value).longValue());
}
else if (type == float.class || type == Float.class) {
setFloat(offset, value == null ? 0f : ((Float)value).floatValue());
}
else if (type == double.class || type == Double.class) {
setDouble(offset, value == null ? 0.0 : ((Double)value).doubleValue());
}
else if (type == Pointer.class) {
setPointer(offset, (Pointer)value);
}
else if (type == String.class) {
setPointer(offset, (Pointer)value);
}
else if (type == WString.class) {
setPointer(offset, (Pointer)value);
}
else if (Structure.class.isAssignableFrom(type)) {
Structure s = (Structure)value;
if (Structure.ByReference.class.isAssignableFrom(type)) {
setPointer(offset, s == null ? null : s.getPointer());
if (s != null) {
s.autoWrite();
}
}
else {
s.useMemory(this, (int)offset);
s.write();
}
}
else if (Callback.class.isAssignableFrom(type)) {
setPointer(offset, CallbackReference.getFunctionPointer((Callback)value));
}
else if (Buffer.class.isAssignableFrom(type)) {
Pointer p = value == null ? null
: Native.getDirectBufferPointer((Buffer)value);
setPointer(offset, p);
}
else if (NativeMapped.class.isAssignableFrom(type)) {
NativeMappedConverter tc = NativeMappedConverter.getInstance(type);
Class nativeType = tc.nativeType();
setValue(offset, tc.toNative(value, new ToNativeContext()), nativeType);
}
else if (type.isArray()) {
setArrayValue(offset, value, type.getComponentType());
}
else {
throw new IllegalArgumentException("Writing " + type + " to memory is not supported");
}
}
private void setArrayValue(long offset, Object value, Class cls) {
if (cls == byte.class) {
byte[] buf = (byte[])value;
write(offset, buf, 0, buf.length);
}
else if (cls == short.class) {
short[] buf = (short[])value;
write(offset, buf, 0, buf.length);
}
else if (cls == char.class) {
char[] buf = (char[])value;
write(offset, buf, 0, buf.length);
}
else if (cls == int.class) {
int[] buf = (int[])value;
write(offset, buf, 0, buf.length);
}
else if (cls == long.class) {
long[] buf = (long[])value;
write(offset, buf, 0, buf.length);
}
else if (cls == float.class) {
float[] buf = (float[])value;
write(offset, buf, 0, buf.length);
}
else if (cls == double.class) {
double[] buf = (double[])value;
write(offset, buf, 0, buf.length);
}
else if (Pointer.class.isAssignableFrom(cls)) {
Pointer[] buf = (Pointer[])value;
write(offset, buf, 0, buf.length);
}
else if (Structure.class.isAssignableFrom(cls)) {
Structure[] sbuf = (Structure[])value;
if (Structure.ByReference.class.isAssignableFrom(cls)) {
Pointer[] buf = new Pointer[sbuf.length];
for (int i=0;i < sbuf.length;i++) {
buf[i] = sbuf[i] == null ? null : sbuf[i].getPointer();
sbuf[i].write();
}
write(offset, buf, 0, buf.length);
}
else {
for (int i=0;i < sbuf.length;i++) {
if (sbuf[i] == null) {
sbuf[i] = Structure.newInstance(cls);
}
sbuf[i].useMemory(this, (int)(offset + i * sbuf[i].size()));
sbuf[i].write();
}
}
}
else if (NativeMapped.class.isAssignableFrom(cls)) {
NativeMapped[] buf = (NativeMapped[])value;
NativeMappedConverter tc = NativeMappedConverter.getInstance(cls);
Class nativeType = tc.nativeType();
int size = Native.getNativeSize(value.getClass(), value) / buf.length;
for (int i=0;i < buf.length;i++) {
Object element = tc.toNative(buf[i], new ToNativeContext());
setValue(offset + i*size, element, nativeType);
}
}
else {
throw new IllegalArgumentException("Writing array of "
+ cls + " to memory not supported");
}
}
/** Write <code>value</code> to the requested bank of memory.
* @param offset byte offset from pointer to start
* @param length number of bytes to write
+1
Ver Arquivo
@@ -87,6 +87,7 @@ public abstract class PointerType implements NativeMapped {
* equal by default.
*/
public boolean equals(Object o) {
if (o == this) return true;
if (o instanceof PointerType) {
Pointer p = ((PointerType)o).getPointer();
if (pointer == null)
+143 -397
Ver Arquivo
@@ -14,8 +14,10 @@ import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.nio.Buffer;
import java.util.AbstractCollection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -122,6 +124,7 @@ public abstract class Structure {
private List fieldOrder;
private boolean autoRead = true;
private boolean autoWrite = true;
private Structure[] array;
protected Structure() {
this((Pointer)null);
@@ -287,10 +290,37 @@ public abstract class Structure {
// Data synchronization methods
//////////////////////////////////////////////////////////////////////////
// Keep track of what is currently being read to avoid redundant reads
// (avoids problems with circular references).
private static Set reading = new HashSet();
private static Set writing = new HashSet();
// Keep track of what is currently being read/written to avoid redundant
// reads (avoids problems with circular references).
private static final ThreadLocal busy = new ThreadLocal() {
/** Avoid using a hash-based implementation since the hash code
will change if structure field values change.
*/
class StructureSet extends AbstractCollection implements Set {
private Collection list = new ArrayList();
public int size() { return list.size(); }
public boolean contains(Object o) {
for (Iterator i=iterator();i.hasNext();) {
if (o == i.next())
return true;
}
return false;
}
public boolean add(Object o) {
if (!contains(o))
return list.add(o);
return true;
}
public Iterator iterator() { return list.iterator(); }
}
protected synchronized Object initialValue() {
return new StructureSet();
}
};
Set busy() {
return (Set)busy.get();
}
/**
* Reads the fields of the struct from native memory
*/
@@ -300,20 +330,17 @@ public abstract class Structure {
// have to explicitly call allocateMemory in a ctor
ensureAllocated();
// Avoid recursive reads
synchronized(reading) {
if (reading.contains(this))
return;
reading.add(this);
if (busy().contains(this)) {
return;
}
busy().add(this);
try {
for (Iterator i=structFields.values().iterator();i.hasNext();) {
readField((StructField)i.next());
}
}
finally {
synchronized(reading) {
reading.remove(this);
}
busy().remove(this);
}
}
@@ -371,9 +398,7 @@ public abstract class Structure {
s = newInstance(type);
s.useMemory(address);
}
if (s.getAutoRead()) {
s.read();
}
s.autoRead();
}
return s;
}
@@ -388,19 +413,20 @@ public abstract class Structure {
int offset = structField.offset;
// Determine the type of the field
Class nativeType = structField.type;
Class fieldType = structField.type;
FromNativeConverter readConverter = structField.readConverter;
if (readConverter != null) {
nativeType = readConverter.nativeType();
fieldType = readConverter.nativeType();
}
// Get the current value only for types which might need to be preserved
Object currentValue = (Structure.class.isAssignableFrom(nativeType)
|| Callback.class.isAssignableFrom(nativeType)
|| Buffer.class.isAssignableFrom(nativeType)
|| Pointer.class.isAssignableFrom(nativeType)
|| nativeType.isArray())
Object currentValue = (Structure.class.isAssignableFrom(fieldType)
|| Callback.class.isAssignableFrom(fieldType)
|| Buffer.class.isAssignableFrom(fieldType)
|| Pointer.class.isAssignableFrom(fieldType)
|| fieldType.isArray())
? getField(structField) : null;
Object result = readValue(offset, nativeType, currentValue);
Object result = memory.getValue(offset, fieldType, currentValue);
// TODO: process against current value here
if (readConverter != null) {
result = readConverter.fromNative(result, structField.context);
@@ -411,170 +437,6 @@ public abstract class Structure {
return result;
}
private Object readValue(int offset, Class nativeType, Object currentValue) {
Object result = null;
if (Structure.class.isAssignableFrom(nativeType)) {
Structure s = (Structure)currentValue;
if (ByReference.class.isAssignableFrom(nativeType)) {
s = updateStructureByReference(nativeType, s, memory.getPointer(offset));
}
else {
s.useMemory(memory, offset);
s.read();
}
result = s;
}
else if (nativeType == boolean.class || nativeType == Boolean.class) {
result = Function.valueOf(memory.getInt(offset) != 0);
}
else if (nativeType == byte.class || nativeType == Byte.class) {
result = new Byte(memory.getByte(offset));
}
else if (nativeType == short.class || nativeType == Short.class) {
result = new Short(memory.getShort(offset));
}
else if (nativeType == char.class || nativeType == Character.class) {
result = new Character(memory.getChar(offset));
}
else if (nativeType == int.class || nativeType == Integer.class) {
result = new Integer(memory.getInt(offset));
}
else if (nativeType == long.class || nativeType == Long.class) {
result = new Long(memory.getLong(offset));
}
else if (nativeType == float.class || nativeType == Float.class) {
result=new Float(memory.getFloat(offset));
}
else if (nativeType == double.class || nativeType == Double.class) {
result = new Double(memory.getDouble(offset));
}
else if (nativeType == Pointer.class) {
Pointer p = memory.getPointer(offset);
if (p != null) {
Pointer oldp = currentValue instanceof Pointer
? (Pointer)currentValue : null;
if (oldp == null || p.peer != oldp.peer)
result = p;
else
result = oldp;
}
}
else if (nativeType == String.class) {
Pointer p = memory.getPointer(offset);
result = p != null ? p.getString(0) : null;
}
else if (nativeType == WString.class) {
Pointer p = memory.getPointer(offset);
result = p != null ? new WString(p.getString(0, true)) : null;
}
else if (Callback.class.isAssignableFrom(nativeType)) {
// Overwrite the Java memory if the native pointer is a different
// function pointer.
Pointer fp = memory.getPointer(offset);
if (fp == null) {
result = null;
}
else {
Callback cb = (Callback)currentValue;
Pointer oldfp = CallbackReference.getFunctionPointer(cb);
if (!fp.equals(oldfp)) {
cb = CallbackReference.getCallback(nativeType, fp);
}
result = cb;
}
}
else if (Buffer.class.isAssignableFrom(nativeType)) {
Pointer bp = memory.getPointer(offset);
if (bp == null) {
result = null;
}
else {
Pointer oldbp = currentValue == null ? null
: Native.getDirectBufferPointer((Buffer)currentValue);
if (oldbp == null || !oldbp.equals(bp)) {
throw new IllegalStateException("Can't autogenerate a direct buffers on Structure read");
}
}
}
else if (nativeType.isArray()) {
result = currentValue;
if (result == null) {
throw new IllegalStateException("Array field in Structure not initialized");
}
readArrayValue(offset, result, nativeType.getComponentType());
}
else {
throw new IllegalArgumentException("Unsupported field type \""
+ nativeType + "\"");
}
return result;
}
private void readArrayValue(int offset, Object o, Class cls) {
int length = 0;
length = Array.getLength(o);
Object result = o;
if (cls == byte.class) {
memory.read(offset, (byte[])result, 0, length);
}
else if (cls == short.class) {
memory.read(offset, (short[])result, 0, length);
}
else if (cls == char.class) {
memory.read(offset, (char[])result, 0, length);
}
else if (cls == int.class) {
memory.read(offset, (int[])result, 0, length);
}
else if (cls == long.class) {
memory.read(offset, (long[])result, 0, length);
}
else if (cls == float.class) {
memory.read(offset, (float[])result, 0, length);
}
else if (cls == double.class) {
memory.read(offset, (double[])result, 0, length);
}
else if (Pointer.class.isAssignableFrom(cls)) {
memory.read(offset, (Pointer[])result, 0, length);
}
else if (Structure.class.isAssignableFrom(cls)) {
Structure[] sarray = (Structure[])result;
if (ByReference.class.isAssignableFrom(cls)) {
Pointer[] parray = memory.getPointerArray(offset, sarray.length);
for (int i=0;i < sarray.length;i++) {
sarray[i] = updateStructureByReference(cls, sarray[i], parray[i]);
}
}
else {
for (int i=0;i < sarray.length;i++) {
if (sarray[i] == null) {
sarray[i] = newInstance(cls);
}
sarray[i].useMemory(memory, offset + i * sarray[i].size());
sarray[i].read();
}
}
}
else if (NativeMapped.class.isAssignableFrom(cls)) {
NativeMapped[] array = (NativeMapped[])result;
NativeMappedConverter tc = NativeMappedConverter.getInstance(cls);
int size = getNativeSize(result.getClass(), result) / array.length;
for (int i=0;i < array.length;i++) {
// FIXME: use proper context
Object value = readValue(offset + size*i, tc.nativeType(), array[i]);
array[i] = (NativeMapped)tc.fromNative(value, new FromNativeContext(cls));
}
}
else {
throw new IllegalArgumentException("Array of "
+ cls + " not supported");
}
}
/**
* Writes the fields of the struct to native memory
*/
@@ -589,11 +451,10 @@ public abstract class Structure {
getTypeInfo();
}
synchronized(writing) {
if (writing.contains(this))
return;
writing.add(this);
if (busy().contains(this)) {
return;
}
busy().add(this);
try {
// Write all fields, except those marked 'volatile'
for (Iterator i=structFields.values().iterator();i.hasNext();) {
@@ -604,9 +465,7 @@ public abstract class Structure {
}
}
finally {
synchronized(writing) {
writing.remove(this);
}
busy().remove(this);
}
}
@@ -644,19 +503,19 @@ public abstract class Structure {
Object value = getField(structField);
// Determine the type of the field
Class nativeType = structField.type;
Class fieldType = structField.type;
ToNativeConverter converter = structField.writeConverter;
if (converter != null) {
value = converter.toNative(value, new StructureWriteContext(this, structField.field));
nativeType = converter.nativeType();
fieldType = converter.nativeType();
}
// Java strings get converted to C strings, where a Pointer is used
if (String.class == nativeType
|| WString.class == nativeType) {
if (String.class == fieldType
|| WString.class == fieldType) {
// Allocate a new string in memory
boolean wide = nativeType == WString.class;
boolean wide = fieldType == WString.class;
if (value != null) {
NativeString nativeString = new NativeString(value.toString(), wide);
// Keep track of allocated C strings to avoid
@@ -670,153 +529,20 @@ public abstract class Structure {
}
}
if (!writeValue(offset, value, nativeType)) {
try {
memory.setValue(offset, value, fieldType);
}
catch(IllegalArgumentException e) {
e.printStackTrace();
String msg = "Structure field \"" + structField.name
+ "\" was declared as " + structField.type
+ (structField.type == nativeType ? "" : " (native type " + nativeType + ")")
+ (structField.type == fieldType
? "" : " (native type " + fieldType + ")")
+ ", which is not supported within a Structure";
throw new IllegalArgumentException(msg);
}
}
private boolean writeValue(int offset, Object value, Class nativeType) {
// Set the value at the offset according to its type
if (nativeType == boolean.class || nativeType == Boolean.class) {
memory.setInt(offset, Boolean.TRUE.equals(value) ? -1 : 0);
}
else if (nativeType == byte.class || nativeType == Byte.class) {
memory.setByte(offset, value == null ? 0 : ((Byte)value).byteValue());
}
else if (nativeType == short.class || nativeType == Short.class) {
memory.setShort(offset, value == null ? 0 : ((Short)value).shortValue());
}
else if (nativeType == char.class || nativeType == Character.class) {
memory.setChar(offset, value == null ? 0 : ((Character)value).charValue());
}
else if (nativeType == int.class || nativeType == Integer.class) {
memory.setInt(offset, value == null ? 0 : ((Integer)value).intValue());
}
else if (nativeType == long.class || nativeType == Long.class) {
memory.setLong(offset, value == null ? 0 : ((Long)value).longValue());
}
else if (nativeType == float.class || nativeType == Float.class) {
memory.setFloat(offset, value == null ? 0f : ((Float)value).floatValue());
}
else if (nativeType == double.class || nativeType == Double.class) {
memory.setDouble(offset, value == null ? 0.0 : ((Double)value).doubleValue());
}
else if (nativeType == Pointer.class) {
memory.setPointer(offset, (Pointer)value);
}
else if (nativeType == String.class) {
memory.setPointer(offset, (Pointer)value);
}
else if (nativeType == WString.class) {
memory.setPointer(offset, (Pointer)value);
}
else if (Structure.class.isAssignableFrom(nativeType)) {
Structure s = (Structure)value;
if (ByReference.class.isAssignableFrom(nativeType)) {
memory.setPointer(offset, s == null ? null : s.getPointer());
if (s != null) {
s.write();
}
}
else {
s.useMemory(memory, offset);
s.write();
}
}
else if (Callback.class.isAssignableFrom(nativeType)) {
memory.setPointer(offset, CallbackReference.getFunctionPointer((Callback)value));
}
else if (nativeType == Buffer.class) {
Pointer p = value == null ? null
: Native.getDirectBufferPointer((Buffer)value);
memory.setPointer(offset, p);
}
else if (nativeType.isArray()) {
return writeArrayValue(offset, value, nativeType.getComponentType());
}
else {
return false;
}
return true;
}
private boolean writeArrayValue(int offset, Object value, Class cls) {
if (cls == byte.class) {
byte[] buf = (byte[])value;
memory.write(offset, buf, 0, buf.length);
}
else if (cls == short.class) {
short[] buf = (short[])value;
memory.write(offset, buf, 0, buf.length);
}
else if (cls == char.class) {
char[] buf = (char[])value;
memory.write(offset, buf, 0, buf.length);
}
else if (cls == int.class) {
int[] buf = (int[])value;
memory.write(offset, buf, 0, buf.length);
}
else if (cls == long.class) {
long[] buf = (long[])value;
memory.write(offset, buf, 0, buf.length);
}
else if (cls == float.class) {
float[] buf = (float[])value;
memory.write(offset, buf, 0, buf.length);
}
else if (cls == double.class) {
double[] buf = (double[])value;
memory.write(offset, buf, 0, buf.length);
}
else if (Pointer.class.isAssignableFrom(cls)) {
Pointer[] buf = (Pointer[])value;
memory.write(offset, buf, 0, buf.length);
}
else if (Structure.class.isAssignableFrom(cls)) {
Structure[] sbuf = (Structure[])value;
if (ByReference.class.isAssignableFrom(cls)) {
Pointer[] buf = new Pointer[sbuf.length];
for (int i=0;i < sbuf.length;i++) {
buf[i] = sbuf[i] == null ? null : sbuf[i].getPointer();
}
memory.write(offset, buf, 0, buf.length);
}
else {
for (int i=0;i < sbuf.length;i++) {
if (sbuf[i] == null) {
sbuf[i] = newInstance(cls);
}
sbuf[i].useMemory(memory, offset + i * sbuf[i].size());
sbuf[i].write();
}
}
}
else if (NativeMapped.class.isAssignableFrom(cls)) {
NativeMapped[] buf = (NativeMapped[])value;
NativeMappedConverter tc = NativeMappedConverter.getInstance(cls);
Class nativeType = tc.nativeType();
int size = getNativeSize(value.getClass(), value) / buf.length;
for (int i=0;i < buf.length;i++) {
// FIXME: incorrect context
Object element = tc.toNative(buf[i], new ToNativeContext());
if (!writeValue(offset + i*size, element, nativeType)) {
return false;
}
}
}
else {
throw new IllegalArgumentException("Inline array of "
+ cls + " not supported");
}
return true;
}
protected List getFieldOrder() {
synchronized(this) {
if (fieldOrder == null) {
@@ -978,7 +704,7 @@ public abstract class Structure {
}
}
try {
structField.size = getNativeSize(nativeType, value);
structField.size = Native.getNativeSize(nativeType, value);
fieldAlignment = getNativeAlignment(nativeType, value, i==0);
}
catch(IllegalArgumentException e) {
@@ -986,7 +712,8 @@ public abstract class Structure {
if (!force && typeMapper == null) {
return CALCULATE_SIZE;
}
throw e;
String msg = "Invalid Structure field in " + getClass() + ", field name '" + structField.name + "', " + structField.type + ": " + e.getMessage();
throw new IllegalArgumentException(msg);
}
// Align fields as appropriate
@@ -1045,7 +772,7 @@ public abstract class Structure {
type = tc.nativeType();
value = tc.toNative(value, new ToNativeContext());
}
int size = getNativeSize(type, value);
int size = Native.getNativeSize(type, value);
if (type.isPrimitive() || Long.class == type || Integer.class == type
|| Short.class == type || Character.class == type
|| Byte.class == type || Boolean.class == type
@@ -1092,33 +819,6 @@ public abstract class Structure {
return alignment;
}
/** Returns the native size of the given class, in bytes. */
private static int getNativeSize(Class type, Object value) {
if (type.isArray()) {
int len = Array.getLength(value);
if (len > 0) {
Object o = Array.get(value, 0);
return len * getNativeSize(type.getComponentType(), o);
}
// Don't process zero-length arrays
throw new IllegalArgumentException("Arrays of length zero not allowed in structure: " + type);
}
if (Structure.class.isAssignableFrom(type)
&& !Structure.ByReference.class.isAssignableFrom(type)) {
if (value == null)
value = newInstance(type);
return ((Structure)value).size();
}
try {
return Native.getNativeSize(type);
}
catch(IllegalArgumentException e) {
throw new IllegalArgumentException("The type \"" + type.getName()
+ "\" is not supported as a structure field: "
+ e.getMessage());
}
}
public String toString() {
return toString(0);
}
@@ -1165,7 +865,22 @@ public abstract class Structure {
value = ((Structure)value).toString(indent + 1);
}
}
contents += "=" + String.valueOf(value).trim();
contents += "=";
if (value instanceof Long) {
contents += Long.toHexString(((Long)value).longValue());
}
else if (value instanceof Integer) {
contents += Integer.toHexString(((Integer)value).intValue());
}
else if (value instanceof Short) {
contents += Integer.toHexString(((Short)value).shortValue());
}
else if (value instanceof Byte) {
contents += Integer.toHexString(((Byte)value).byteValue());
}
else {
contents += String.valueOf(value).trim();
}
contents += LS;
if (!i.hasNext())
contents += prefix + "}";
@@ -1211,6 +926,11 @@ public abstract class Structure {
array[i].useMemory(memory.share(i*size, size));
array[i].read();
}
if (this instanceof ByReference) {
this.array = array;
}
return array;
}
@@ -1229,20 +949,35 @@ public abstract class Structure {
public boolean equals(Object o) {
if (o == this)
return true;
if (o instanceof Structure && ((Structure)o).size() == size()) {
if (o.getClass().isAssignableFrom(getClass())
|| getClass().isAssignableFrom(o.getClass())) {
Structure s = (Structure)o;
Pointer p1 = getPointer();
Pointer p2 = s.getPointer();
for (int i=0;i < size();i++) {
if (p1.getByte(i) != p2.getByte(i)) {
return false;
}
}
return true;
if (o == null)
return false;
if (o.getClass() != getClass()) {
// Only allow one class derived from the other and implementing
// ByReference or ByValue, or both implementing
// ByReference/ByValue on the same base class
if (!((o.getClass().isAssignableFrom(getClass())
&& (ByReference.class.isAssignableFrom(getClass())
|| ByValue.class.isAssignableFrom(getClass())))
|| (getClass().isAssignableFrom(o.getClass())
&& (ByReference.class.isAssignableFrom(o.getClass())
|| ByValue.class.isAssignableFrom(o.getClass())))
|| ((ByReference.class.isAssignableFrom(o.getClass())
|| ByValue.class.isAssignableFrom(o.getClass()))
&& (ByReference.class.isAssignableFrom(getClass())
|| ByValue.class.isAssignableFrom(getClass()))
&& (o.getClass().getSuperclass()
== getClass().getSuperclass())))) {
return false;
}
}
Structure s = (Structure)o;
if (s.size() == size()) {
clear(); write();
byte[] buf = getPointer().getByteArray(0, size());
s.clear(); s.write();
byte[] sbuf = s.getPointer().getByteArray(0, s.size());
return Arrays.equals(buf, sbuf);
}
return false;
}
@@ -1250,8 +985,8 @@ public abstract class Structure {
* as the hash code.
*/
public int hashCode() {
Pointer p = getPointer();
return p != null ? p.hashCode() : 0;
clear(); write();
return Arrays.hashCode(getPointer().getByteArray(0, size()));
}
protected void cacheTypeInfo(Pointer p) {
@@ -1397,6 +1132,8 @@ public abstract class Structure {
typeInfoMap.put(Character.class, ctype);
typeInfoMap.put(byte.class, FFITypes.ffi_type_sint8);
typeInfoMap.put(Byte.class, FFITypes.ffi_type_sint8);
typeInfoMap.put(boolean.class, FFITypes.ffi_type_uint32);
typeInfoMap.put(Boolean.class, FFITypes.ffi_type_uint32);
typeInfoMap.put(Pointer.class, FFITypes.ffi_type_pointer);
typeInfoMap.put(String.class, FFITypes.ffi_type_pointer);
typeInfoMap.put(WString.class, FFITypes.ffi_type_pointer);
@@ -1485,22 +1222,9 @@ public abstract class Structure {
typeInfoMap.put(obj, type);
return type.getPointer();
}
throw new IllegalArgumentException("Unsupported structure field type " + cls);
throw new IllegalArgumentException("Unsupported type " + cls);
}
}
static String getSignature(Object o) {
Pointer p = get(o);
if (p == FFITypes.ffi_type_void) return "V";
if (p == FFITypes.ffi_type_float) return "F";
if (p == FFITypes.ffi_type_double) return "D";
if (p == FFITypes.ffi_type_sint8) return "B";
if (p == FFITypes.ffi_type_sint16) return "S";
if (p == FFITypes.ffi_type_uint16) return "C";
if (p == FFITypes.ffi_type_sint32) return "I";
if (p == FFITypes.ffi_type_sint64) return "J";
if (p == FFITypes.ffi_type_pointer) return "Lcom/sun/jna/Pointer;";
throw new IllegalArgumentException("Unsupported type " + o);
}
}
private class AutoAllocated extends Memory {
@@ -1508,4 +1232,26 @@ public abstract class Structure {
super(size);
}
}
public void autoRead() {
if (getAutoRead()) {
read();
if (array != null) {
for (int i=1;i < array.length;i++) {
array[i].autoRead();
}
}
}
}
public void autoWrite() {
if (getAutoWrite()) {
write();
if (array != null) {
for (int i=1;i < array.length;i++) {
array[i].autoWrite();
}
}
}
}
}
+1
Ver Arquivo
@@ -20,6 +20,7 @@ import java.nio.CharBuffer;
public final class WString implements CharSequence, Comparable {
private String string;
public WString(String s){
if (s == null) throw new NullPointerException("String initializer must be non-null");
this.string = s;
}
public String toString() {
@@ -275,6 +275,7 @@ public interface X11 extends Library {
/** Definition of the Xevie library. */
interface Xevie extends Library {
/** Instance of Xevie. Note: This extension has been removed from xorg/xserver on Oct 22, 2008 because it is broken and maintainerless. */
Xevie INSTANCE = (Xevie)Native.loadLibrary("Xevie", Xevie.class);
int XEVIE_UNMODIFIED = 0;
int XEVIE_MODIFIED = 1;
@@ -65,4 +65,65 @@ public interface Shell32 extends W32API {
}
}
int SHFileOperation(SHFILEOPSTRUCT fileop);
DWORD SHGFP_TYPE_CURRENT = new DWORD(0); // current value for user, verify it exists
DWORD SHGFP_TYPE_DEFAULT = new DWORD(1); // default value, may not exist
int CSIDL_DESKTOP = 0x0000; // <desktop>
int CSIDL_INTERNET = 0x0001; // Internet Explorer (icon on desktop)
int CSIDL_PROGRAMS = 0x0002; // Start Menu\Programs
int CSIDL_CONTROLS = 0x0003; // My Computer\Control Panel
int CSIDL_PRINTERS = 0x0004; // My Computer\Printers
int CSIDL_PERSONAL = 0x0005; // My Documents
int CSIDL_FAVORITES = 0x0006; // <user name>\Favorites
int CSIDL_STARTUP = 0x0007; // Start Menu\Programs\Startup
int CSIDL_RECENT = 0x0008; // <user name>\Recent
int CSIDL_SENDTO = 0x0009; // <user name>\SendTo
int CSIDL_BITBUCKET = 0x000a; // <desktop>\Recycle Bin
int CSIDL_STARTMENU = 0x000b; // <user name>\Start Menu
int CSIDL_MYDOCUMENTS = CSIDL_PERSONAL; // Personal was just a silly name for My Documents
int CSIDL_MYMUSIC = 0x000d; // "My Music" folder
int CSIDL_MYVIDEO = 0x000e; // "My Videos" folder
int CSIDL_DESKTOPDIRECTORY = 0x0010; // <user name>\Desktop
int CSIDL_DRIVES = 0x0011; // My Computer
int CSIDL_NETWORK = 0x0012; // Network Neighborhood (My Network Places)
int CSIDL_NETHOOD = 0x0013; // <user name>\nethood
int CSIDL_FONTS = 0x0014; // windows\fonts
int CSIDL_TEMPLATES = 0x0015;
int CSIDL_COMMON_STARTMENU = 0x0016; // All Users\Start Menu
int CSIDL_COMMON_PROGRAMS = 0X0017; // All Users\Start Menu\Programs
int CSIDL_COMMON_STARTUP = 0x0018; // All Users\Startup
int CSIDL_COMMON_DESKTOPDIRECTORY = 0x0019; // All Users\Desktop
int CSIDL_APPDATA = 0x001a; // <user name>\Application Data
int CSIDL_PRINTHOOD = 0x001b; // <user name>\PrintHood
int CSIDL_LOCAL_APPDATA = 0x001c; // <user name>\Local Settings\Applicaiton Data (non roaming)
int CSIDL_ALTSTARTUP = 0x001d; // non localized startup
int CSIDL_COMMON_ALTSTARTUP = 0x001e; // non localized common startup
int CSIDL_COMMON_FAVORITES = 0x001f;
int CSIDL_INTERNET_CACHE = 0x0020;
int CSIDL_COOKIES = 0x0021;
int CSIDL_HISTORY = 0x0022;
int CSIDL_COMMON_APPDATA = 0x0023; // All Users\Application Data
int CSIDL_WINDOWS = 0x0024; // GetWindowsDirectory()
int CSIDL_SYSTEM = 0x0025; // GetSystemDirectory()
int CSIDL_PROGRAM_FILES = 0x0026; // C:\Program Files
int CSIDL_MYPICTURES = 0x0027; // C:\Program Files\My Pictures
int CSIDL_PROFILE = 0x0028; // USERPROFILE
int CSIDL_SYSTEMX86 = 0x0029; // x86 system directory on RISC
int CSIDL_PROGRAM_FILESX86 = 0x002a; // x86 C:\Program Files on RISC
int CSIDL_PROGRAM_FILES_COMMON = 0x002b; // C:\Program Files\Common
int CSIDL_PROGRAM_FILES_COMMONX86 = 0x002c; // x86 Program Files\Common on RISC
int CSIDL_COMMON_TEMPLATES = 0x002d; // All Users\Templates
int CSIDL_COMMON_DOCUMENTS = 0x002e; // All Users\Documents
int CSIDL_COMMON_ADMINTOOLS = 0x002f; // All Users\Start Menu\Programs\Administrative Tools
int CSIDL_ADMINTOOLS = 0x0030; // <user name>\Start Menu\Programs\Administrative Tools
int CSIDL_CONNECTIONS = 0x0031; // Network and Dial-up Connections
int CSIDL_COMMON_MUSIC = 0x0035; // All Users\My Music
int CSIDL_COMMON_PICTURES = 0x0036; // All Users\My Pictures
int CSIDL_COMMON_VIDEO = 0x0037; // All Users\My Video
int CSIDL_RESOURCES = 0x0038; // Resource Direcotry
int CSIDL_RESOURCES_LOCALIZED = 0x0039; // Localized Resource Direcotry
int CSIDL_COMMON_OEM_LINKS = 0x003a; // Links to All Users OEM specific apps
int CSIDL_CDBURN_AREA = 0x003b; // USERPROFILE\Local Settings\Application Data\Microsoft\CD Burning
int CSIDL_COMPUTERSNEARME = 0x003d; // Computers Near Me (computered from Workgroup membership)
HRESULT SHGetFolderPath(HWND hwndOwner, int nFolder, HANDLE hToken, DWORD dwFlags, char[] pszPath);
}
@@ -68,7 +68,10 @@ public interface User32 extends W32API {
int LR_SHARED =0x8000;
HWND FindWindow(String winClass, String title);
/** ASCII version. */
int GetClassName(HWND hWnd, byte[] lpClassName, int nMaxCount);
/** Unicode version. */
int GetClassName(HWND hWnd, char[] lpClassName, int nMaxCount);
class GUITHREADINFO extends Structure {
public int cbSize = size();
public int flags;
@@ -96,15 +99,22 @@ public interface User32 extends W32API {
}
boolean GetWindowInfo(HWND hWnd, WINDOWINFO pwi);
boolean GetWindowRect(HWND hWnd, RECT rect);
/** ASCII version. */
int GetWindowText(HWND hWnd, byte[] lpString, int nMaxCount);
/** Unicode version. */
int GetWindowText(HWND hWnd, char[] lpString, int nMaxCount);
int GetWindowTextLength(HWND hWnd);
/** ASCII version. */
int GetWindowModuleFileName(HWND hWnd, byte[] lpszFileName, int cchFileNameMax);
/** Unicode version. */
int GetWindowModuleFileName(HWND hWnd, char[] lpszFileName, int cchFileNameMax);
int GetWindowThreadProcessId(HWND hWnd, IntByReference lpdwProcessId);
interface WNDENUMPROC extends StdCallCallback {
/** Return whether to continue enumeration. */
boolean callback(HWND hWnd, Pointer data);
}
boolean EnumWindows(WNDENUMPROC lpEnumFunc, Pointer data);
boolean EnumChildWindows(HWND hWnd, WNDENUMPROC lpEnumFunc, Pointer data);
boolean EnumThreadWindows(int dwThreadId, WNDENUMPROC lpEnumFunc, Pointer data);
boolean FlashWindowEx(FLASHWINFO info);
+23 -13
Ver Arquivo
@@ -17,6 +17,8 @@ import java.util.Map;
import com.sun.jna.FromNativeContext;
import com.sun.jna.IntegerType;
import com.sun.jna.Native;
import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
import com.sun.jna.PointerType;
import com.sun.jna.ptr.ByReference;
@@ -47,6 +49,9 @@ public interface W32API extends StdCallLibrary, W32Errors {
Map DEFAULT_OPTIONS = Boolean.getBoolean("w32.ascii") ? ASCII_OPTIONS : UNICODE_OPTIONS;
class HANDLE extends PointerType {
private boolean immutable;
public HANDLE() { }
public HANDLE(Pointer p) { setPointer(p); immutable = true; }
/** Override to the appropriate object for INVALID_HANDLE_VALUE. */
public Object fromNative(Object nativeValue, FromNativeContext context) {
Object o = super.fromNative(nativeValue, context);
@@ -54,6 +59,11 @@ public interface W32API extends StdCallLibrary, W32Errors {
return INVALID_HANDLE_VALUE;
return o;
}
public void setPointer(Pointer p) {
if (immutable)
throw new UnsupportedOperationException("immutable reference");
super.setPointer(p);
}
}
class WORD extends IntegerType {
@@ -64,29 +74,29 @@ public interface W32API extends StdCallLibrary, W32Errors {
public DWORD() { this(0); }
public DWORD(long value) { super(4, value); }
}
class LONG extends IntegerType {
public LONG() { this(0); }
public LONG(long value) { super(Native.LONG_SIZE, value); }
}
class HDC extends HANDLE { }
class HICON extends HANDLE { }
class HBITMAP extends HANDLE { }
class HRGN extends HANDLE { }
class HWND extends HANDLE { }
class HWND extends HANDLE {
public HWND() { }
public HWND(Pointer p) { super(p); }
}
class HINSTANCE extends HANDLE { }
class HMODULE extends HINSTANCE { }
class HRESULT extends NativeLong { }
/** Constant value representing an invalid HANDLE. */
HANDLE INVALID_HANDLE_VALUE = new HANDLE() {
{ super.setPointer(Pointer.createConstant(-1)); }
public void setPointer(Pointer p) {
throw new UnsupportedOperationException("Immutable reference");
}
};
HANDLE INVALID_HANDLE_VALUE = new HANDLE(Pointer.createConstant(-1));
/** Special HWND value. */
HWND HWND_BROADCAST = new HWND() {
{ super.setPointer(Pointer.createConstant(0xFFFF)); }
public void setPointer(Pointer p) {
throw new UnsupportedOperationException("Immutable reference");
}
};
HWND HWND_BROADCAST = new HWND(Pointer.createConstant(0xFFFF));
/** LPHANDLE */
class HANDLEByReference extends ByReference {
public HANDLEByReference() {
+78 -33
Ver Arquivo
@@ -44,6 +44,7 @@ additional JNI or native code.
<li><a href="#structures">Structures</a>
<li><a href="#unions">Unions</a>
<li><a href="#java-objects">Java Objects</a>
<li><a href="#last-error">Last Error</a>
</ul>
<li><a href="#invocation-mapping">Invocation Mapping</a>
<li><a href="#global-data">Library Global Data</a>
@@ -56,14 +57,25 @@ additional JNI or native code.
<a name="library-mapping"></a>
<h2>Library Mapping</h2>
When you've determined which shared library holds the methods to which you
need access, create an interface class corresponding to that library. For
example, a mapping for the C library itself would look like this:<br>
need access, create a class corresponding to that library. For
example, a mapping for the C library itself would look like one of the
following:<br>
<blockquote><code><pre>
// Alternative 1: interface-mapped class, dynamically load the C library
public interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary)Native.loadLibrary("c", CLibrary.class);
}
// Alternative 2: direct-mapped class
public class CLibrary {
static {
Native.register("c");
}
}
</pre></code></blockquote>
The <code>String</code> passed to the <code>Native.loadLibrary</code> method
The <code>String</code> passed to the
{@link com.sun.jna.Native#loadLibrary(String,Class)}
(or {@link com.sun.jna.NativeLibrary#getInstance(String)}) method
is the undecorated name of the shared library file. Here are some examples of
library name mappings.<p>
<style type="text/css">
@@ -77,11 +89,18 @@ blockquote { background-color:#EAEAEA; }
<tr><td>Linux</td><td>libX11.so</td><td>X11</td></tr>
<tr><td>Mac OS X</td><td>libm.dylib</td><td>m</td></tr>
<tr><td>Mac OS X Framework</td><td>/System/Library/Frameworks/Carbon.framework/Carbon</td><td>Carbon</td></tr>
<tr><td>Any Platform</td><td>&lt;current process&gt;</td><td><code>null</code></td></tr>
</table>
<p>
Any given native library with a unique filesystem path is represented by a single instance of {@link com.sun.jna.NativeLibrary} and obtained via {@link com.sun.jna.NativeLibrary#getInstance(String)}. The native library will be unloaded when no longer referenced by any Java code.
<p>
The search path for loaded native libraries may be modified by setting <code>jna.library.path</code>. See {@link com.sun.jna.NativeLibrary} for details.
If the library name is <code>null</code>, your mappings will apply to the
current process instead of a separately loaded library. This may help avoid
conflicts if there are several incompatible versions of a library available.
<p>
The search path for loaded native libraries may be modified by
setting <code>jna.library.path</code> and a few other properties. See {@link
com.sun.jna.NativeLibrary} for details.
<p>
<a href="#toc">Table of Contents</a>
<a name="function-mapping"></a>
@@ -94,6 +113,13 @@ public interface CLibrary extends Library {
int atol(String s);
}
</pre></code></blockquote>
Alternatively, you can map directly to a declared native method:<br>
<blockquote><code><pre>
public class CLibrary {
public static native int atol(String s);
}
</pre></code></blockquote>
If you prefer to rename the Java methods to conform to Java coding conventions, then you can provide an entry ({@link com.sun.jna.Library#OPTION_FUNCTION_MAPPER}/{@link com.sun.jna.FunctionMapper}) in the options {@link java.util.Map} passed to {@link com.sun.jna.Native#loadLibrary(String,Class,java.util.Map) Native.loadLibrary()} which maps the Java names to the native names. While this keeps your Java code a little cleaner, the additional mapping of names may make it a little less obvious the native functions being called.<p>
An instance of the {@link com.sun.jna.Function} class is obtained through the {@link com.sun.jna.NativeLibrary} instance corresponding to the containing native library. This {@link com.sun.jna.Function} instance handles argument marshalling and delegation to the native function.
@@ -106,30 +132,33 @@ An instance of the {@link com.sun.jna.Function} class is obtained through the {@
Java types must be chosen to match native types of the same size. Following are the types supported by the JNA library.<p>
<center>
<table border=1 borderColor=white class=styled width="100%">
<tr><td><b>Java Type</b></td><td><b>C Type</b></td><td><b>Native Representation</b></td></tr>
<tr><td>boolean</td><td>int</td><td>32-bit integer (customizable)</td>
<tr><td>byte</td><td>char</td><td>8-bit integer</td>
<tr><td>char</td><td>wchar_t</td><td>platform-dependent</td>
<tr><td>short</td><td>short</td><td>16-bit integer</td>
<tr><td>int</td><td>int</td><td>32-bit integer</td>
<tr><td>long</td><td>long long, __int64</td><td>64-bit integer</td>
<tr><td>float</td><td>float</td><td>32-bit floating point</td>
<tr><td>double</td><td>double</td><td>64-bit floating point</td>
<tr><td>{@link java.nio.Buffer}<br>
{@link com.sun.jna.Pointer}<td>pointer</td><td>platform-dependent (32- or 64-bit pointer to memory)</td>
<tr><td>&lt;T&gt;[] (array of primitive type)</td><td>pointer<br>array</td><td>32- or 64-bit pointer to memory (argument/return)<br>contiguous memory (struct member)</td>
<tr><td colspan=3>In addition to the above types, which are supported at the native layer, the JNA Java library automatically handles the following types. All but <code>NativeMapped</code> and <code>NativeLong</code> are converted to {@link com.sun.jna.Pointer} before being passed to the native layer.</td></tr>
<tr><td>{@link java.lang.String}</td><td>char*</td><td>NUL-terminated array (native encoding or <code>jna.encoding</code>)</td>
<tr><td>{@link com.sun.jna.WString}</td><td>wchar_t*</td><td>NUL-terminated array (unicode)</td>
<tr><td>{@link java.lang.String String[]}</td><td>char**</td><td>NULL-terminated array of C strings</td>
<tr><td>{@link com.sun.jna.WString WString[]}</td><td>wchar_t**</td><td>NULL-terminated array of wide C strings</td>
<tr><td>{@link com.sun.jna.Structure}</td><td>struct*<br>struct</td><td>pointer to struct (argument or return) ({@link com.sun.jna.Structure.ByReference or explicitly})<br>struct by value (member of struct) ({@link com.sun.jna.Structure.ByValue or explicitly})</td>
<tr><td>{@link com.sun.jna.Union}</td><td>union</td><td>same as <code>Structure</code></td>
<tr><td>{@link com.sun.jna.Structure Structure[]}</td><td>struct[]</td><td>array of structs, contiguous in memory</td>
<tr><td>{@link com.sun.jna.Callback}</td><td>&lt;T&gt; (*fp)()</td><td>function pointer (Java or native)</td>
<tr><td>{@link com.sun.jna.NativeMapped}</td><td>varies</td><td>depends on definition</td>
<tr><td>{@link com.sun.jna.NativeLong}</td><td>long</td><td>platform-dependent (32- or 64-bit integer)</td>
<tr><td>{@link com.sun.jna.PointerType}</td><td>pointer</td><td>same as <code>Pointer</code></td>
<tr><td><b>C Type</b></td><td><b>Native Representation</b></td><td><b>Java Type</b></td></tr>
<tr><td>char</td><td>8-bit integer</td><td>byte</td></tr>
<tr><td>wchar_t</td><td>platform-dependent</td><td>char</td></tr>
<tr><td>short</td><td>16-bit integer</td><td>short</td></tr>
<tr><td>int</td><td>32-bit integer</td><td>int</td></tr>
<tr><td>int</td><td>boolean flag</td><td>boolean</td></tr>
<tr><td>enum</td><td>enumeration type</td><td>int (usually)</td></tr>
<tr><td>long long, __int64</td><td>64-bit integer</td><td>long</td></tr>
<tr><td>float</td><td>32-bit floating point</td><td>float</td></tr>
<tr><td>double</td><td>64-bit floating point</td><td>double</td></tr>
<tr><td>pointer (e.g. void*)</td><td>platform-dependent (32- or 64-bit pointer to memory)</td><td>{@link java.nio.Buffer}<br>
{@link com.sun.jna.Pointer}</td></tr>
<tr><td>pointer (e.g. void*),<br>array</td><td>32- or 64-bit pointer to memory (argument/return)<br>contiguous memory (struct member)</td><td>&lt;P&gt;[] (array of primitive type)</td></tr>
<tr><td colspan='3' style='padding:20px 5px'>In addition to the above types, which are supported at the native layer, the JNA Java library automatically handles the following types. All but <code>NativeMapped</code> and <code>NativeLong</code> are converted to {@link com.sun.jna.Pointer} before being passed to the native layer.</td></tr>
<tr><td>long</td><td>platform-dependent (32- or 64-bit integer)</td><td>{@link com.sun.jna.NativeLong}</td></tr>
<tr><td>const char*</td><td>NUL-terminated array (native encoding or <code>jna.encoding</code>)</td><td>{@link java.lang.String}</td></tr>
<tr><td>const wchar_t*</td><td>NUL-terminated array (unicode)</td><td>{@link com.sun.jna.WString}</td></tr>
<tr><td>char**</td><td>NULL-terminated array of C strings</td><td>{@link java.lang.String String[]}</td></tr>
<tr><td>wchar_t**</td><td>NULL-terminated array of wide C strings</td><td>{@link com.sun.jna.WString WString[]}</td></tr>
<tr><td>void**</td><td>NULL-terminated array of pointers</td><td>{@link com.sun.jna.Pointer Pointer[]}</td></tr>
<tr><td>struct*<br>struct</td><td>pointer to struct (argument or return) ({@link com.sun.jna.Structure.ByReference or explicitly})<br>struct by value (member of struct) ({@link com.sun.jna.Structure.ByValue or explicitly})</td><td>{@link com.sun.jna.Structure}</td></tr>
<tr><td>union</td><td>same as <code>Structure</code></td><td>{@link com.sun.jna.Union}</td></tr>
<tr><td>struct[]</td><td>array of structs, contiguous in memory</td><td>{@link com.sun.jna.Structure Structure[]}</td></tr>
<tr><td>void (*FP)()</td><td>function pointer (Java or native)</td><td>{@link com.sun.jna.Callback}</td></tr>
<tr><td>pointer (&lt;T&gt; *)</td><td>same as <code>Pointer</code></td><td>{@link com.sun.jna.PointerType}</td></tr>
<tr><td>other</td><td>integer type</td><td>{@link com.sun.jna.IntegerType}</td></tr>
<tr><td>other</td><td>custom mapping, depends on definition</td><td>{@link com.sun.jna.NativeMapped}</td></tr>
</table>
</center>
<p>
@@ -144,8 +173,8 @@ Java types must be chosen to match native types of the same size. Following are
single call. If the native code keeps a reference to the memory, use {@link
com.sun.jna.Memory} or {@link java.nio.Buffer} instead.
<li>Primitive arrays and structures as members of a structure are overlaid on the parent structure memory.
<li>Bitfields must be manully packed into an integer type.
<li>All other types must eventually be converted to one of the types in this table. Methods with arguments or return values of types other than these must either use types deriving from {@link com.sun.jna.NativeMapped} or supply type conversion information for the unsupported types.
<li>Bitfields must be manually packed into an integer type.
<li>All other types must eventually be converted to one of the types in the this table. Methods with arguments or return values of types other than these must either use types deriving from {@link com.sun.jna.NativeMapped} or supply type conversion information for the unsupported types.
<li>Type mapping behavior may be customized by providing a {@link com.sun.jna.TypeMapper} for the {@link com.sun.jna.Library#OPTION_TYPE_MAPPER} option when initializing a library interface. See {@link com.sun.jna.win32.W32APITypeMapper} for an example which provides custom conversion of boolean and String types. You are free to use whatever types are convenient in your defined interfaces, but all custom types <em>must</em> provide a mapping to one of the basic or derived types listed above.
<li>Type mapping may also be customized on a per-class basis for user-defined types by making the user-defined type implement the {@link com.sun.jna.NativeMapped} interface.
<li><code>Structure</code> and <code>Union</code> are <em>not</em> converted to <code>Pointer</code> when passed by value.
@@ -589,6 +618,11 @@ method. On read, all non-pointer-based fields will be initialized from native
memory. Structure, String, and WString members will <em>not</em> be
initialized unless they are selected via {@link com.sun.jna.Union#setType}.
<a name="last-error"></a>
<h3>Obtaining "last" error</h3>
If a function sets the system error property
(<code><a href="http://www.opengroup.org/onlinepubs/009695399/functions/errno.html">errno</a></code> or <code><a href="http://msdn.microsoft.com/en-us/library/ms679360(VS.85).aspx">GetLastError()</a></code>), the error code will be thrown as a {@link com.sun.jna.LastErrorException} if you declare the exception in your JNA mapping. Alternatively, you can use {@link com.sun.jna.Native#getLastError()} to retrieve it, providing that {@link com.sun.jna.Native#setPreserveLastError(boolean)} has been called with a <code>true</code> value. Throwing an exception is preferred since it has better performance.
<a name="java-objects"></a>
<h3>Arbitrary Java Object arguments/return values</h3>
In some cases, such as invoking native VM functions directly, it is necessary
@@ -614,14 +648,25 @@ The method {@link com.sun.jna.NativeLibrary#getGlobalVariableAddress} may be use
<a href="#toc">Table of Contents</a>
<a name="crash-protection"></a>
<h2>VM Crash Protection</h2>
It is not uncommon when defining a new library and writing tests to encounter memory access errors which crash the VM. These are often caused by improper mappings or invalid arguments passed to the native library. To generate Java errors instead of crashing the VM, call {@link com.sun.jna.Native#setProtected Native.setProtected(true)}</code>. Not all platforms support this protection; if not, the value of {@link com.sun.jna.Native#isProtected} will remain <code>false</code>.
It is not uncommon when defining a new library and writing tests to encounter memory access errors which crash the VM. These are often caused by improper mappings or invalid arguments passed to the native library. To generate Java errors instead of crashing the VM, call {@link com.sun.jna.Native#setProtected Native.setProtected(true)}</code>. Not all platforms support this protection; if not, the value of {@link com.sun.jna.Native#isProtected} will remain <code>false</code>.<p>
NOTE: When protected mode is enabled, you should make use of the jsig library, if available (see <a href="http://java.sun.com/j2se/1.4.2/docs/guide/vm/signal-chaining.html">Signal Chaining</a>) to avoid interfering with the JVM's use of signals. In short, set the environment variable <code>LD_PRELOAD</code> (or <code>LD_PRELOAD_64</code>) to the path to <code>libjsig.so</code> in your JRE lib directory (usually ${java.home}/lib/${os.arch}/libjsig.so) before launching your Java application.
<p>
<a href="#toc">Table of Contents</a>
<a name="performance"></a>
<h2>Performance</h2>
<h3>Use direct mapping of methods</h3>
Using <a href="#direct-mapping">direct mapping</a> of methods makes native
calls more efficiently than does interface mapping. Direct mapping does not
support varargs calls or arrays of Pointer, String, or WString as an argument
or return value.
<h3>Avoid type mapping</h3>
Type mapping incurs additional overhead on each function call. You can avoid
this by ensuring that your arguments and/or return types are already primitive
types.
<h3>Pointer/Array/Buffer Variants</h3>
Java primitive arrays are generally slower to use than memory
Java primitive arrays are generally slower to use than direct memory
(Pointer, Memory, or ByReference) or NIO buffers, since the Java memory has to
be pinned and possibly copied across the native call, since the Java array is not necessarily contiguously allocated.
<h3>Large Structures</h3>
@@ -631,7 +676,7 @@ a performance hit using reflection to walk through all the fields. Structure
auto-synch can be disabled by calling
{@link com.sun.jna.Structure#setAutoSynch} with a <code>false</code> parameter.
It is then up to you to use {@link com.sun.jna.Structure#readField(String)}
and {@link com.sun.jna.Structure#writeField(String)}/{@link
and {@link com.sun.jna.Structure#writeField(String)} or {@link
com.sun.jna.Structure#writeField(String,Object)} to synch with just the fields
of interest.
</body>
+118 -6
Ver Arquivo
@@ -61,6 +61,12 @@ public class ArgumentsMarshalTest extends TestCase {
String returnStringArrayElement(String[] args, int which);
WString returnWideStringArrayElement(WString[] args, int which);
Pointer returnPointerArrayElement(Pointer[] args, int which);
public static class TestPointerType extends PointerType {
public TestPointerType() { }
public TestPointerType(Pointer p) { super(p); }
}
TestPointerType returnPointerArrayElement(TestPointerType[] args, int which);
CheckFieldAlignment returnPointerArrayElement(CheckFieldAlignment.ByReference[] args, int which);
int returnRotatedArgumentCount(String[] args);
@@ -89,6 +95,40 @@ public class ArgumentsMarshalTest extends TestCase {
// Nonexistent functions
boolean returnBooleanArgument(Object arg);
// Structure
class MinTestStructure extends Structure {
public int field;
}
Pointer testStructurePointerArgument(MinTestStructure s);
class VariableSizedStructure extends Structure {
public int length;
public byte[] buffer;
public VariableSizedStructure(String arg) {
length = arg.length() + 1;
buffer = new byte[length];
System.arraycopy(arg.getBytes(), 0, buffer, 0, arg.length());
}
}
String returnStringFromVariableSizedStructure(VariableSizedStructure s);
class CbStruct extends Structure {
public static interface TestCallback extends Callback {
int callback(int arg1, int arg2);
}
public TestCallback cb;
}
void setCallbackInStruct(CbStruct cbstruct);
// Union (by value)
class TestUnion extends Union implements Structure.ByValue {
public String f1;
public int f2;
}
interface UnionCallback extends Callback {
TestUnion invoke(TestUnion arg);
}
TestUnion testUnionByValueCallbackArgument(UnionCallback cb, TestUnion arg);
}
TestLibrary lib;
@@ -228,9 +268,12 @@ public class ArgumentsMarshalTest extends TestCase {
return new Integer(value);
}
}
public void testNativeMappedArgument() {
NativeMappedLibrary lib = (NativeMappedLibrary)
protected NativeMappedLibrary loadNativeMappedLibrary() {
return (NativeMappedLibrary)
Native.loadLibrary("testlib", NativeMappedLibrary.class);
}
public void testNativeMappedArgument() {
NativeMappedLibrary lib = loadNativeMappedLibrary();
final int MAGIC = 0x12345678;
Custom arg = new Custom(MAGIC);
assertEquals("Argument not mapped", MAGIC, lib.returnInt32Argument(arg));
@@ -490,7 +533,7 @@ public class ArgumentsMarshalTest extends TestCase {
public void testPointerArrayArgument() {
Pointer[] args = {
new NativeString(getName()).getPointer(),
new NativeString(getName()).getPointer(),
null,
new NativeString(getName()+"2").getPointer(),
};
@@ -500,15 +543,26 @@ public class ArgumentsMarshalTest extends TestCase {
assertNull("Native array should be null terminated", lib.returnPointerArrayElement(args, 3));
}
public void testNativeMappedArrayArgument() {
TestLibrary.TestPointerType[] args = {
new TestLibrary.TestPointerType(new NativeString(getName()).getPointer()),
null,
new TestLibrary.TestPointerType(new NativeString(getName()+"2").getPointer()),
};
assertEquals("Wrong value returned", args[0], lib.returnPointerArrayElement(args, 0));
assertNull("Wrong value returned", lib.returnPointerArrayElement(args, 1));
assertEquals("Wrong value returned", args[2], lib.returnPointerArrayElement(args, 2));
};
public void testStructureByReferenceArrayArgument() {
CheckFieldAlignment.ByReference[] args = {
new CheckFieldAlignment.ByReference(),
null,
new CheckFieldAlignment.ByReference(),
};
assertEquals("Wrong value returned", args[0], lib.returnPointerArrayElement(args, 0));
assertNull("Wrong value returned", lib.returnPointerArrayElement(args, 1));
assertEquals("Wrong value returned", args[2], lib.returnPointerArrayElement(args, 2));
assertEquals("Wrong value returned (0)", args[0], lib.returnPointerArrayElement(args, 0));
assertNull("Wrong value returned (1)", lib.returnPointerArrayElement(args, 1));
assertEquals("Wrong value returned (2)", args[2], lib.returnPointerArrayElement(args, 2));
assertNull("Native array should be null terminated", lib.returnPointerArrayElement(args, 3));
}
@@ -520,6 +574,64 @@ public class ArgumentsMarshalTest extends TestCase {
Arrays.asList(args));
}
public void testReadFunctionPointerAsCallback() {
TestLibrary.CbStruct s = new TestLibrary.CbStruct();
assertNull("Function pointer field should be null", s.cb);
lib.setCallbackInStruct(s);
assertNotNull("Callback field not set", s.cb);
}
public void testCallProxiedFunctionPointer() {
TestLibrary.CbStruct s = new TestLibrary.CbStruct();
lib.setCallbackInStruct(s);
assertEquals("Proxy to native function pointer failed: " + s.cb,
3, s.cb.callback(1, 2));
}
public void testVariableSizedStructureArgument() {
String EXPECTED = getName();
TestLibrary.VariableSizedStructure s =
new TestLibrary.VariableSizedStructure(EXPECTED);
assertEquals("Wrong string returned from variable sized struct",
EXPECTED, lib.returnStringFromVariableSizedStructure(s));
}
public void testDisableAutoSynch() {
TestLibrary.MinTestStructure s = new TestLibrary.MinTestStructure();
final int VALUE = 42;
s.field = VALUE;
s.setAutoWrite(false);
lib.testStructurePointerArgument(s);
assertEquals("Auto write should be disabled", 0, s.field);
final int EXPECTED = s.field;
s.getPointer().setInt(0, VALUE);
s.setAutoRead(false);
lib.testStructurePointerArgument(s);
assertEquals("Auto read should be disabled", EXPECTED, s.field);
}
public void testUnionByValueCallbackArgument() throws Exception{
TestLibrary.TestUnion arg = new TestLibrary.TestUnion();
arg.setType(String.class);
final String VALUE = getName();
arg.f1 = VALUE;
final boolean[] called = { false };
final String[] cbvalue = { null };
TestLibrary.TestUnion result = lib.testUnionByValueCallbackArgument(new TestLibrary.UnionCallback() {
public TestLibrary.TestUnion invoke(TestLibrary.TestUnion v) {
called[0] = true;
v.setType(String.class);
v.read();
cbvalue[0] = v.f1;
return v;
}
}, arg);
assertTrue("Callback not called", called[0]);
assertEquals("Incorrect callback union argument", VALUE, cbvalue[0]);
assertEquals("Union value not propagated", VALUE, result.getTypedValue(String.class));
}
public static void main(java.lang.String[] argList) {
junit.textui.TestRunner.run(ArgumentsMarshalTest.class);
}
@@ -18,6 +18,7 @@ import com.sun.jna.ptr.DoubleByReference;
import com.sun.jna.ptr.FloatByReference;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.LongByReference;
import com.sun.jna.ptr.NativeLongByReference;
import com.sun.jna.ptr.PointerByReference;
import com.sun.jna.ptr.ShortByReference;
@@ -32,6 +33,7 @@ public class ByReferenceArgumentsTest extends TestCase {
void incrementInt8ByReference(ByteByReference b);
void incrementInt16ByReference(ShortByReference s);
void incrementInt32ByReference(IntByReference i);
void incrementNativeLongByReference(NativeLongByReference l);
void incrementInt64ByReference(LongByReference l);
void complementFloatByReference(FloatByReference f);
void complementDoubleByReference(DoubleByReference d);
@@ -62,6 +64,12 @@ public class ByReferenceArgumentsTest extends TestCase {
lib.incrementInt32ByReference(iref);
assertEquals("Int argument not modified", 1, iref.getValue());
}
public void testNativeLongByReference() {
NativeLongByReference iref = new NativeLongByReference();
lib.incrementNativeLongByReference(iref);
assertEquals("Native long argument not modified",
new NativeLong(1), iref.getValue());
}
public void testLongByReference() {
LongByReference lref = new LongByReference();
lib.incrementInt64ByReference(lref);
+237 -83
Ver Arquivo
@@ -12,16 +12,19 @@
*/
package com.sun.jna;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;
import java.lang.ref.WeakReference;
import com.sun.jna.CallbacksTest.TestLibrary.CbCallback;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.Callback.UncaughtExceptionHandler;
import java.util.WeakHashMap;
import junit.framework.TestCase;
import com.sun.jna.Callback.UncaughtExceptionHandler;
import com.sun.jna.CallbacksTest.TestLibrary.CbCallback;
import com.sun.jna.ptr.IntByReference;
/** Exercise callback-related functionality.
*
* @author twall@users.sf.net
@@ -46,6 +49,19 @@ public class CallbacksTest extends TestCase {
public SmallTestStructure inner;
}
public static interface TestLibrary extends Library {
interface NoMethodCallback extends Callback {
}
interface CustomMethodCallback extends Callback {
void invoke();
}
interface TooManyMethodsCallback extends Callback {
void invoke();
void invoke2();
}
interface MultipleMethodsCallback extends Callback {
void invoke();
void callback();
}
interface VoidCallback extends Callback {
void callback();
}
@@ -116,11 +132,21 @@ public class CallbacksTest extends TestCase {
}
CbCallback callCallbackWithCallback(CbCallback cb);
public interface Int32CallbackX extends Callback {
interface Int32CallbackX extends Callback {
public int callback(int arg);
}
Int32CallbackX returnCallback();
Int32CallbackX returnCallbackArgument(Int32CallbackX cb);
interface CustomCallback extends Callback {
Custom callback(Custom arg1, Custom arg2);
}
int callInt32Callback(CustomCallback cb, int arg1, int arg2);
class CbStruct extends Structure {
public Callback cb;
}
void callCallbackInStruct(CbStruct cbstruct);
}
TestLibrary lib;
@@ -132,6 +158,66 @@ public class CallbacksTest extends TestCase {
lib = null;
}
public void testLookupNullCallback() {
assertNull("NULL pointer should result in null callback",
CallbackReference.getCallback(null, null));
try {
CallbackReference.getCallback(TestLibrary.VoidCallback.class, new Pointer(0));
fail("Null pointer lookup should fail");
}
catch(NullPointerException e) {
}
}
public void testLookupNonCallbackClass() {
try {
CallbackReference.getCallback(String.class, new Pointer(0));
fail("Request for non-Callback class should fail");
}
catch(IllegalArgumentException e) {
}
}
public void testNoMethodCallback() {
try {
CallbackReference.getCallback(TestLibrary.NoMethodCallback.class, new Pointer(1));
fail("Callback with no callback method should fail");
}
catch(IllegalArgumentException e) {
}
}
public void testCustomMethodCallback() {
CallbackReference.getCallback(TestLibrary.CustomMethodCallback.class, new Pointer(1));
}
public void testTooManyMethodsCallback() {
try {
CallbackReference.getCallback(TestLibrary.TooManyMethodsCallback.class, new Pointer(1));
fail("Callback lookup with too many methods should fail");
}
catch(IllegalArgumentException e) {
}
}
public void testMultipleMethodsCallback() {
CallbackReference.getCallback(TestLibrary.MultipleMethodsCallback.class, new Pointer(1));
}
public void testNativeFunctionPointerStringValue() {
Callback cb = CallbackReference.getCallback(TestLibrary.VoidCallback.class, new Pointer(1));
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));
assertEquals("Callback lookups for same pointer should return same Callback object", cb, cb2);
}
public void testGCCallback() throws Exception {
final boolean[] called = { false };
TestLibrary.VoidCallback cb = new TestLibrary.VoidCallback() {
@@ -142,16 +228,19 @@ public class CallbacksTest extends TestCase {
lib.callVoidCallback(cb);
assertTrue("Callback not called", called[0]);
Map refs = CallbackReference.callbackMap;
Map refs = new WeakHashMap(CallbackReference.callbackMap);
refs.putAll(CallbackReference.directCallbackMap);
assertTrue("Callback not cached", refs.containsKey(cb));
CallbackReference ref = (CallbackReference)refs.get(cb);
refs = ref.proxy != null ? CallbackReference.callbackMap
: CallbackReference.directCallbackMap;
Pointer cbstruct = ref.cbstruct;
cb = null;
System.gc();
for (int i = 0; i < 100 && (ref.get() != null || refs.containsValue(ref)); ++i) {
try {
Thread.sleep(1); // Give the GC a chance to run
Thread.sleep(10); // Give the GC a chance to run
} finally {}
}
assertNull("Callback not GC'd", ref.get());
@@ -159,9 +248,12 @@ public class CallbacksTest extends TestCase {
ref = null;
System.gc();
for (int i = 0; i < 100 && cbstruct.peer != 0; ++i) {
for (int i = 0; i < 100 && (cbstruct.peer != 0 || refs.size() > 0); ++i) {
// Flush weak hash map
refs.size();
try {
Thread.sleep(1); // Give the GC a chance to run
Thread.sleep(10); // Give the GC a chance to run
System.gc();
} finally {}
}
assertEquals("Callback trampoline not freed", 0, cbstruct.peer);
@@ -175,7 +267,7 @@ public class CallbacksTest extends TestCase {
};
assertEquals("Wrong callback interface",
TestLibrary.Int32Callback.class,
Native.findCallbackClass(cb.getClass()));
CallbackReference.findCallbackClass(cb.getClass()));
}
public void testCallInt32Callback() {
@@ -218,15 +310,20 @@ public class CallbacksTest extends TestCase {
public void testCallFloatCallback() {
final boolean[] called = { false };
final float[] args = { 0, 0 };
TestLibrary.FloatCallback cb = new TestLibrary.FloatCallback() {
public float callback(float arg, float arg2) {
called[0] = true;
args[0] = arg;
args[1] = arg2;
return arg + arg2;
}
};
final float EXPECTED = FLOAT_MAGIC*3;
float value = lib.callFloatCallback(cb, FLOAT_MAGIC, FLOAT_MAGIC*2);
assertTrue("Callback not called", called[0]);
assertEquals("Wrong first argument", FLOAT_MAGIC, args[0], 0);
assertEquals("Wrong second argument", FLOAT_MAGIC*2, args[1], 0);
assertEquals("Wrong callback value", EXPECTED, value, 0);
value = lib.callFloatCallback(cb, -1f, -2f);
@@ -235,15 +332,20 @@ public class CallbacksTest extends TestCase {
public void testCallDoubleCallback() {
final boolean[] called = { false };
final double[] args = { 0, 0 };
TestLibrary.DoubleCallback cb = new TestLibrary.DoubleCallback() {
public double callback(double arg, double arg2) {
called[0] = true;
args[0] = arg;
args[1] = arg2;
return arg + arg2;
}
};
final double EXPECTED = DOUBLE_MAGIC*3;
double value = lib.callDoubleCallback(cb, DOUBLE_MAGIC, DOUBLE_MAGIC*2);
assertTrue("Callback not called", called[0]);
assertEquals("Wrong first argument", DOUBLE_MAGIC, args[0], 0);
assertEquals("Wrong second argument", DOUBLE_MAGIC*2, args[1], 0);
assertEquals("Wrong callback value", EXPECTED, value, 0);
value = lib.callDoubleCallback(cb, -1d, -2d);
@@ -263,7 +365,7 @@ public class CallbacksTest extends TestCase {
};
SmallTestStructure value = lib.callStructureCallback(cb, s);
assertTrue("Callback not called", called[0]);
assertEquals("Wrong callback argument", s, cbarg[0]);
assertEquals("Wrong argument passed to callback", s, cbarg[0]);
assertEquals("Wrong structure return", s, value);
}
@@ -378,16 +480,10 @@ public class CallbacksTest extends TestCase {
return o instanceof Custom && ((Custom)o).value == value;
}
}
public static interface CustomCallback extends Callback {
Custom callback(Custom arg1, Custom arg2);
}
public static interface NativeMappedLibrary extends Library {
int callInt32Callback(CustomCallback cb, int arg1, int arg2);
}
public void testCallNativeMappedCallback() {
final boolean[] called = {false};
final Custom[] cbargs = { null, null};
CustomCallback cb = new CustomCallback() {
TestLibrary.CustomCallback cb = new TestLibrary.CustomCallback() {
public Custom callback(Custom arg, Custom arg2) {
called[0] = true;
cbargs[0] = arg;
@@ -395,8 +491,6 @@ public class CallbacksTest extends TestCase {
return new Custom(arg.value + arg2.value);
}
};
NativeMappedLibrary lib = (NativeMappedLibrary)
Native.loadLibrary("testlib", NativeMappedLibrary.class);
int value = lib.callInt32Callback(cb, 1, 2);
assertTrue("Callback not called", called[0]);
assertEquals("Wrong callback argument 1", new Custom(1), cbargs[0]);
@@ -533,6 +627,26 @@ public class CallbacksTest extends TestCase {
assertEquals("Callback reference should be reused", cb, cb2);
}
public void testDefaultCallbackExceptionHandler() {
final RuntimeException ERROR = new RuntimeException(getName());
PrintStream ps = System.err;
ByteArrayOutputStream s = new ByteArrayOutputStream();
System.setErr(new PrintStream(s));
try {
TestLibrary.CbCallback cb = new TestLibrary.CbCallback() {
public CbCallback callback(CbCallback arg) {
throw ERROR;
}
};
TestLibrary.CbCallback cb2 = lib.callCallbackWithCallback(cb);
String output = s.toString();
assertTrue("Default handler not called", output.length() > 0);
}
finally {
System.setErr(ps);
}
}
/* Most Callbacks are wrapped in DefaultCallbackProxy, which catches their
* exceptions.
*/
@@ -611,61 +725,7 @@ public class CallbacksTest extends TestCase {
Native.getCallbackExceptionHandler());
}
public static interface CallbackTestLibrary extends Library {
interface Int32Callback extends Callback {
float callback(float arg, float arg2);
}
float callInt32Callback(Int32Callback c, float arg, float arg2);
}
public void testCallbackTypeMappingFromLibrary() throws Exception {
final DefaultTypeMapper mapper = new DefaultTypeMapper();
Map options = new HashMap() {
{ put(Library.OPTION_TYPE_MAPPER, mapper); }
};
CallbackTestLibrary lib = (CallbackTestLibrary)
Native.loadLibrary("testlib", CallbackTestLibrary.class, options);
// Convert java floats into native integers and back
TypeConverter converter = new TypeConverter() {
public Object fromNative(Object value, FromNativeContext context) {
return new Float(((Integer)value).intValue());
}
public Class nativeType() {
return Integer.class;
}
public Object toNative(Object value, ToNativeContext ctx) {
return new Integer(Math.round(((Float)value).floatValue()));
}
};
mapper.addTypeConverter(float.class, converter);
CallbackTestLibrary.Int32Callback cb = new CallbackTestLibrary.Int32Callback() {
public float callback(float arg, float arg2) {
return arg + arg2;
}
};
assertEquals("Wrong type mapper for callback class", mapper,
Native.getTypeMapper(CallbackTestLibrary.Int32Callback.class));
assertEquals("Wrong type mapper for callback object", mapper,
Native.getTypeMapper(cb.getClass()));
assertEquals("Wrong type mapper used in callback invocation",
-2, lib.callInt32Callback(cb, -1, -1), 0);
}
private static class TestCallback implements Callback {
public static final TypeMapper TYPE_MAPPER = new DefaultTypeMapper();
public void callback() { }
}
public void testCallbackTypeMappingFromCallback() throws Exception {
assertEquals("Wrong type mapper for callback class",
TestCallback.TYPE_MAPPER,
Native.getTypeMapper(TestCallback.class));
}
public void testInvokeCallback() {
TestLibrary lib = (TestLibrary)
Native.loadLibrary("testlib", TestLibrary.class);
TestLibrary.Int32CallbackX cb = lib.returnCallback();
assertNotNull("Callback should not be null", cb);
assertEquals("Callback should be callable", 1, cb.callback(1));
@@ -681,21 +741,14 @@ public class CallbacksTest extends TestCase {
cb, lib.returnCallbackArgument(cb));
}
static class CbStruct extends Structure {
public Callback cb;
}
interface CbTest extends Library {
public void callCallbackInStruct(CbStruct cbstruct);
}
public void testCallCallbackInStructure() {
final boolean[] flag = {false};
final CbStruct s = new CbStruct();
final TestLibrary.CbStruct s = new TestLibrary.CbStruct();
s.cb = new Callback() {
public void callback() {
flag[0] = true;
}
};
CbTest lib = (CbTest)Native.loadLibrary("testlib", CbTest.class);
lib.callCallbackInStruct(s);
assertTrue("Callback not invoked", flag[0]);
}
@@ -721,6 +774,107 @@ public class CallbacksTest extends TestCase {
lib.callVoidCallback(cb);
}
public static interface CallbackTestLibrary extends Library {
final TypeMapper _MAPPER = new DefaultTypeMapper() {
{
// Convert java doubles into native integers and back
TypeConverter converter = new TypeConverter() {
public Object fromNative(Object value, FromNativeContext context) {
return new Double(((Integer)value).intValue());
}
public Class nativeType() {
return Integer.class;
}
public Object toNative(Object value, ToNativeContext ctx) {
return new Integer(((Double)value).intValue());
}
};
addTypeConverter(double.class, converter);
converter = new TypeConverter() {
public Object fromNative(Object value, FromNativeContext context) {
return new Float(((Long)value).intValue());
}
public Class nativeType() {
return Long.class;
}
public Object toNative(Object value, ToNativeContext ctx) {
return new Long(((Float)value).longValue());
}
};
addTypeConverter(float.class, converter);
}
};
final Map _OPTIONS = new HashMap() {
{
put(Library.OPTION_TYPE_MAPPER, _MAPPER);
}
};
interface DoubleCallback extends Callback {
double callback(double arg, double arg2);
}
double callInt32Callback(DoubleCallback c, double arg, double arg2);
interface FloatCallback extends Callback {
float callback(float arg, float arg2);
}
float callInt64Callback(FloatCallback c, float arg, float arg2);
}
protected CallbackTestLibrary loadCallbackTestLibrary() {
return (CallbackTestLibrary)
Native.loadLibrary("testlib", CallbackTestLibrary.class, CallbackTestLibrary._OPTIONS);
}
/** This test is here instead of NativeTest in order to facilitate running
the exact same test on a direct-mapped library without the tests
interfering with one another due to persistent/cached state in library
loading.
*/
public void testCallbackUsesTypeMapper() throws Exception {
CallbackTestLibrary lib = loadCallbackTestLibrary();
final double[] ARGS = new double[2];
CallbackTestLibrary.DoubleCallback cb = new CallbackTestLibrary.DoubleCallback() {
public double callback(double arg, double arg2) {
ARGS[0] = arg;
ARGS[1] = arg2;
return arg + arg2;
}
};
assertEquals("Wrong type mapper for callback class", lib._MAPPER,
Native.getTypeMapper(CallbackTestLibrary.DoubleCallback.class));
assertEquals("Wrong type mapper for callback object", lib._MAPPER,
Native.getTypeMapper(cb.getClass()));
double result = lib.callInt32Callback(cb, -1, -1);
assertEquals("Wrong callback argument 1", -1, ARGS[0], 0);
assertEquals("Wrong callback argument 2", -1, ARGS[1], 0);
assertEquals("Incorrect result of callback invocation", -2, result, 0);
}
public void testCallbackUsesTypeMapperWithDifferentReturnTypeSize() throws Exception {
CallbackTestLibrary lib = loadCallbackTestLibrary();
final float[] ARGS = new float[2];
CallbackTestLibrary.FloatCallback cb = new CallbackTestLibrary.FloatCallback() {
public float callback(float arg, float arg2) {
ARGS[0] = arg;
ARGS[1] = arg2;
return arg + arg2;
}
};
assertEquals("Wrong type mapper for callback class", lib._MAPPER,
Native.getTypeMapper(CallbackTestLibrary.FloatCallback.class));
assertEquals("Wrong type mapper for callback object", lib._MAPPER,
Native.getTypeMapper(cb.getClass()));
float result = lib.callInt64Callback(cb, -1, -1);
assertEquals("Wrong callback argument 1", -1, ARGS[0], 0);
assertEquals("Wrong callback argument 2", -1, ARGS[1], 0);
assertEquals("Incorrect result of callback invocation", -2, result, 0);
}
public static void main(java.lang.String[] argList) {
junit.textui.TestRunner.run(CallbacksTest.class);
}
@@ -0,0 +1,137 @@
/* Copyright (c) 2009 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.
* <p/>
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package com.sun.jna;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.nio.LongBuffer;
import java.nio.ShortBuffer;
/** Exercise a range of native methods.
*
* @author twall@users.sf.net
*/
public class DirectArgumentsMarshalTest extends ArgumentsMarshalTest {
public static class DirectTestLibrary implements TestLibrary {
/** Dummy. Automatically fail when passed an object. */
public String returnStringArgument(Object arg) {throw new IllegalArgumentException(arg.getClass().getName()); }
public native boolean returnBooleanArgument(boolean arg);
public native byte returnInt8Argument(byte arg);
public native char returnWideCharArgument(char arg);
public native short returnInt16Argument(short arg);
public native int returnInt32Argument(int i);
public native long returnInt64Argument(long l);
public native NativeLong returnLongArgument(NativeLong l);
public native float returnFloatArgument(float f);
public native double returnDoubleArgument(double d);
public native String returnStringArgument(String s);
public native WString returnWStringArgument(WString s);
public native Pointer returnPointerArgument(Pointer p);
public String returnStringArrayElement(String[] args, int which) {throw new UnsupportedOperationException();}
public WString returnWideStringArrayElement(WString[] args, int which) {throw new UnsupportedOperationException();}
public Pointer returnPointerArrayElement(Pointer[] args, int which) {throw new UnsupportedOperationException();}
public TestPointerType returnPointerArrayElement(TestPointerType[] args, int which) {throw new UnsupportedOperationException();}
public CheckFieldAlignment returnPointerArrayElement(CheckFieldAlignment.ByReference[] args, int which) {throw new UnsupportedOperationException();}
public int returnRotatedArgumentCount(String[] args) {throw new UnsupportedOperationException();}
public native long checkInt64ArgumentAlignment(int i, long j, int i2, long j2);
public native double checkDoubleArgumentAlignment(float i, double j, float i2, double j2);
public native Pointer testStructurePointerArgument(CheckFieldAlignment p);
public native double testStructureByValueArgument(CheckFieldAlignment.ByValue p);
public int testStructureArrayInitialization(CheckFieldAlignment[] p, int len) {
throw new UnsupportedOperationException();
}
public void modifyStructureArray(CheckFieldAlignment[] p, int length) {
throw new UnsupportedOperationException();
}
public native int fillInt8Buffer(byte[] buf, int len, byte value);
public native int fillInt16Buffer(short[] buf, int len, short value);
public native int fillInt32Buffer(int[] buf, int len, int value);
public native int fillInt64Buffer(long[] buf, int len, long value);
// ByteBuffer alternative definitions
public native int fillInt8Buffer(ByteBuffer buf, int len, byte value);
public native int fillInt16Buffer(ByteBuffer buf, int len, short value);
public native int fillInt32Buffer(ByteBuffer buf, int len, int value);
public native int fillInt64Buffer(ByteBuffer buf, int len, long value);
// {Short,Int,Long}Buffer alternative definitions
public native int fillInt16Buffer(ShortBuffer buf, int len, short value);
public native int fillInt32Buffer(IntBuffer buf, int len, int value);
public native int fillInt64Buffer(LongBuffer buf, int len, long value);
// dummy to avoid causing Native.register to fail
public boolean returnBooleanArgument(Object arg) {throw new IllegalArgumentException();}
public native Pointer testStructurePointerArgument(MinTestStructure s);
public native String returnStringFromVariableSizedStructure(VariableSizedStructure s);
public native void setCallbackInStruct(CbStruct s);
public native TestUnion testUnionByValueCallbackArgument(UnionCallback cb, TestUnion arg);
static {
Native.register("testlib");
}
}
/* Override original. */
protected void setUp() {
lib = new DirectTestLibrary();
}
public static class DirectNativeMappedLibrary implements NativeMappedLibrary {
public native int returnInt32Argument(Custom arg);
static {
Native.register("testlib");
}
}
protected NativeMappedLibrary loadNativeMappedLibrary() {
return new DirectNativeMappedLibrary();
}
// This test crashes on w32 IBM J9 unless -Xint is used
// (jvmwi3260-20080415_18762)
public void testWideCharArgument() {
if (Platform.isWindows()
&& "IBM".equals(System.getProperty("java.vm.vendor"))) {
fail("XFAIL, crash avoided");
}
super.testWideCharArgument();
}
// This test crashes on w32 IBM J9 unless -Xint is used
// (jvmwi3260-20080415_18762)
public void testWStringArgumentReturn() {
if (Platform.isWindows()
&& "IBM".equals(System.getProperty("java.vm.vendor"))) {
fail("XFAIL, crash avoided");
}
super.testWStringArgumentReturn();
}
// Override tests not yet supported
public void testStringArrayArgument() { }
public void testWriteStructureArrayArgumentMemory() { }
public void testUninitializedStructureArrayArgument() { }
public void testRejectNoncontiguousStructureArrayArgument() { }
public void testWideStringArrayArgument() { }
public void testPointerArrayArgument() { }
public void testNativeMappedArrayArgument() { }
public void testStructureByReferenceArrayArgument() { }
public void testModifiedCharArrayArgument() { }
public static void main(java.lang.String[] argList) {
junit.textui.TestRunner.run(DirectArgumentsMarshalTest.class);
}
}
@@ -0,0 +1,54 @@
/* Copyright (c) 2009 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.
* <p/>
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package com.sun.jna;
import com.sun.jna.ptr.ByteByReference;
import com.sun.jna.ptr.DoubleByReference;
import com.sun.jna.ptr.FloatByReference;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.LongByReference;
import com.sun.jna.ptr.NativeLongByReference;
import com.sun.jna.ptr.PointerByReference;
import com.sun.jna.ptr.ShortByReference;
/** Exercise a range of native methods.
*
* @author twall@users.sf.net
*/
public class DirectByReferenceArgumentsTest extends ByReferenceArgumentsTest {
public static class DirectTestLibrary implements TestLibrary {
public native void incrementInt8ByReference(ByteByReference b);
public native void incrementInt16ByReference(ShortByReference s);
public native void incrementInt32ByReference(IntByReference i);
public native void incrementNativeLongByReference(NativeLongByReference i);
public native void incrementInt64ByReference(LongByReference l);
public native void complementFloatByReference(FloatByReference f);
public native void complementDoubleByReference(DoubleByReference d);
public native void setPointerByReferenceNull(PointerByReference p);
static {
Native.register("testlib");
}
}
protected void setUp() {
lib = new DirectTestLibrary();
}
public static void main(java.lang.String[] argList) {
junit.textui.TestRunner.run(DirectByReferenceArgumentsTest.class);
}
}
@@ -0,0 +1,77 @@
/* Copyright (c) 2009 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.
* <p/>
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package com.sun.jna;
import java.util.Map;
import com.sun.jna.ptr.IntByReference;
/** Exercise callback-related functionality.
*
* @author twall@users.sf.net
*/
public class DirectCallbacksTest extends CallbacksTest {
public static class DirectTestLibrary implements TestLibrary {
public native void callVoidCallback(VoidCallbackCustom c);
public native boolean callBooleanCallback(BooleanCallback c, boolean arg, boolean arg2);
public native byte callInt8Callback(ByteCallback c, byte arg, byte arg2);
public native short callInt16Callback(ShortCallback c, short arg, short arg2);
public native int callInt32Callback(Int32Callback c, int arg, int arg2);
public native NativeLong callNativeLongCallback(NativeLongCallback c, NativeLong arg, NativeLong arg2);
public native long callInt64Callback(Int64Callback c, long arg, long arg2);
public native float callFloatCallback(FloatCallback c, float arg, float arg2);
public native double callDoubleCallback(DoubleCallback c, double arg, double arg2);
public native SmallTestStructure callStructureCallback(StructureCallback c, SmallTestStructure arg);
public native String callStringCallback(StringCallback c, String arg);
public native WString callWideStringCallback(WideStringCallback c, WString arg);
public Pointer callStringArrayCallback(StringArrayCallback c, String[] arg) { throw new UnsupportedOperationException(); }
public native int callCallbackWithByReferenceArgument(CopyArgToByReference cb, int arg, IntByReference result);
public native TestStructure.ByValue callCallbackWithStructByValue(TestStructure.TestCallback callback, TestStructure.ByValue cbstruct);
public native CbCallback callCallbackWithCallback(CbCallback cb);
public native Int32CallbackX returnCallback();
public native Int32CallbackX returnCallbackArgument(Int32CallbackX cb);
public native void callVoidCallback(VoidCallback c);
public native int callInt32Callback(CustomCallback cb, int arg1, int arg2);
public native void callCallbackInStruct(CbStruct s);
static {
Native.register("testlib");
}
}
protected void setUp() {
lib = new DirectTestLibrary();
}
public static class DirectCallbackTestLibrary implements CallbackTestLibrary {
public native double callInt32Callback(DoubleCallback c, double arg, double arg2);
public native float callInt64Callback(FloatCallback c, float arg, float arg2);
static {
Native.register(NativeLibrary.getInstance("testlib", _OPTIONS));
}
}
protected CallbackTestLibrary loadCallbackTestLibrary() {
return new DirectCallbackTestLibrary();
}
// Currently unsupported tests
public void testCallStringArrayCallback() { }
public void testCallbackExceptionHandlerWithCallbackProxy() { }
public static void main(java.lang.String[] argList) {
junit.textui.TestRunner.run(DirectCallbacksTest.class);
}
}
@@ -0,0 +1,95 @@
/* Copyright (c) 2009 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.
* <p/>
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package com.sun.jna;
import java.util.HashMap;
import java.util.Map;
import junit.framework.TestCase;
import com.sun.jna.ReturnTypesTest.TestLibrary.SimpleStructure;
import com.sun.jna.ReturnTypesTest.TestLibrary.TestStructure;
import com.sun.jna.ReturnTypesTest.TestLibrary.TestSmallStructure;
/** Exercise a range of native methods.
*
* @author twall@users.sf.net
*/
public class DirectReturnTypesTest extends ReturnTypesTest {
public static class DirectTestLibrary implements TestLibrary {
public Object returnObjectArgument(Object s) {
throw new IllegalArgumentException(s.getClass().getName());
}
public TestObject returnObjectArgument(TestObject s) {
throw new IllegalArgumentException(s.getClass().getName());
}
public native boolean returnFalse();
public native boolean returnTrue();
public native int returnInt32Zero();
public native int returnInt32Magic();
public native long returnInt64Zero();
public native long returnInt64Magic();
public native NativeLong returnLongZero();
public native NativeLong returnLongMagic();
public native float returnFloatZero();
public native float returnFloatMagic();
public native double returnDoubleZero();
public native double returnDoubleMagic();
public native String returnStringMagic();
public native WString returnWStringMagic();
public native SimpleStructure returnStaticTestStructure();
public native SimpleStructure returnNullTestStructure();
public native TestSmallStructure.ByValue returnSmallStructureByValue();
public native TestStructure.ByValue returnStructureByValue();
public Pointer[] returnPointerArgument(Pointer[] arg) {throw new UnsupportedOperationException();}
public String[] returnPointerArgument(String[] arg) {throw new UnsupportedOperationException();}
public WString[] returnPointerArgument(WString[] arg) {throw new UnsupportedOperationException();}
static {
Native.register("testlib");
}
}
protected void setUp() {
lib = new DirectTestLibrary();
}
public static class DirectObjectTestLibrary extends DirectTestLibrary {
public DirectObjectTestLibrary(Map options) {
Native.register(getClass(), NativeLibrary.getInstance("testlib", options));
}
}
public static class DirectNativeMappedLibrary implements NativeMappedLibrary {
public native Custom returnInt32Argument(int arg);
static {
Native.register("testlib");
}
}
protected NativeMappedLibrary loadNativeMappedLibrary() {
return new DirectNativeMappedLibrary();
}
// Override not-yet-supported tests
public void testReturnObject() { }
public void testReturnPointerArray() { }
public void testReturnStringArray() { }
public void testReturnWStringArray() { }
public static void main(java.lang.String[] argList) {
junit.textui.TestRunner.run(DirectReturnTypesTest.class);
}
}
+527
Ver Arquivo
@@ -0,0 +1,527 @@
/* Copyright (c) 2009 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.
* <p/>
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package com.sun.jna;
import junit.framework.*;
import com.sun.jna.*;
import com.sun.jna.ptr.PointerByReference;
import java.lang.ref.*;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
public class DirectTest extends TestCase {
private static final String BUILDDIR =
System.getProperty("jna.builddir",
"build" + (Platform.is64Bit() ? "-d64" : ""));
private static class JNI {
static {
String path = BUILDDIR + "/native/" + System.mapLibraryName("testlib");;
if (!new File(path).isAbsolute()) {
path = System.getProperty("user.dir") + "/" + path;
}
if (path.endsWith(".jnilib")) {
path = path.replace(".jnilib", ".dylib");
}
System.load(path);
}
private static native double cos(double x);
}
public static void main(java.lang.String[] argList) {
junit.textui.TestRunner.run(DirectTest.class);
checkPerformance();
}
static class MathLibrary {
public static native double cos(double x);
static {
Native.register(Platform.isWindows()?"msvcrt":"m");
}
}
interface MathInterface extends Library {
double cos(double x);
}
static class CLibrary {
public static class size_t extends IntegerType {
public size_t() {
super(Native.POINTER_SIZE);
}
public size_t(long value) {
super(Native.POINTER_SIZE, value);
}
}
public static native Pointer memset(Pointer p, int v, size_t len);
public static native Pointer memset(Pointer p, int v, int len);
public static native Pointer memset(Pointer p, int v, long len);
public static native long memset(long p, int v, long len);
public static native int memset(int p, int v, int len);
public static native int strlen(String s1);
public static native int strlen(Pointer p);
public static native int strlen(byte[] b);
public static native int strlen(Buffer b);
static {
Native.register(Platform.isWindows()?"msvcrt":"c");
}
}
static interface CInterface extends Library {
Pointer memset(Pointer p, int v, int len);
int strlen(String s);
}
static interface TestInterface extends Library {
interface Int32Callback extends Callback {
int invoke(int arg1, int arg2);
}
interface NativeLongCallback extends Callback {
NativeLong invoke(NativeLong arg1, NativeLong arg2);
}
int callInt32CallbackRepeatedly(Int32Callback cb, int arg1, int arg2, int count);
NativeLong callLongCallbackRepeatedly(NativeLongCallback cb, NativeLong arg1, NativeLong arg2, int count);
}
static class TestLibrary implements TestInterface {
public native int callInt32CallbackRepeatedly(Int32Callback cb, int arg1, int arg2, int count);
public native NativeLong callLongCallbackRepeatedly(NativeLongCallback cb, NativeLong arg1, NativeLong arg2, int count);
static {
Native.register("testlib");
}
}
private static class TestLoader extends URLClassLoader {
public TestLoader() throws MalformedURLException {
super(new URL[] {
new File(BUILDDIR + "/classes").toURI().toURL(),
new File(BUILDDIR + "/test-classes").toURI().toURL(),
}, null);
}
}
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";
ClassLoader loader = new TestLoader();
Class cls = Class.forName(name, true, loader);
assertNotNull("Failed loading class", cls);
WeakReference ref = new WeakReference(cls);
loader = null;
cls = null;
System.gc();
for (int i=0;i < 100 && ref.get() != null;i++) {
try {
Thread.sleep(10); // Give the GC a chance to run
System.gc();
} finally {}
}
// TODO: need a real check to ensure native memory is freed
assertNull("Registered methods not GC'd: " + ref.get(), ref.get());
}
private Class returnCallingClass() {
return Native.getCallingClass();
}
public void testFindCallingClass() {
assertEquals("Wrong calling class detected",
getClass(), returnCallingClass());
}
public void testFindNativeClass() {
class UnregisterLibrary {
class Inner {
public Class getNativeClass() {
return getNativeClassInner();
}
public Class getNativeClassInner() {
return Native.getNativeClass(Native.getCallingClass());
};
}
public native double cos(double x);
public Class getNativeClass() {
return new Inner().getNativeClass();
};
}
assertEquals("Wrong native class found",
UnregisterLibrary.class, new UnregisterLibrary().getNativeClass());
}
// Requires java.library.path include testlib
public static void checkPerformance() {
final int COUNT = 100000;
System.out.println("Checking performance of different access methods (" + COUNT + " iterations)");
final int SIZE = 8*1024;
ByteBuffer b = ByteBuffer.allocateDirect(SIZE);
// Native order is faster
b.order(ByteOrder.nativeOrder());
Pointer pb = Native.getDirectBufferPointer(b);
String mname = Platform.isWindows()?"msvcrt":"m";
MathInterface mlib = (MathInterface)
Native.loadLibrary(mname, MathInterface.class);
Function f = NativeLibrary.getInstance(mname).getFunction("cos");
///////////////////////////////////////////
// cos
Object[] args = { new Double(0) };
double dresult;
long start = System.currentTimeMillis();
for (int i=0;i < COUNT;i++) {
dresult = mlib.cos(0d);
}
long delta = System.currentTimeMillis() - start;
System.out.println("cos (JNA interface): " + delta + "ms");
start = System.currentTimeMillis();
for (int i=0;i < COUNT;i++) {
dresult = f.invokeDouble(args);
}
delta = System.currentTimeMillis() - start;
System.out.println("cos (JNA function): " + delta + "ms");
start = System.currentTimeMillis();
for (int i=0;i < COUNT;i++) {
dresult = MathLibrary.cos(0d);
}
delta = System.currentTimeMillis() - start;
System.out.println("cos (JNA direct): " + delta + "ms");
long types = pb.peer;
long cif;
long resp;
long argv;
if (Native.POINTER_SIZE == 4) {
b.putInt(0, (int)Structure.FFIType.get(double.class).peer);
cif = Native.ffi_prep_cif(0, 1, Structure.FFIType.get(double.class).peer, types);
resp = pb.peer + 4;
argv = pb.peer + 12;
double INPUT = 42;
start = System.currentTimeMillis();
for (int i=0;i < COUNT;i++) {
b.putInt(12, (int)pb.peer + 16);
b.putDouble(16, INPUT);
Native.ffi_call(cif, f.peer, resp, argv);
dresult = b.getDouble(4);
}
delta = System.currentTimeMillis() - start;
}
else {
b.putLong(0, Structure.FFIType.get(double.class).peer);
cif = Native.ffi_prep_cif(0, 1, Structure.FFIType.get(double.class).peer, types);
resp = pb.peer + 8;
argv = pb.peer + 16;
double INPUT = 42;
start = System.currentTimeMillis();
for (int i=0;i < COUNT;i++) {
b.putLong(16, pb.peer + 24);
b.putDouble(24, INPUT);
Native.ffi_call(cif, f.peer, resp, argv);
dresult = b.getDouble(8);
}
delta = System.currentTimeMillis() - start;
}
System.out.println("cos (JNI ffi): " + delta + "ms");
start = System.currentTimeMillis();
for (int i=0;i < COUNT;i++) {
dresult = JNI.cos(0d);
}
delta = System.currentTimeMillis() - start;
System.out.println("cos (JNI): " + delta + "ms");
start = System.currentTimeMillis();
for (int i=0;i < COUNT;i++) {
dresult = Math.cos(0d);
}
delta = System.currentTimeMillis() - start;
System.out.println("cos (pure java): " + delta + "ms");
///////////////////////////////////////////
// memset
Pointer presult;
String cname = Platform.isWindows()?"msvcrt":"c";
CInterface clib = (CInterface)
Native.loadLibrary(cname, CInterface.class);
start = System.currentTimeMillis();
for (int i=0;i < COUNT;i++) {
presult = clib.memset(null, 0, 0);
}
delta = System.currentTimeMillis() - start;
System.out.println("memset (JNA interface): " + delta + "ms");
f = NativeLibrary.getInstance(cname).getFunction("memset");
args = new Object[] { null, new Integer(0), new Integer(0)};
start = System.currentTimeMillis();
for (int i=0;i < COUNT;i++) {
presult = f.invokePointer(args);
}
delta = System.currentTimeMillis() - start;
System.out.println("memset (JNA function): " + delta + "ms");
start = System.currentTimeMillis();
for (int i=0;i < COUNT;i++) {
presult = CLibrary.memset((Pointer)null, 0, new CLibrary.size_t(0));
}
delta = System.currentTimeMillis() - start;
System.out.println("memset (JNA direct Pointer/size_t): " + delta + "ms");
start = System.currentTimeMillis();
if (Native.POINTER_SIZE == 4) {
for (int i=0;i < COUNT;i++) {
presult = CLibrary.memset((Pointer)null, 0, 0);
}
}
else {
for (int i=0;i < COUNT;i++) {
presult = CLibrary.memset((Pointer)null, 0, 0L);
}
}
delta = System.currentTimeMillis() - start;
System.out.println("memset (JNA direct Pointer/primitive): " + delta + "ms");
int iresult;
long jresult;
start = System.currentTimeMillis();
if (Native.POINTER_SIZE == 4) {
for (int i=0;i < COUNT;i++) {
iresult = CLibrary.memset(0, 0, 0);
}
}
else {
for (int i=0;i < COUNT;i++) {
jresult = CLibrary.memset(0L, 0, 0L);
}
}
delta = System.currentTimeMillis() - start;
System.out.println("memset (JNA direct primitives): " + delta + "ms");
if (Native.POINTER_SIZE == 4) {
b.putInt(0, (int)Structure.FFIType.get(Pointer.class).peer);
b.putInt(4, (int)Structure.FFIType.get(int.class).peer);
b.putInt(8, (int)Structure.FFIType.get(int.class).peer);
cif = Native.ffi_prep_cif(0, 3, Structure.FFIType.get(Pointer.class).peer, types);
resp = pb.peer + 12;
argv = pb.peer + 16;
start = System.currentTimeMillis();
for (int i=0;i < COUNT;i++) {
b.putInt(16, (int)pb.peer + 28);
b.putInt(20, (int)pb.peer + 32);
b.putInt(24, (int)pb.peer + 36);
b.putInt(28, 0);
b.putInt(32, 0);
b.putInt(36, 0);
Native.ffi_call(cif, f.peer, resp, argv);
b.getInt(12);
}
delta = System.currentTimeMillis() - start;
}
else {
b.putLong(0, Structure.FFIType.get(Pointer.class).peer);
b.putLong(8, Structure.FFIType.get(int.class).peer);
b.putLong(16, Structure.FFIType.get(long.class).peer);
cif = Native.ffi_prep_cif(0, 3, Structure.FFIType.get(Pointer.class).peer, types);
resp = pb.peer + 24;
argv = pb.peer + 32;
start = System.currentTimeMillis();
for (int i=0;i < COUNT;i++) {
b.putLong(32, pb.peer + 56);
b.putLong(40, pb.peer + 64);
b.putLong(48, pb.peer + 72);
b.putLong(56, 0);
b.putInt(64, 0);
b.putLong(72, 0);
Native.ffi_call(cif, f.peer, resp, argv);
b.getLong(24);
}
delta = System.currentTimeMillis() - start;
}
System.out.println("memset (JNI ffi): " + delta + "ms");
start = System.currentTimeMillis();
for (int i=0;i < COUNT;i++) {
Pointer._setMemory(0L, 0L, (byte)0);
}
delta = System.currentTimeMillis() - start;
System.out.println("memset (JNI): " + delta + "ms");
///////////////////////////////////////////
// strlen
String str = "performance test";
start = System.currentTimeMillis();
for (int i=0;i < COUNT;i++) {
iresult = clib.strlen(str);
}
delta = System.currentTimeMillis() - start;
System.out.println("strlen (JNA interface): " + delta + "ms");
f = NativeLibrary.getInstance(cname).getFunction("strlen");
args = new Object[] { str };
start = System.currentTimeMillis();
for (int i=0;i < COUNT;i++) {
iresult = f.invokeInt(args);
}
delta = System.currentTimeMillis() - start;
System.out.println("strlen (JNA function): " + delta + "ms");
start = System.currentTimeMillis();
for (int i=0;i < COUNT;i++) {
iresult = CLibrary.strlen(str);
}
delta = System.currentTimeMillis() - start;
System.out.println("strlen (JNA direct - String): " + delta + "ms");
start = System.currentTimeMillis();
for (int i=0;i < COUNT;i++) {
iresult = CLibrary.strlen(new NativeString(str).getPointer());
}
delta = System.currentTimeMillis() - start;
System.out.println("strlen (JNA direct - Pointer): " + delta + "ms");
start = System.currentTimeMillis();
for (int i=0;i < COUNT;i++) {
iresult = CLibrary.strlen(Native.toByteArray(str));
}
delta = System.currentTimeMillis() - start;
System.out.println("strlen (JNA direct - byte[]): " + delta + "ms");
start = System.currentTimeMillis();
for (int i=0;i < COUNT;i++) {
byte[] bytes = str.getBytes();
b.position(0);
b.put(bytes);
b.put((byte)0);
iresult = CLibrary.strlen(b);
}
delta = System.currentTimeMillis() - start;
System.out.println("strlen (JNA direct - Buffer): " + delta + "ms");
if (Native.POINTER_SIZE == 4) {
b.putInt(0, (int)Structure.FFIType.get(Pointer.class).peer);
cif = Native.ffi_prep_cif(0, 1, Structure.FFIType.get(int.class).peer, types);
resp = pb.peer + 4;
argv = pb.peer + 8;
start = System.currentTimeMillis();
for (int i=0;i < COUNT;i++) {
b.putInt(8, (int)pb.peer + 12);
b.putInt(12, (int)pb.peer + 16);
b.position(16);
// This operation is very expensive!
b.put(str.getBytes());
b.put((byte)0);
Native.ffi_call(cif, f.peer, resp, argv);
iresult = b.getInt(4);
}
delta = System.currentTimeMillis() - start;
}
else {
b.putLong(0, Structure.FFIType.get(Pointer.class).peer);
cif = Native.ffi_prep_cif(0, 1, Structure.FFIType.get(long.class).peer, types);
resp = pb.peer + 8;
argv = pb.peer + 16;
start = System.currentTimeMillis();
for (int i=0;i < COUNT;i++) {
b.putLong(16, pb.peer + 24);
b.putLong(24, pb.peer + 32);
b.position(32);
// This operation is very expensive!
b.put(str.getBytes());
b.put((byte)0);
Native.ffi_call(cif, f.peer, resp, argv);
jresult = b.getLong(8);
}
delta = System.currentTimeMillis() - start;
}
System.out.println("strlen (JNI ffi): " + delta + "ms");
///////////////////////////////////////////
// Direct buffer vs. Pointer methods
byte[] bulk = new byte[SIZE];
start = System.currentTimeMillis();
for (int i=0;i < COUNT;i++) {
b.putInt(0, 0);
}
delta = System.currentTimeMillis() - start;
System.out.println("direct Buffer write: " + delta + "ms");
start = System.currentTimeMillis();
for (int i=0;i < COUNT;i++) {
b.position(0);
b.put(bulk);
}
delta = System.currentTimeMillis() - start;
System.out.println("direct Buffer write (bulk): " + delta + "ms");
Pointer p = new Memory(SIZE);
start = System.currentTimeMillis();
for (int i=0;i < COUNT;i++) {
p.setInt(0, 0);
}
delta = System.currentTimeMillis() - start;
System.out.println("Memory write: " + delta + "ms");
start = System.currentTimeMillis();
for (int i=0;i < COUNT;i++) {
p.write(0, bulk, 0, bulk.length);
}
delta = System.currentTimeMillis() - start;
System.out.println("Memory write (bulk): " + delta + "ms");
///////////////////////////////////////////
// Callbacks
TestInterface tlib = (TestInterface)Native.loadLibrary("testlib", TestInterface.class);
start = System.currentTimeMillis();
TestInterface.Int32Callback cb = new TestInterface.Int32Callback() {
public int invoke(int arg1, int arg2) {
return arg1 + arg2;
}
};
tlib.callInt32CallbackRepeatedly(cb, 1, 2, COUNT);
delta = System.currentTimeMillis() - start;
System.out.println("callback (JNA interface): " + delta + "ms");
tlib = new TestLibrary();
start = System.currentTimeMillis();
tlib.callInt32CallbackRepeatedly(cb, 1, 2, COUNT);
delta = System.currentTimeMillis() - start;
System.out.println("callback (JNA direct): " + delta + "ms");
start = System.currentTimeMillis();
TestInterface.NativeLongCallback nlcb = new TestInterface.NativeLongCallback() {
public NativeLong invoke(NativeLong arg1, NativeLong arg2) {
return new NativeLong(arg1.longValue() + arg2.longValue());
}
};
tlib.callLongCallbackRepeatedly(nlcb, new NativeLong(1), new NativeLong(2), COUNT);
delta = System.currentTimeMillis() - start;
System.out.println("callback w/NativeMapped (JNA interface): " + delta + "ms");
tlib = new TestLibrary();
start = System.currentTimeMillis();
tlib.callLongCallbackRepeatedly(nlcb, new NativeLong(1), new NativeLong(2), COUNT);
delta = System.currentTimeMillis() - start;
System.out.println("callback w/NativeMapped (JNA direct): " + delta + "ms");
}
}
@@ -0,0 +1,163 @@
/* Copyright (c) 2009 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.
* <p/>
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package com.sun.jna;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.HashMap;
import java.util.Map;
import junit.framework.TestCase;
public class DirectTypeMapperTest extends TestCase {
public static class DirectTestLibraryBoolean {
final static int MAGIC = 0xABEDCF23;
public native int returnInt32Argument(boolean b);
static {
Map options = new HashMap();
DefaultTypeMapper mapper = new DefaultTypeMapper();
mapper.addToNativeConverter(Boolean.class, new ToNativeConverter() {
public Object toNative(Object arg, ToNativeContext ctx) {
return new Integer(Boolean.TRUE.equals(arg) ? MAGIC : 0);
}
public Class nativeType() {
return Integer.class;
}
});
options.put(Library.OPTION_TYPE_MAPPER, mapper);
Native.register(NativeLibrary.getInstance("testlib", options));
}
}
public static class DirectTestLibraryString {
public native int returnInt32Argument(String s);
static {
DefaultTypeMapper mapper = new DefaultTypeMapper();
mapper.addToNativeConverter(String.class, new ToNativeConverter() {
public Object toNative(Object arg, ToNativeContext ctx) {
return Integer.valueOf((String) arg, 16);
}
public Class nativeType() {
return Integer.class;
}
});
Map options = new HashMap();
options.put(Library.OPTION_TYPE_MAPPER, mapper);
Native.register(NativeLibrary.getInstance("testlib", options));
}
}
public static class DirectTestLibraryCharSequence {
public native int returnInt32Argument(String n);
static {
DefaultTypeMapper mapper = new DefaultTypeMapper();
mapper.addToNativeConverter(CharSequence.class, new ToNativeConverter() {
public Object toNative(Object arg, ToNativeContext ctx) {
return Integer.valueOf(((CharSequence)arg).toString(), 16);
}
public Class nativeType() {
return Integer.class;
}
});
Map options = new HashMap();
options.put(Library.OPTION_TYPE_MAPPER, mapper);
Native.register(NativeLibrary.getInstance("testlib", options));
}
}
public static class DirectTestLibraryNumber {
public native int returnInt32Argument(Number n);
static {
DefaultTypeMapper mapper = new DefaultTypeMapper();
mapper.addToNativeConverter(Number.class, new ToNativeConverter() {
public Object toNative(Object arg, ToNativeContext ctx) {
return new Integer(((Number)arg).intValue());
}
public Class nativeType() {
return Integer.class;
}
});
Map options = new HashMap();
options.put(Library.OPTION_TYPE_MAPPER, mapper);
Native.register(NativeLibrary.getInstance("testlib", options));
}
}
public void testBooleanToIntArgumentConversion() {
DirectTestLibraryBoolean lib = new DirectTestLibraryBoolean();
assertEquals("Failed to convert Boolean argument to Int",
lib.MAGIC,
lib.returnInt32Argument(true));
}
public void testStringToIntArgumentConversion() {
final int MAGIC = 0x7BEDCF23;
DirectTestLibraryString lib = new DirectTestLibraryString();
assertEquals("Failed to convert String argument to Int", MAGIC,
lib.returnInt32Argument(Integer.toHexString(MAGIC)));
}
public void testCharSequenceToIntArgumentConversion() {
final int MAGIC = 0x7BEDCF23;
DirectTestLibraryCharSequence lib = new DirectTestLibraryCharSequence();
assertEquals("Failed to convert String argument to Int", MAGIC,
lib.returnInt32Argument(Integer.toHexString(MAGIC)));
}
public void testNumberToIntArgumentConversion() {
final int MAGIC = 0x7BEDCF23;
DirectTestLibraryNumber lib = new DirectTestLibraryNumber();
assertEquals("Failed to convert Double argument to Int", MAGIC,
lib.returnInt32Argument(new Double(MAGIC)));
}
public static class DirectBooleanTestLibrary {
public native boolean returnInt32Argument(boolean b);
static {
final int MAGIC = 0xABEDCF23;
Map options = new HashMap();
DefaultTypeMapper mapper = new DefaultTypeMapper();
// Use opposite sense of default int<-->boolean conversions
mapper.addToNativeConverter(Boolean.class, new ToNativeConverter() {
public Object toNative(Object value, ToNativeContext ctx) {
return new Integer(Boolean.TRUE.equals(value) ? 0 : MAGIC);
}
public Class nativeType() {
return Integer.class;
}
});
mapper.addFromNativeConverter(Boolean.class, new FromNativeConverter() {
public Object fromNative(Object value, FromNativeContext context) {
return Boolean.valueOf(((Integer) value).intValue() != MAGIC);
}
public Class nativeType() {
return Integer.class;
}
});
options.put(Library.OPTION_TYPE_MAPPER, mapper);
Native.register(NativeLibrary.getInstance("testlib", options));
}
}
public void testIntegerToBooleanResultConversion() throws Exception {
DirectBooleanTestLibrary lib = new DirectBooleanTestLibrary();
// argument "true" converts to zero; result zero converts to "true"
assertTrue("Failed to convert integer return to boolean TRUE",
lib.returnInt32Argument(true));
// argument "true" converts to MAGIC; result MAGIC converts to "false"
assertFalse("Failed to convert integer return to boolean FALSE",
lib.returnInt32Argument(false));
}
public static void main(String[] args) {
junit.textui.TestRunner.run(DirectTypeMapperTest.class);
}
}
+105 -8
Ver Arquivo
@@ -1,4 +1,4 @@
/* Copyright (c) 2007 Timothy Wall, All Rights Reserved
/* Copyright (c) 2007-2009 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,41 +12,138 @@
*/
package com.sun.jna;
import java.lang.ref.WeakReference;
import java.io.File;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import junit.framework.TestCase;
public class JNAUnloadTest extends TestCase {
private static final String BUILDDIR =
System.getProperty("jna.builddir", "build"
+ (Native.POINTER_SIZE == 8 ? "-d64" : ""));
+ (Platform.is64Bit() ? "-d64" : ""));
private static class TestLoader extends URLClassLoader {
public TestLoader() throws MalformedURLException {
public TestLoader(boolean fromJar) throws MalformedURLException {
super(new URL[] {
new File(BUILDDIR + "/classes").toURI().toURL(),
new File(BUILDDIR + (fromJar ? "/jna.jar" : "/classes")).toURI().toURL(),
}, null);
}
}
// TODO: test auto-dispose of callback memory
// Fails under clover
public void testUnloadFromJar() throws Exception {
File jar = new File(BUILDDIR + "/jna.jar");
assertTrue("Expected JNA jar file at " + jar + " is missing", jar.exists());
public void testUnload() throws Exception {
ClassLoader loader = new TestLoader();
ClassLoader loader = new TestLoader(true);
Class cls = Class.forName("com.sun.jna.Native", true, loader);
assertEquals("Wrong class loader", loader, cls.getClassLoader());
Field field = cls.getDeclaredField("nativeLibraryPath");
field.setAccessible(true);
String path = (String)field.get(null);
assertTrue("Native library not unpacked from jar: " + path,
path.startsWith(System.getProperty("java.io.tmpdir")));
WeakReference ref = new WeakReference(cls);
WeakReference clref = new WeakReference(loader);
loader = null;
cls = null;
field = null;
System.gc();
for (int i=0;i < 100 && (ref.get() != null || clref.get() != null);i++) {
Thread.sleep(10);
System.gc();
}
assertNull("Class not GC'd: " + ref.get(), ref.get());
assertNull("ClassLoader not GC'd: " + clref.get(), clref.get());
File f = new File(path);
for (int i=0;i < 100 && f.exists();i++) {
Thread.sleep(10);
System.gc();
}
// NOTE: Temporary file removal on Windows only works on a Sun VM
try {
if (Platform.isWindows()) {
ClassLoader.class.getDeclaredField("nativeLibraries");
}
if (f.exists() && !f.delete()) {
assertFalse("Temporary native library still locked: " + path,
f.exists());
}
}
catch(Exception e) {
// Skip on non-supported VMs
}
try {
loader = new TestLoader(true);
cls = Class.forName("com.sun.jna.Native", true, loader);
}
catch(Throwable t) {
fail("Native library not unloaded: " + t.getMessage());
}
finally {
loader = null;
cls = null;
System.gc();
}
}
// Fails under clover
public void testUnload() throws Exception {
ClassLoader loader = new TestLoader(false);
Class cls = Class.forName("com.sun.jna.Native", true, loader);
assertEquals("Wrong class loader", loader, cls.getClassLoader());
Field field = cls.getDeclaredField("nativeLibraryPath");
field.setAccessible(true);
String path = (String)field.get(null);
assertNotNull("Native library not found", path);
WeakReference ref = new WeakReference(cls);
WeakReference clref = new WeakReference(loader);
loader = null;
cls = null;
field = null;
System.gc();
for (int i=0;i < 100 && (ref.get() != null || clref.get() != null);i++) {
Thread.sleep(10);
System.gc();
}
assertNull("Class not GC'd: " + ref.get(), ref.get());
assertNull("ClassLoader not GC'd: " + clref.get(), clref.get());
Throwable throwable = null;
// NOTE: IBM J9 needs some extra time to unload the native library,
// so try a few times before failing
for (int i=0;i < 100;i++) {
System.gc();
Thread.sleep(10);
try {
loader = new TestLoader(false);
cls = Class.forName("com.sun.jna.Native", true, loader);
break;
}
catch(Throwable t) {
loader = null;
throwable = t;
}
}
try {
if (loader == null)
fail("Native library not unloaded: " + throwable.getMessage());
}
finally {
loader = null;
cls = null;
System.gc();
}
}
public static void main(String[] args) {
+82
Ver Arquivo
@@ -0,0 +1,82 @@
/* Copyright (c) 2009 Timothy Wall, All Rights Reserved
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package com.sun.jna;
import java.util.Map;
import java.util.HashMap;
import java.lang.reflect.Method;
import junit.framework.TestCase;
public class LastErrorTest extends TestCase {
private static final Map OPTIONS = new HashMap() {{
put(Library.OPTION_FUNCTION_MAPPER, new FunctionMapper() {
public String getFunctionName(NativeLibrary library, Method m) {
if (m.getName().equals("noThrowLastError")
|| m.getName().equals("throwLastError")) {
return "setLastError";
}
return m.getName();
}
});
}};
public interface TestLibrary extends Library {
void noThrowLastError(int code);
void throwLastError(int code) throws LastErrorException;
}
public static class DirectTestLibrary implements TestLibrary {
public native void noThrowLastError(int code);
public native void throwLastError(int code) throws LastErrorException;
static {
Native.register(NativeLibrary.getInstance("testlib", OPTIONS));
}
}
public void testThrowLastError() {
Map options = new HashMap();
TestLibrary lib = (TestLibrary)Native.loadLibrary("testlib", TestLibrary.class, OPTIONS);
final int ERROR = -1;
lib.noThrowLastError(ERROR);
assertEquals("Last error not preserved", ERROR, Native.getLastError());
try {
lib.throwLastError(ERROR);
fail("Method should throw LastErrorException");
}
catch(LastErrorException e) {
assertEquals("Exception should contain error code", ERROR, e.errorCode);
}
}
public void testThrowLastErrorDirect() {
TestLibrary lib = new DirectTestLibrary();
final int ERROR = -1;
lib.noThrowLastError(ERROR);
assertEquals("Last error not preserved", ERROR, Native.getLastError());
try {
lib.throwLastError(ERROR);
fail("Method should throw LastErrorException");
}
catch(LastErrorException e) {
assertEquals("Exception should contain error code", ERROR, e.errorCode);
}
}
public static void main(String[] args) {
junit.textui.TestRunner.run(LastErrorTest.class);
}
}
+9 -4
Ver Arquivo
@@ -1,4 +1,4 @@
/* Copyright (c) 2007 Timothy Wall, All Rights Reserved
/* Copyright (c) 2007-2009 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,8 +13,8 @@
package com.sun.jna;
import java.awt.Frame;
import java.awt.Toolkit;
import java.awt.GraphicsEnvironment;
import java.awt.Toolkit;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
@@ -26,7 +26,7 @@ public class LibraryLoadTest extends TestCase {
private static final String BUILDDIR =
System.getProperty("jna.builddir", "build"
+ (Native.POINTER_SIZE == 8 ? "-d64" : ""));
+ (Platform.is64Bit() ? "-d64" : ""));
public void testLoadJNALibrary() {
assertTrue("Point size should never be zero", Pointer.SIZE > 0);
@@ -54,6 +54,8 @@ public class LibraryLoadTest extends TestCase {
}
public void testLoadAWTAfterJNA() {
if (GraphicsEnvironment.isHeadless()) return;
if (Pointer.SIZE > 0) {
Toolkit.getDefaultToolkit();
}
@@ -89,6 +91,8 @@ public class LibraryLoadTest extends TestCase {
String tmp = System.getProperty("java.io.tmpdir");
String libName = System.mapLibraryName("jnidispatch");
File src = new File(BUILDDIR + "/native", libName);
assertTrue("Expected JNA native library at " + src + " is missing", src.exists());
String newLibName = UNICODE;
if (libName.startsWith("lib"))
newLibName = "lib" + newLibName;
@@ -105,7 +109,8 @@ public class LibraryLoadTest extends TestCase {
dst.deleteOnExit();
copy(src, dst);
NativeLibrary.addSearchPath(UNICODE, tmp);
NativeLibrary.getInstance(UNICODE);
NativeLibrary nl = NativeLibrary.getInstance(UNICODE);
nl.dispose();
}
public void testHandleObjectMethods() {
+61 -6
Ver Arquivo
@@ -13,6 +13,9 @@
package com.sun.jna;
import java.lang.ref.WeakReference;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import junit.framework.TestCase;
public class MemoryTest extends TestCase {
@@ -31,9 +34,10 @@ public class MemoryTest extends TestCase {
System.gc();
long start = System.currentTimeMillis();
assertFalse("Memory prematurely GC'd", flag[0]);
// This check fails on IBM's J9, on which the weak ref
// is cleared but the object not yet GC'd
//assertNotNull("Memory prematurely GC'd", ref.get());
assertNotNull("Base memory GC'd while shared memory extant", ref.get());
// Avoid having IBM J9 prematurely nullify "shared"
shared.setInt(0, 0);
shared = null;
System.gc();
while (ref.get() != null) {
@@ -64,17 +68,25 @@ public class MemoryTest extends TestCase {
}
public void testAlignment() {
final int SIZE = 128;
final int SIZE = 1<<16;
Memory base = new Memory(SIZE);
for (int align=1;align < 8;align *= 2) {
for (int align=1;align < SIZE;align *= 2) {
Memory unaligned = base;
long mask = ~((long)align - 1);
if ((base.peer & mask) == base.peer)
unaligned = (Memory)base.share(1, SIZE-1);
Pointer aligned = unaligned.align(align);
assertEquals("Memory not aligned",
assertEquals("Memory not aligned (" + align + ")",
aligned.peer & mask, aligned.peer);
assertSame("Alignment request on aligned memory should no-op",
aligned, ((Memory)aligned).align(align));
}
}
public void testNegativeAlignment() {
final int SIZE = 128;
Memory base = new Memory(SIZE);
try {
base.align(-1);
fail("Negative alignments not allowed");
@@ -82,6 +94,49 @@ public class MemoryTest extends TestCase {
catch(IllegalArgumentException e) { }
}
public void testInvalidAlignment() {
final int SIZE = 128;
Memory base = new Memory(SIZE);
int[] alignments = { 0, 3, 5, 9, 13 };
for (int i=0;i < alignments.length;i++) {
try {
base.align(alignments[i]);
fail("Power-of-two alignments required");
}
catch(IllegalArgumentException e) { }
}
}
public void testAvoidGCWithExtantBuffer() throws Exception {
Memory m = new Memory(1024);
ByteBuffer b = m.getByteBuffer(0, m.getSize());
WeakReference ref = new WeakReference(m);
WeakReference bref = new WeakReference(b);
m = null;
System.gc();
Memory.purge();
for (int i=0;i < 100 && ref.get() != null;i++) {
Thread.sleep(10);
System.gc();
Memory.purge();
}
assertNotNull("Memory GC'd while NIO Buffer still extant", ref.get());
// Avoid IBM J9 optimization resulting in premature GC of buffer
b.put((byte)0);
b = null;
System.gc();
Memory.purge();
for (int i=0;i < 100 && (bref.get() != null || ref.get() != null);i++) {
Thread.sleep(10);
System.gc();
Memory.purge();
}
assertNull("Buffer not GC'd\n", bref.get());
assertNull("Memory not GC'd after buffer GC'd\n", ref.get());
}
public static void main(String[] args) {
junit.textui.TestRunner.run(MemoryTest.class);
}
@@ -182,6 +182,12 @@ public class NativeLibraryTest extends TestCase {
}
}
public void testGetProcess() {
NativeLibrary process = NativeLibrary.getProcess();
// Access a common C library function
process.getFunction("printf");
}
public static void main(String[] args) {
junit.textui.TestRunner.run(NativeLibraryTest.class);
}
+97 -2
Ver Arquivo
@@ -194,8 +194,103 @@ public class NativeTest extends TestCase {
Native.getStructureAlignment(TestInterfaceWithAlignment.class));
}
// TODO extract (alignment|typemapper)
// from (variable|options)
public void testCharArrayToString() {
char[] buf = { 'a', 'b', 'c', '\0', 'd', 'e' };
assertEquals("Wrong String generated", "abc", Native.toString(buf));
}
public void testByteArrayToString() {
byte[] buf = { 'a', 'b', 'c', '\0', 'd', 'e' };
assertEquals("Wrong String generated", "abc", Native.toString(buf));
}
public void testToByteArray() {
final String VALUE = getName();
byte[] buf = Native.toByteArray(VALUE);
assertEquals("Wrong byte array length", VALUE.length()+1, buf.length);
assertEquals("Missing NUL terminator", (byte)0, buf[buf.length-1]);
assertEquals("Wrong byte array contents", VALUE, new String(buf, 0, buf.length-1));
}
public void testToCharArray() {
final String VALUE = getName();
char[] buf = Native.toCharArray(VALUE);
assertEquals("Wrong char array length", VALUE.length()+1, buf.length);
assertEquals("Missing NUL terminator", (char)0, buf[buf.length-1]);
assertEquals("Wrong char array contents: " + new String(buf), VALUE, new String(buf, 0, buf.length-1));
}
public void testOSPrefix() {
assertEquals("Wrong resource path", "/com/sun/jna/win32-x86",
Native.getNativeLibraryResourcePath(Platform.WINDOWS,
"x86", "Windows"));
assertEquals("Wrong resource path Windows/i386", "/com/sun/jna/win32-x86",
Native.getNativeLibraryResourcePath(Platform.WINDOWS,
"i386", "Windows"));
assertEquals("Wrong resource path Mac/x86", "/com/sun/jna/darwin",
Native.getNativeLibraryResourcePath(Platform.MAC,
"x86", "Darwin"));
assertEquals("Wrong resource path Mac/x86_64", "/com/sun/jna/darwin",
Native.getNativeLibraryResourcePath(Platform.MAC,
"x86_64", "Mac"));
assertEquals("Wrong resource path Solaris/sparc", "/com/sun/jna/sunos-sparc",
Native.getNativeLibraryResourcePath(Platform.SOLARIS,
"sparc", "Solaris"));
assertEquals("Wrong resource path SunOS/sparcv9", "/com/sun/jna/sunos-sparcv9",
Native.getNativeLibraryResourcePath(Platform.SOLARIS,
"sparcv9", "SunOS"));
assertEquals("Wrong resource path Linux/i386", "/com/sun/jna/linux-i386",
Native.getNativeLibraryResourcePath(Platform.LINUX,
"i386", "Linux/Gnu"));
assertEquals("Wrong resource path Linux/x86", "/com/sun/jna/linux-i386",
Native.getNativeLibraryResourcePath(Platform.LINUX,
"x86", "Linux"));
assertEquals("Wrong resource path OpenBSD/x86", "/com/sun/jna/openbsd-i386",
Native.getNativeLibraryResourcePath(Platform.OPENBSD,
"x86", "OpenBSD"));
assertEquals("Wrong resource path FreeBSD/x86", "/com/sun/jna/freebsd-i386",
Native.getNativeLibraryResourcePath(Platform.FREEBSD,
"x86", "FreeBSD"));
assertEquals("Wrong resource path other/other", "/com/sun/jna/name-ppc",
Native.getNativeLibraryResourcePath(Platform.UNSPECIFIED,
"PowerPC", "Name Of System"));
}
public static class DirectMapping {
public static class DirectStructure extends Structure {
public int field;
}
public static interface DirectCallback extends Callback {
void invoke();
}
public DirectMapping(Map options) {
Native.register(getClass(), NativeLibrary.getInstance("testlib", options));
}
}
public void testGetTypeMapperForDirectMapping() {
final TypeMapper mapper = new DefaultTypeMapper();
Map options = new HashMap();
options.put(Library.OPTION_TYPE_MAPPER, mapper);
DirectMapping lib = new DirectMapping(options);
assertEquals("Wrong type mapper for direct mapping",
mapper, Native.getTypeMapper(DirectMapping.class));
assertEquals("Wrong type mapper for direct mapping nested structure",
mapper, Native.getTypeMapper(DirectMapping.DirectStructure.class));
assertEquals("Wrong type mapper for direct mapping nested callback",
mapper, Native.getTypeMapper(DirectMapping.DirectCallback.class));
}
private static class TestCallback implements Callback {
public static final TypeMapper TYPE_MAPPER = new DefaultTypeMapper();
public void callback() { }
}
public void testGetTypeMapperFromCallbackInterface() throws Exception {
assertEquals("Wrong type mapper for callback class",
TestCallback.TYPE_MAPPER,
Native.getTypeMapper(TestCallback.class));
}
public static void main(String[] args) {
junit.textui.TestRunner.run(NativeTest.class);
+27
Ver Arquivo
@@ -227,6 +227,33 @@ public class PointerTest extends TestCase {
p, Native.getDirectBufferPointer(b.asFloatBuffer()));
assertEquals("DoubleBuffer Pointer does not match",
p, Native.getDirectBufferPointer(b.asDoubleBuffer()));
assertEquals("Wrong direct buffer address",
p, Native.getDirectBufferPointer(b));
}
public static class TestPointerType extends PointerType {
public TestPointerType() { }
public TestPointerType(Pointer p) { super(p); }
}
public void testSetNativeMapped() {
Pointer p = new Memory(Pointer.SIZE);
TestPointerType tp = new TestPointerType(p);
p.setValue(0, tp, tp.getClass());
assertEquals("Wrong value written", p, p.getPointer(0));
}
public void testGetNativeMapped() {
Pointer p = new Memory(Pointer.SIZE);
p.setPointer(0, null);
Object o = p.getValue(0, TestPointerType.class, null);
assertNull("Wrong empty value: " + o, o);
p.setPointer(0, p);
TestPointerType tp = new TestPointerType(p);
assertEquals("Wrong value", tp, p.getValue(0, TestPointerType.class, null));
}
public static void main(String[] args) {
-194
Ver Arquivo
@@ -1,194 +0,0 @@
/* Copyright (c) 2009 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.
* <p/>
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package com.sun.jna;
import junit.framework.*;
import com.sun.jna.*;
import java.lang.ref.*;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
public class RawTest extends TestCase {
private static final String BUILDDIR =
System.getProperty("jna.builddir",
"build" + (Platform.is64Bit() ? "-d64" : ""));
private static class JNI {
static {
String path = BUILDDIR + "/native/" + System.mapLibraryName("testlib");;
if (!new File(path).isAbsolute()) {
path = System.getProperty("user.dir") + "/" + path;
}
if (path.endsWith(".jnilib")) {
path = path.replace(".jnilib", ".dylib");
}
System.load(path);
}
private static native double cos(double x);
}
public static void main(java.lang.String[] argList) {
junit.textui.TestRunner.run(RawTest.class);
checkPerformance();
}
static class MathLibrary {
public static native double cos(double x);
static {
Native.register(Platform.isWindows()?"msvcrt":"m");
}
}
interface MathInterface extends Library {
double cos(double x);
}
static class CLibrary {
public static native Pointer memset(Pointer p, int v, int len);
static {
Native.register(Platform.isWindows()?"msvcrt":"c");
}
}
static interface CInterface extends Library {
Pointer memset(Pointer p, int v, int len);
}
private static class TestLoader extends URLClassLoader {
public TestLoader() throws MalformedURLException {
super(new URL[] {
new File(BUILDDIR + "/classes").toURI().toURL(),
new File(BUILDDIR + "/test-classes").toURI().toURL(),
}, null);
}
}
public void testRegisterMethods() throws Exception {
// Use a dedicated class loader to ensure the class can be gc'd
String name = "com.sun.jna.RawTest$MathLibrary";
ClassLoader loader = new TestLoader();
Class cls = Class.forName(name, true, loader);
assertNotNull("Failed loading class", cls);
WeakReference ref = new WeakReference(cls);
loader = null;
cls = null;
System.gc();
for (int i=0;i < 100 && ref.get() != null;i++) {
try {
Thread.sleep(10); // Give the GC a chance to run
System.gc();
} finally {}
}
// TODO: need a real check for freed native memory
assertNull("Registered methods not GC'd: " + ref.get(), ref.get());
}
public void testInvokeMethod() {
assertEquals("Wrong value", Math.cos(0), MathLibrary.cos(0d));
}
public void testInvokeMethodWithPointer() {
assertNull("Returned pointer should be null",
CLibrary.memset(null, 0, 0));
}
// Requires java.library.path include testlib
public static void checkPerformance() {
System.out.println("Checking performance of different access methods");
String mname = Platform.isWindows()?"msvcrt":"m";
MathInterface mlib = (MathInterface)
Native.loadLibrary(mname, MathInterface.class);
Function f = NativeLibrary.getInstance(mname).getFunction("cos");
final int COUNT = 1000000;
Object[] args = { new Double(0) };
long start = System.currentTimeMillis();
for (int i=0;i < COUNT;i++) {
mlib.cos(0d);
}
long delta = System.currentTimeMillis() - start;
System.out.println("cos (JNA interface): " + delta + "ms");
start = System.currentTimeMillis();
for (int i=0;i < COUNT;i++) {
f.invokeDouble(args);
}
delta = System.currentTimeMillis() - start;
System.out.println("cos (JNA Function): " + delta + "ms");
start = System.currentTimeMillis();
for (int i=0;i < COUNT;i++) {
MathLibrary.cos(0d);
}
delta = System.currentTimeMillis() - start;
System.out.println("cos (JNA raw): " + delta + "ms");
start = System.currentTimeMillis();
for (int i=0;i < COUNT;i++) {
JNI.cos(0d);
}
delta = System.currentTimeMillis() - start;
System.out.println("cos (JNI): " + delta + "ms");
start = System.currentTimeMillis();
for (int i=0;i < COUNT;i++) {
Math.cos(0d);
}
delta = System.currentTimeMillis() - start;
System.out.println("cos (pure java): " + delta + "ms");
// memset
String cname = Platform.isWindows()?"msvcrt":"c";
CInterface clib = (CInterface)
Native.loadLibrary(cname, CInterface.class);
start = System.currentTimeMillis();
for (int i=0;i < COUNT;i++) {
clib.memset(null, 0, 0);
}
delta = System.currentTimeMillis() - start;
System.out.println("memset (JNA interface): " + delta + "ms");
f = NativeLibrary.getInstance(cname).getFunction("memset");
args = new Object[] { null, new Integer(0), new Integer(0)};
start = System.currentTimeMillis();
for (int i=0;i < COUNT;i++) {
f.invokePointer(args);
}
delta = System.currentTimeMillis() - start;
System.out.println("memset (JNA Function): " + delta + "ms");
f = NativeLibrary.getInstance(cname).getFunction("memset");
start = System.currentTimeMillis();
for (int i=0;i < COUNT;i++) {
CLibrary.memset(null, 0, 0);
}
delta = System.currentTimeMillis() - start;
System.out.println("memset (JNA raw): " + delta + "ms");
start = System.currentTimeMillis();
for (int i=0;i < COUNT;i++) {
Pointer._setMemory(0L, 0L, (byte)0);
}
delta = System.currentTimeMillis() - start;
System.out.println("memset (JNI): " + delta + "ms");
}
}
+13 -7
Ver Arquivo
@@ -13,6 +13,7 @@
package com.sun.jna;
import java.util.HashMap;
import java.util.Map;
import junit.framework.TestCase;
@@ -97,9 +98,10 @@ public class ReturnTypesTest extends TestCase {
}
public void testReturnObject() throws Exception {
lib = (TestLibrary)Native.loadLibrary("testlib", TestLibrary.class, new HashMap() { {
Map options = new HashMap() { {
put(Library.OPTION_ALLOW_OBJECTS, Boolean.TRUE);
}});
}};
lib = (TestLibrary)Native.loadLibrary("testlib", TestLibrary.class, options);
assertNull("null value not returned", lib.returnObjectArgument(null));
final Object VALUE = new Object() {
public String toString() {
@@ -110,7 +112,6 @@ public class ReturnTypesTest extends TestCase {
}
public void testReturnObjectUnsupported() throws Exception {
lib = (TestLibrary)Native.loadLibrary("testlib", TestLibrary.class);
try {
lib.returnObjectArgument(new TestLibrary.TestObject());
fail("Java Object return is not supported, should throw IllegalArgumentException");
@@ -181,9 +182,13 @@ public class ReturnTypesTest extends TestCase {
return o instanceof Custom && ((Custom)o).value == value;
}
}
public void testInvokeNativeMapped() {
NativeMappedLibrary lib = (NativeMappedLibrary)
protected NativeMappedLibrary loadNativeMappedLibrary() {
return (NativeMappedLibrary)
Native.loadLibrary("testlib", NativeMappedLibrary.class);
}
public void testInvokeNativeMapped() {
NativeMappedLibrary lib = loadNativeMappedLibrary();
final int MAGIC = 0x12345678;
final Custom EXPECTED = new Custom(MAGIC);
assertEquals("Argument not mapped", EXPECTED, lib.returnInt32Argument(MAGIC));
@@ -203,12 +208,13 @@ public class ReturnTypesTest extends TestCase {
static final String MAGIC = "magic";
public void testInvokeString() {
assertEquals("Expect string magic", MAGIC, lib.returnStringMagic());
assertEquals("Expect String magic", MAGIC, lib.returnStringMagic());
}
public void testInvokeWString() {
WString s = lib.returnWStringMagic();
assertEquals("Expect wstring magic", new WString(MAGIC), s);
assertEquals("Wrong length", MAGIC.length(), s.toString().length());
assertEquals("Expect WString magic", new WString(MAGIC), s);
}
public void testInvokeStructure() {

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