I am trying to call OpenEvent of kernel32.dll using JNA and it fails with the error
java.lang.UnsatisfiedLinkError: Error looking up function 'OpenEvent': The specified procedure could not be found.
My stub declaration looks like this
public static native Pointer OpenEvent(int access, boolean inheritHandle, String name);
Can someone help me identify the issue here?
--
After making modification based on users feedback I dont get the error now; but OpenEvent method always returns null. This is the code that demonstrates the behavior
/**
* Hello world!
*
*/
import com.sun.jna.FromNativeContext;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.PointerType;
public class App
{
static {
Native.register("kernel32");
}
public static native HANDLE OpenEventW(int access, boolean inheritHandle,
String name);
public static native HANDLE CreateEventW(Pointer securityAttributes,
boolean manualReset, boolean initialState, String name);
public static native int GetLastError();
public static void main( String[] args )
{
HANDLE i = CreateEventW(null,false,false,"Global\\testEvent");
System.out.println("After create event:"+GetLastError());
HANDLE j = OpenEventW(100000, false, "Global\\testEvent");
System.out.println("After open event:"+GetLastError());
}
public static class HANDLE extends PointerType {
public Object fromNative(Object nativeValue, FromNativeContext context) {
Object o = super.fromNative(nativeValue, context);
if (INVALID_HANDLE_VALUE.equals(o))
return INVALID_HANDLE_VALUE;
return o;
}
}
static HANDLE INVALID_HANDLE_VALUE = new HANDLE() {
{ super.setPointer(Pointer.createConstant(-1)); }
public void setPointer(Pointer p) {
throw new UnsupportedOperationException("Immutable reference");
}
};
}
No idea what JNA is or how it works, but the problem is likely that the actual exported function is NOT "OpenEvent". It is "OpenEventA" or "OpenEventW" depending on if you want toe ASCII or Unicode variant. I assume Java strings are Unicode, so you most likely want "OpenEventW".
If you're mapping directly to the OpenEventW function without using the options provided by JNA, then you need to explicitly map the Java String to the native wchar_t* type by using WString where you currently use String. Otherwise you'll be passing invalid event IDs to the native function, which would likely cause the call to fail.
Related
I'm using a native library coded in C or C++, after a lot of multiple tests i successed to make it work, but i'm not sure if what i do correspond to the correct coding rules, and some parts are not clear for me.
So my question is : could you confirm and complete what i understood.
Thanks
the C prototype function is:
typedef void (*pfHook) (const char *pText);
and the function to set the callback function is:
short LogHookEx(void (*pfHook) (const char*));
So i created an interface for my native dll like that:
So if i understood "interface pfHookCallback" correspond to the C prototype function and "sCscSetApiLogHookEx" is a classic method from my native dll.
public interface Reader extends Library {
Reader INSTANCE = (Reader) Native.load((Platform.isWindows() ? "ReaderDll" : "c"),
Reader.class);
interface pfHookCallback extends Callback {
void invoke(String pText);
}
short LogHookEx(pfHookCallback pfHook);
}
The part that i understand less, is the part that i include in my "main":
public class Principal {
public static void main(String[] args) {
Reader.pfHookCallback pfHook = new Reader.pfHookCallback() {
public void invoke(String pText) {
System.out.println(pText);
}
};
res = Reader.INSTANCE.LogHookEx(pfHook);
To be more clear this callback function is used for tracing from an hardware device.
As described above, it's working, but it's not cleat for me.
And another question is , the goal of my code is to save the logs (so the pText string) into a file. Is there a best practice to do that, because if i create buffered writer, i don't know if it's good or not to do something like that:
public class Principal {
public static void main(String[] args) {
Reader.pfHookCallback pfHook = new Reader.pfHookCallback() {
public void invoke(String pText) {
bw.write(pText);
bw.close;
}
};
res = Reader.INSTANCE.LogHookEx(pfHook);
My question is i don't know if it's really good to open and close a file very quickly every time there is a log to be saved ?
What is the correct way to map a callback function that has void* as an argument?
I am working with native library (.dll) using JNA.
Library defines the following callback function:
typedef void (__stdcall *NotifyFunc)(int code, void *value);.
Here is how it is mapped in java:
public static NatLib.NotifyFunc notifyFunction = new MyNotifyFuncImpl();
public static void main(String[] args) {
NatLib.INSTANCE.SetCallbackFunc(notifyFunction);
}
public interface NatLib extends Library {
NatLib INSTANCE = Native.load("Nat.dll", NatLib.class);
//...
void SetCallbackFunc(NotifyFunc func);
interface NotifyFunc extends Callback {
void MyNotifyFunc(int code, Pointer value);
}
}
public static class MyNotifyFuncImpl implements NatLib.NotifyFunc {
#Override
public void MyNotifyFunc(int code, Pointer value) {
System.out.println("Notification: " + Integer.toHexString(code));
}
}
I set the callback function. However problems start at runtime. Callback function is executed only once, and then java application fails with non-zero exit value -1073740791. hs_err_pid* log file is not generated.
Is there something wrong with the mapping? I could not find examples for mappings with void* as parameter. Generally void* is mapped as Pointer, is it different when it is used as a parameter?
Do I need to free memory after each callback? I tried to do Native.free(Pointer.nativeValue(value)); inside callback, but this didn't solve the problem.
P.S. I did read JNA - callback method with void* arguments stackoverflow question, but it doesn't seem to be my case. I declared callback as static member public static NatLib.NotifyFunc notifyFunction = new MyNotifyFuncImpl(); - this should keep the reference to callback function unchanged and not garbage collected during runtime.
The problem is that you can not use Callback, if it is a __stdcall function. In this case you need to implement StdCallLibrary.StdCallCallback. So your code should be like this:
interface NotifyFunc extends StdCallLibrary.StdCallCallback{
void MyNotifyFunc(int code, Pointer value);
}
The reason behind this is that __stdcall is used to call functions of the Win32 API. And if you only use Callback Jna does not know it has to use these.
I need to use RegLoadKey function in my java code by using jna, but I'm getting the following error message:
Exception in thread "main" java.lang.UnsatisfiedLinkError: Error looking up function 'RegLoadKey': The specified procedure could not be found.
Blockquote
RegLoadKey syntax
LONG WINAPI RegLoadKey(
_In_ HKEY hKey,
_In_opt_ LPCTSTR lpSubKey,
_In_ LPCTSTR lpFile
);
my code:
Advapi32.java
import com.sun.jna.platform.win32.WinReg.HKEY;
import com.sun.jna.win32.StdCallLibrary;
public interface Advapi32 extends StdCallLibrary
{
long RegLoadKey(HKEY hKey, String lpSubKey,String lpFile);
}
apiTest.java
import com.sun.jna.*;
import com.sun.jna.platform.win32.WinReg.HKEY;
public class apiTest
{
public static void main (String [] args)
{
Advapi32 lib2 = (Advapi32) Native.loadLibrary("Advapi32", Advapi32.class);
HKEY key1 = new HKEY();
String filePath = "C:\\tmp\\software";
String regName = "loadedRegKey";
long test = lib2.RegLoadKey(key1, regName, filePath);
}
I think there are several problems with my code. I'm new to windows api and jna.
Did you know that an Advapi32 encapsulation is already part of JNA?
Have a look here. I just saw that your method RegLoadKey is not yet added there. So add it and submit that change to the jna guys. Afterwards you can use it like this (pseudo code):
public class RegistryRead{
private Advapi32 api = null;
public RegistryRead(){
this.api = Advapi32.INSTANCE;
}
public void read() {
long winapi = this.api.RegLoadKey(HKEY hkey, String subkey, String file);
...
}
}
If you look at the Advapi32 library mapping that comes with JNA, you'll see that the library instantiation includes some options to the load method. Among other things, these load options automatically map things like RegLoadKey to RegLoadKeyW, which is the real name of the function you're trying to link to.
It is a typical for JNA developing error. Just add before using it.
System.setProperty("jna.library.path","PATH_TO_LIBRARY_JNA");
PATH_TO_LIBRARY_JNA - absolute path to jna lib
I'm controlling some external device using my android app, and in order to control this device it provides an sdk which is a C#(.dll) files, I know how to load .dll libraries into java and how to use it, but I can't access a lot of methods inside these libraries because it takes C# native arguments like structs which is not available in Java, and I tried equivalents in Java like classes with public elements to represent a struct but it keeps give me the error: java.lang.IllegalArgumentException: Unsupported argument type
This is how I deal with the Library(using jna):
import outsource.classes.MyClass;
import com.sun.jna.Library;
import com.sun.jna.Native;
public class Test {
public interface simpleDLL extends Library {
long H264_DVR_GetLastError(int num); // accessed without any problems
boolean H264_DVR_SetDVRMessCallBack(MyClass obj, long num); // this "MyClass" is mainly a STRUCT in the C# sdk
}
static
{
System.loadLibrary("NetSdk");
}
public static void main(String args[]) {
simpleDLL INSTANCE = (simpleDLL) Native.loadLibrary(("NetSdk"),
simpleDLL.class);
System.out.println(INSTANCE.H264_DVR_GetLastError(4));
System.out.println(INSTANCE.H264_DVR_SetDVRMessCallBack(new MyClass(),
0));
}
}
And this is how I created MyClass.Class:
public class MyClass() {
public String Id = "myDevice";
public String UserName = "admin";
public int password = 1234;
}// also tried declaring the values inside a constructor but nothing changed
and this is how the struct defined inside the sdk:
typedef struct _DEVICEINFO
{
char id[64];
char user[64];
int pw;
}DEVICEINFO,*LP_DEVICEINFO;
p.s. I know there are some ways to write an android app with C# code using VisualBasic(e.g vs-android) but that won't work in my case as the app is already written and running with java and it's pretty huge with a lot of other functionalists so it can't be rewritten.
I am writing a JUnit test for code submitted to a competition. The rules of the competition require that certain methods not be called from other methods. (I unfortunately can not change the rules.)
The contestants are all implementing an interface we supplied which includes an add(K key, V value) method and a delete(K key) method. We need to test that entries do not implement delete by adding every other element to a new object and return that object.
We are also trying to avoid adding dependencies outside of the Java core since we are using a lot of automated tools (like the Marmoset Project) to test the hundreds of submissions.
I read through the documentation for Java Reflection and Instrumentation and nothing jumped out at me.
We are using Java 8 if it makes a difference.
AspectJ compile time weaving will probably be your best bet.
You will need to recompile the code with aspectj compiler and add advice to intercept the call.
If you give me more details I can show some example code.
You probably want a mocking library, and to use a "spy" test object. Using Mockito it might look something like this.
eg.
import static org.mockito.Mockito.*;
public class Test {
#Spy
ClassUnderTest classUnderTest;
#Before
public void init() {
MockitoAnnotations.initMocks(this);
}
#Test
public void deleteNeverCalled() {
// given
String key = randomString();
String value = randomString();
// when
classUnderTest.add(key, value)
// then
verify(classUnderTest, never()).delete(any());
}
}
This was my solution in the end. It looks like in the original question, I did not mention that this was a binary tree, so the compareTo function would be used constantly.
I created an Exception we could throw in our test framework and then detect.
public static class NotAllowedException extends RuntimeException
I created a new type that would have a flag that could be set to true by the testing framework before calling delete.
/**
* This class uses reflection to check whether {#link compareTo()} is being
* called inside the add method after the test decides it is done with the
* add method.
* It will throw a {#link NotAllowedException}.
*
* #author yakatz <email#domain.com>
*/
private class MyIntWrapper {
private boolean doneAdding = false;
public void doneAdding() {
this.doneAdding(true);
}
public void doneAdding(boolean b) {
this.doneAdding = b;
}
private class MyInteger implements Comparable<MyInteger> {
private Integer value;
public MyInteger(int value) {
this.value = value;
}
#Override
public int compareTo(MyInteger o) {
if (MyIntWrapper.this.doneAdding) {
StackTraceElement[] causes = Thread.currentThread().getStackTrace();
for (StackTraceElement cause : causes) {
if (cause.getClassName().equals("tree.Node") && cause.getMethodName().equals("add")) {
throw new NotAllowedException();
}
}
}
return this.value.compareTo(o.value);
}
}
}
I can then use the class in tests like this:
MyIntWrapper mir = new MyIntWrapper();
Tree<MyIntWrapper.MyInteger, String> tree = new Tree();
// Add stuff to the tree
mir.doneAdding();
MyIntWrapper.MyInteger mi = mir.new MyInteger(1);
tree = tree.delete(mi); // Will throw NotAllowedException if add() is called