I wanted to test JNI by preparing simple example. I did had a lot of problems with it. Especially with creating proper DLL :( That is why I wanted to live something behind - maybe someone will have less problems. This is a simple example not tutorial about JNI.
Software:
Plan:
- Java part.
- Create java project.
- Create java class with native methods.
- Generate cpp header.
- Create java class which will load library and use our native class
- C++ part.
- Create c++ project.
- Create c++ class and implement it.
Java part
After opening eclipse IDE create new Java project (File->New->Other->Java Project). Name: jni_hello_world. Create new class (File->New->Class) in default package (empty package) named MyFirstWrapper.
public class MyFirstWrapper {
native public String first(String parameter);
}
Create cpp directory in main project. Using eclipse External Tools Configuration (on the main toolbar there is play icon with red toolbox - running external tools) we add new configuration. Name: generate JNI header, location: c:\Program Files\Java\jdk1.7.0\bin\javah.exe, working directory: ${workspace_loc:/jni_hello_world/cpp} (use browse workspace directory), arguments: -jni MyFirstWrapper. After running it refresh the project (F5 on project). There should be created header file MyFirstWrapper.h in cpp directory.
/* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class MyFirstWrapper */
#ifndef _Included_MyFirstWrapper
#define _Included_MyFirstWrapper
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: MyFirstWrapper
* Method: first
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_MyFirstWrapper_first
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
Now lets create new class named Runner in default package.
public class Runner {
static public void main(String[] args) throws Exception {
System.loadLibrary("MyFirst");
MyFirstWrapper wrapper = new MyFirstWrapper();
System.out.println(wrapper.first("world!"));
}
}
Using eclipse Run Configuration (on the main toolbar there is play icon) we add new configuration. On the main tab: name: Runner, project: jni_hello_world, main class: Runner. On the arguments tab: vm arguments: -Djava.library.path=cpp. Apply.
Now we are missing the dll so we go to the second part in dev-cpp.
C++ part
Open dev-cpp and create new project (File->New->Project). Choose on tab basic: Dynamic DLL, name: MyFirst, language C++, then OK and save it in your workspace in cpp directory (e.g. c:\workspaces\playground\jni_hello_world\cpp\MyFirst.dev). Now lets close without saving all generated tabs (right click on tab and close all). Add header file (right click on project and add to project - choose MyFirstWrapper.h). Create new file and save it as MyFirstWrapper.cpp (right click on project and new file then CTRL+S).
#include
#include
#include
#include
#include
#include "MyFirstWrapper.h"
JNIEXPORT jstring JNICALL Java_MyFirstWrapper_first
(JNIEnv *env, jobject obj, jstring parameter) {
jboolean isCopy;
const char *param = env->GetStringUTFChars(parameter, JNI_FALSE);
char temp[127];
sprintf(temp, "Hello %s!", param);
jstring result = env->NewStringUTF(temp);
env->ReleaseStringUTFChars(parameter, param);
return result;
}
Now we have to setup the project options. Open project properties (right click on project and project options). Tab Directories, subtab Include Directories add C:\Program Files\Java\jdk1.7.0\include and C:\Program Files\Java\jdk1.7.0\include\win32 (click the folder icon, choose folder and add button).
Hit in menu Execute->Rebuild All and there should be MyFirst.dll created.
Finally refresh the project in Eclipse and hit the earlier prepared runner configuration. The End. If you found it usefull live me a note ;) Maybe I will write something more when I will play around.
14 comments:
Great tutorial!! It helped me a lot. I had no problems at all, and it saved me a big headache...
I can't be thankfull enough.
Thank You
I use eclipse Helios on Windows 7, I did exactly as you told, but I get "error: cannot access MyFirstWrapper, class file for MyFirstWrapper not found, javadoc: error - Class MyFirstWrapper not found. Error: No classes were specified on the command line. Try -help."
1)my MyFirstWrapper.class is created in bin folder of jni_hello_world folder in eclipse.
2)i have set environment variable "Variable Name : JAVA_HOME, Variable Value : C:\Program Files\Java\jdk1.6.0_23"
3)How do I give Arguments, -jni MyFirstWrapper, how do I tell eclipse to look for my class file in ".....jni_hello_world\bin" folder of my eclipse workspace.
Your help will be appreciated, thankyou
Okay, now, I changed, working Directory to "....\jni_hello_world\bin" and then ran. It successfully created the header file, but it created in the bin folder.
How do I make eclipse search for the class file from "....\jni_hello_world\bin" and store the header file created in "....\jni_hello_world\cpp"
Hi while trying out your example in eclipse Helios windows xp am getting this error in eclipse console
"error: cannot access MyFirstWrapper, class file for MyFirstWrapper not found, javadoc: error - Class MyFirstWrapper not found. Error: No classes were specified on the command line. Try -help."
what i have to do..???
waiting for your reply
Hi vishwa, I exactly got the same error, you can read the comments in this post, But I tried something, and I was able to create the header file, but changing the working directory...
Hi Gopal May i know exactly what u changed...i didnt get you
In Run Tools, External Tools Configurations, Name : give whatever name you want, 1)Location : c:\Program Files\Java\jdk1.7.0\bin\javah.exe 2) WrokingDirectory : GIVE THE BIN FOLDER OF YOUR ANDROID_TEST_PROJECT(jni_hello_world). 3) -jni MyFirstWrapper
What Working Directory actually means is, where our MyFirstWrapper.class file is located. previously we used to give /jni_hello_world/cpp. But that is not where our MyFirstWrapper.class is created. I guess for us it is created in some folder "bin" in the folder jni_hello_world, (check your filesystem once).
Probably that Wendro guy might have done some previous setting to get the MyFirstWrapper.class created in cpp directory. So he mentioned jni_hello_world/cpp in "Working Directory"
Then once you do this, your jni header file will also be created in bin folder, now copy this header file and paste it in jni_hello_world/cpp and proceed...
Hope it works, or you can get back to me...
Hi Thanks i did like this i got a jni header file
In Eclipse Run Tools, External Tools Configurations,
Name:Jni
Location:My javah.exe location
D:\ProgramFiles\Java\jdk1.6.0_17\bin\javah.exe
Working Directory: my javah file location
${workspace_loc:/jni_hello_world/cpp}
And the most important point is inside Arguments we have to give first as our .class location then jni command like below
-classpath E:\Workspace\JNI\jni_hello_world\bin
-jni MyFirstWrapper
hi,
I have tried this example, but I got an error.java.lang.NoClassDefFoundError: Djava/library/path=cpp.
Actually what have to set as the VM arguments in Run Configuration.
In this document it is given as Djava/library/path=cpp....
Pls reply anyone............
Advance thanks......
hi,
I have tried this example, but I got an error.java.lang.NoClassDefFoundError: Djava/library/path=cpp.
Actually what have to set as the VM arguments in Run Configuration.
In this document it is given as Djava/library/path=cpp....
Pls reply anyone............
Advance thanks......
posted a working example here:
http://stackoverflow.com/questions/17199904/why-do-i-get-unsatisfiedlinkerror-when-calling-a-mingw-compiled-function-not-lo/18523019#18523019
Works for me..
In Eclipse Run Tools, External Tools Configurations:
* Working Directory: my javah file location => ${workspace_loc:/jni_hello_world/bin}
* inside Arguments :
-verbose -d "${workspace_loc:/jni_hello_world/cpp}"
-jni MyFirstWrapper
Post a Comment