()
| 1441 | } |
| 1442 | |
| 1443 | public void testDLLCallback() throws Exception { |
| 1444 | if (!Platform.HAS_DLL_CALLBACKS) { |
| 1445 | return; |
| 1446 | } |
| 1447 | |
| 1448 | final boolean[] called = { false }; |
| 1449 | class TestCallback implements TestLibrary.VoidCallback, com.sun.jna.win32.DLLCallback { |
| 1450 | @Override |
| 1451 | public void callback() { |
| 1452 | called[0] = true; |
| 1453 | } |
| 1454 | } |
| 1455 | |
| 1456 | TestCallback cb = new TestCallback(); |
| 1457 | lib.callVoidCallback(cb); |
| 1458 | assertTrue("Callback not called", called[0]); |
| 1459 | |
| 1460 | // Check module information |
| 1461 | Pointer fp = CallbackReference.getFunctionPointer(cb); |
| 1462 | NativeLibrary kernel32 = NativeLibrary.getInstance("kernel32", W32APIOptions.DEFAULT_OPTIONS); |
| 1463 | Function f = kernel32.getFunction("GetModuleHandleExW"); |
| 1464 | final int GET_MODULE_HANDLE_FROM_ADDRESS = 0x4; |
| 1465 | PointerByReference pref = new PointerByReference(); |
| 1466 | int result = f.invokeInt(new Object[] { Integer.valueOf(GET_MODULE_HANDLE_FROM_ADDRESS), fp, pref }); |
| 1467 | assertTrue("GetModuleHandleEx(fptr) failed: " + Native.getLastError(), result != 0); |
| 1468 | |
| 1469 | f = kernel32.getFunction("GetModuleFileNameW"); |
| 1470 | char[] buf = new char[1024]; |
| 1471 | result = f.invokeInt(new Object[] { pref.getValue(), buf, buf.length }); |
| 1472 | assertTrue("GetModuleFileName(fptr) failed: " + Native.getLastError(), result != 0); |
| 1473 | |
| 1474 | f = kernel32.getFunction("GetModuleHandleW"); |
| 1475 | Pointer handle = f.invokePointer(new Object[] { Native.jnidispatchPath != null ? Native.jnidispatchPath : "jnidispatch" }); |
| 1476 | assertNotNull("GetModuleHandle(\"jnidispatch\") failed: " + Native.getLastError(), handle); |
| 1477 | assertEquals("Wrong module HANDLE for DLL function pointer", handle, pref.getValue()); |
| 1478 | |
| 1479 | // Check slot re-use |
| 1480 | Map<Callback, CallbackReference> refs = new WeakHashMap<>(callbackCache()); |
| 1481 | assertTrue("Callback not cached", refs.containsKey(cb)); |
| 1482 | CallbackReference ref = refs.get(cb); |
| 1483 | refs = callbackCache(); |
| 1484 | Pointer cbstruct = ref.cbstruct; |
| 1485 | Pointer first_fptr = cbstruct.getPointer(0); |
| 1486 | |
| 1487 | cb = null; |
| 1488 | System.gc(); |
| 1489 | for (int i = 0; i < 100 && (ref.get() != null || refs.containsValue(ref)); ++i) { |
| 1490 | Thread.sleep(10); // Give the GC a chance to run |
| 1491 | System.gc(); |
| 1492 | } |
| 1493 | assertNull("Callback not GC'd", ref.get()); |
| 1494 | assertFalse("Callback still in map", refs.containsValue(ref)); |
| 1495 | |
| 1496 | ref = null; |
| 1497 | System.gc(); |
| 1498 | for (int i = 0; i < 100 && (cbstruct.peer != 0 || refs.size() > 0); ++i) { |
| 1499 | // Flush weak hash map |
| 1500 | refs.size(); |
nothing calls this directly
no test coverage detected