I am trying to generate a dll which I can access from java via JNA.
I just try a simple one:
CPP:
void Initialize()
{
std::cout<< "Hello World!";
}
iostream is also included and after compiling I get: CreateDll.dll
Via Visual Studio I can generate now a *.dll.
which I try loading into Java like:
public class mainRoutine {
public static void main(String[] args) {
NativeWrapper INSTANCE = (NativeWrapper) Native.loadLibrary("CreateDll" , NativeWrapper.class);
INSTANCE.Initialize();
}
static {
System.setProperty("jna.library.path", "C:\\workspace\\JNA");
}
}
There is also another Interface:
import com.sun.jna.Library;
public interface NativeWrapper extends Library {
void Initialize();
}
So but now running the Java function I get the error,
java.lang.UnsatisfiedLinkError:
Error looking up function 'Initialize':
The specified procedure could not be found.
What am I missing?
PS: I know there are many topics, but trying for a day already I have not found the solution. Please help me.
You need to both export and (if using C++) un-decorate the function name.
On windows, functions are typically made available for export with __declspec(dllexport).
On any platform, to ensure a function is exported in unmanagled form, you must use extern "C".
Specifically:
extern "C" void __declspec(dllexport) Initialize() { ... }
There are other ways to designate exported functions, but this is probably the most common and straightforward to use. If you don't use extern "C", your function will look something like InitializeZ#ASDF#, where the additional garbage characters are used by the compiler and linker to make a given function uniquely recognizable based on its calling signature.
Are you exporting the symbol:
void _declspec(dllexport) Initialize()
{
std::cout<< "Hello World!";
}
What if there is a class to be implemented ? where the .h file looks like this:
namespace simpleDLLNS
{
class simpleDLL
{
public:
char giveVoidPtrGetChar(void* param);
int giveIntGetInt(int a);
void simpleCall(void);
int giveVoidPtrGetInt(void* param);
};
}
Where should extern "C" void __declspec(dllexport) be used ?
I used it when implementing the functions. but when i opened the dll, it looked like this:
?simpleCall#simpleDLL#simpleDLLNS##QAEXXZ
Related
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'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'm new from JNI programming
Can i call a native method like from a different JNI namespace definition?
For example:
package com.example.hellojni;
public class HelloJni extends Activity
{
public native int MyMethod();
public native int OtherMethod(); // this works have the namespace package=jniexport interface
static {System.loadLibrary("hello-jni");}
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
int b = OtherMethod(); //works
int a = MyMethod(); //ERROR java.lang.reflect.InvocationTargetException
}
}
================File.c================
JNIEXPORT int JNICALL Java_Cardioline_HelloJni_MyMethod(JNIEnv *env, jobject thisObj)
{
return 1;
}
JNIEXPORT int JNICALL Java_com_example_hellojni_HelloJni_OtherMethod(JNIEnv *env, jobject thisObj)
{
return 2;
}
No, the JNI method name is predetermined by javah. Try starting here:
http://blog.edwards-research.com/2012/04/tutorial-android-jni/
javah will provide you with the header and you must copy the method declarations into your .c file.
If you have a JNI method in another class that you want to call, call the other class in java. Basically change this:
int a = MyMethod();
to this:
int a = new CardioLine.HelloJni().MyMethod();
Typically, I have a one-to-one mapping of Java files to .c/.cpp files. That's probably what you want too (for Java classes with native methods).
As #JonnyBoy explained in his answer, the name of a JNI native function is tightly coupled with the full name of the Java class that uses this function as a native method. The full name of HelloJni class in com.example.hellojni package is com.example.hellojni.HelloJni, thus it looks for native functions which names start with Java_com_example_hellojni_HelloJni_.
Luckily, there is no requirement in Android for all your classes to be under the app package. For example, your app that is registered as com.example.hellojni is free to include and use a package CardioLine and class CardioLine.HelloJni.
The directory structure for a simple Android project will include a tree like this:
src
com
example
hellojni
HelloJni.java
CardioLine
HelloJni.java
On the other hand, if you include JNI_OnLoad() function in your native library, and use RegisterNatives(), your Java class can have native methods regardless of their exported names.
I have one c++ dll file. And I know the methods used in it. I need to call these methods from my java code. I don't have access to modify the DLL file. Please provide me a solution to do this.
I created JavaCPP exactly for that purpose. I'll copy/paste some sample code and explanations from the page:
The most common use case involves accessing some legacy library written for C++, for example, inside a file named LegacyLibrary.h containing this C++ class:
#include <string>
namespace LegacyLibrary {
class LegacyClass {
public:
const std::string& get_property() { return property; }
void set_property(const std::string& property) { this->property = property; }
std::string property;
};
}
To get the job done with JavaCPP, we can easily define a Java class such as this one--although one could use the Parser to produce it from the header file as demonstrated below:
import com.googlecode.javacpp.*;
import com.googlecode.javacpp.annotation.*;
#Platform(include="LegacyLibrary.h")
#Namespace("LegacyLibrary")
public class LegacyLibrary {
public static class LegacyClass extends Pointer {
static { Loader.load(); }
public LegacyClass() { allocate(); }
private native void allocate();
// to call the getter and setter functions
public native #StdString String get_property(); public native void set_property(String property);
// to access the member variable directly
public native #StdString String property(); public native void property(String property);
}
public static void main(String[] args) {
// Pointer objects allocated in Java get deallocated once they become unreachable,
// but C++ destructors can still be called in a timely fashion with Pointer.deallocate()
LegacyClass l = new LegacyClass();
l.set_property("Hello World!");
System.out.println(l.property());
}
}
Alternately, we can produce a Java interface by parsing the header file with a config class such as this one:
#Properties(target="LegacyLibrary", value=#Platform(include="LegacyLibrary.h"))
public class LegacyLibraryConfig implements Parser.InfoMapper {
public void map(Parser.InfoMap infoMap) {
}
}
And the following build commands:
$ javac -cp javacpp.jar LegacyLibraryConfig.java
$ java -jar javacpp.jar LegacyLibraryConfig
$ javac -cp javacpp.jar LegacyLibrary.java
$ java -jar javacpp.jar LegacyLibrary
For more complex examples including Maven/IDE integration, check out the JavaCPP Presets!
I am wondering is it possible to verify in Java under the Android SDK that a method in a Java class implemented as a native JNI method was resolved statically? Below there is an explanation of what I am looking for.
I have a Java class that is partially implemented as a JNI class. This class can be initialized statically if the corresponding JNI library has been created as a static library (libhelper.a, for instance). Or it can be initialized dynamically if the corresponding JNI library is implemented as a dynamic library (libhelper.so, for instance). In case of dynamic initialization the class should have a static initializer that loads the dynamic library – libhelper.so. I am using both case and I want to keep the same source code for both of them. For this purpose I would like to verify in the static initializer if the corresponding native methods has been already resolved. If it is true, I do not need to load dynamic library. If it is false, it means that I have to load dynamic library. The problem is I do not know how to verify that a method in the class has been already resolved.
The sample below has incorrect lines, that show my intention.
package com.sample.package;
public class MyUtilityClass
{
private static final String TAG = "MyUtilityClass";
public MyUtilityClass () {
Log.v(TAG, " MyUtilityClass constructor");
}
public static native int initMyHelperClass();
public static native int performHelpAction(String action);
public static native int uninitMyHelperClass();
static {
try {
/* Here I want to verify that the native method
initMyHelperClass has has been already resolved.
In this code snippet I am just comparing it to null,
which is not correct. It should be something different. */
if (initMyHelperClass == null) {
/* initMyHelperClass has not been resolved yet,
load the dynamic library - libhelper.so */
System.loadLibrary("helper");
}
} catch (UnsatisfiedLinkError ule) {
/*Library not found. We should throw second exception. */
throw ule;
}
}
}
Thank you.
You could use UnsatisfiedLinkError and a dummy method to check if a given class' native methods are loaded:
private static native void checkMe(); // does nothing
static {
try {
checkMe();
} catch (UnsatisfiedLinkError e) {
System.loadLibrary("checkLibrary");
}
}