其实网上的例子我都作了,很管用,自己也写了,如下 我的任务是,人家给我一个.h(用c写的)然后我用java的jni去掉用人家写好的方法,我只是模拟一个小例子,就这么简单的任务,没想到这么复杂,终于有了一点点的进步,网上的例子很多都是对于.dll里很简单的方法调用,没有参数传递,要么就是一个空方法,然后自己去实现,可恶得很,下面就介绍我写的吧! 首先是要有一个.c文件,然后对应他的.h文件,动态连接库的工程名称是helllo(本来想起hello的,可是我写错了) Source Files: .c文件名:mydll2.cpp(和c一样)#include "mydll2.h" 源码: int ReturnY(int x, int y, int z){ return x+y+z; }.h文件名:mydll2.h 源码: #ifndef _MYDLL2__H__ #define _MYDLL2__H__ #ifdef __cplusplus extern "C" { #endif //extern "C" __declspec(dllimport) ReturnX(int x, int y); extern "C" int __declspec(dllexport) ReturnY(int x, int y, int z); #ifdef __cplusplus } #endif #endifok,如果你得.c编译成功就对了,这个mydll2.h就是你要用java调用的,其中里面有个方法叫做ReturnY,下面就是写一个java了 .java文件名:head.java 源码: public class head { public native int ReturnY(int x,int y,int z); public static void main(String[] args) { System.loadLibrary("helllo"); head h = new head(); int square = h.ReturnY(1,2,3); System.out.println("intMethod: " + square); } } 看着很熟悉吧,然后javac head.java生成.class文件,javach head生成.h文件,按照上编日志,把.h文件导入工程的Header Files里。 下面我们就编写自己的.c文件了,目的是生成自己的.dll库文件供java去掉用,好累,快写完了。 .c文件名:head.c 源码: #include <jni.h> JNIEXPORT jint JNICALL Java_head_ReturnY (JNIEnv *ev, jobject obj, jint x, jint y,jint z) { return ReturnY(x,y,z); } 这里的ReturnY(x,y,z)实际上是调用mydll2.h所对应的mydll2.cpp里的c函数。 可是如果.h文件里有结构体,我该怎么办呢?我又不知道java如何调用结构体
假如我拿到的头文件mydll2.h里有这样的方法,参数是结构体,或者是指针,对应的java我就不会写了拉,哭死了,指针我已经试验成功了!如果要源码加我msn:[email protected] struct tagSmsEntry { int index; /*index, start from 1*/ int status; /*read, unread*/ int type; /*-1-can't parser 0-normal, 1-flash, 2-mms*/ int storage; /*SMS_SIM, SMS_MT*/ char date[24]; char number[32]; char text[144]; } SmsEntry; int SmsInit(void); int SmsSend(char *phonenum, char *content); int SmsRead(SmsEntry *entry, int storage, int index);
2.用javah生成和主程序对应的头文件
3.修改java的本地安全策略,使得有权限访问本地的动态链接库
public class demo{
public native int getNumber();
public native void setNumber(int value);
}用javac编译成 demo.class
再用javah编译成 demo.h
写一个demo.cpp把demo.h的定义的原形方法实现
如果你电脑装了c++ Builder使用
1。bcc32 demo.cpp 生成demo.obj
2。bcc32 -WDR demo.obj
生成后的就是demo.dll,和类放在一起,在测试类里面写
static{
System.loadLibrary("demo");
|
public static void main(String args[]){
demo test = new demo();
test.setNumber(123);
system.out.println(test.getNumber());
}
程序输出如下: 123
如果不懂给我发邮件[email protected]
转的高手帖
/////////////////////////////////////////////
从 Java 程序调用 C 或 C ++ 代码的过程由六个步骤组成。我们将在下面几页中深入讨论每个步骤,但还是先让我们迅速地浏览一下它们。
编写 Java 代码。我们将从编写 Java 类开始,这些类执行三个任务:声明将要调用的本机方法;装入包含本机代码的共享库;然后调用该本机方法。
编译 Java 代码。在使用 Java 类之前,必须成功地将它们编译成字节码。
创建 C/C++ 头文件。C/C++ 头文件将声明想要调用的本机函数说明。然后,这个头文件与 C/C++ 函数实现(请参阅步骤 4)一起来创建共享库(请参阅步骤 5)。
编写 C/C++ 代码。这一步实现 C 或 C++ 源代码文件中的函数。C/C++ 源文件必须包含步骤 3 中创建的头文件。
创建共享库文件。从步骤 4 中创建的 C 源代码文件来创建共享库文件。
运行 Java 程序。运行该代码,并查看它是否有用。我们还将讨论一些用于解决常见错误的技巧。
步骤 1:编写 Java 代码 第 3 页(共16 页)
我们从编写 Java 源代码文件开始,它将声明本机方法(或方法),装入包含本机代码的共享库,然后实际调用本机方法。
这里是名为 Sample1.java 的 Java 源代码文件的示例:
1. public class Sample1
2. {
3. public native int intMethod(int n);
4. public native boolean booleanMethod(boolean bool);
5. public native String stringMethod(String text);
6. public native int intArrayMethod(int[] intArray);
7.
8. public static void main(String[] args)
9. {
10. System.loadLibrary("Sample1");
11. Sample1 sample = new Sample1();
12. int square = sample.intMethod(5);
13. boolean bool = sample.booleanMethod(true);
14. String text = sample.stringMethod("JAVA");
15. int sum = sample.intArrayMethod(
16. new int[]{1,1,2,3,5,8,13} );
17.
18. System.out.println("intMethod: " + square);
19. System.out.println("booleanMethod: " + bool);
20. System.out.println("stringMethod: " + text);
21. System.out.println("intArrayMethod: " + sum);
22. }
23. }
第二步接下来,我们需要将 Java 代码编译成字节码。完成这一步的方法之一是使用随 SDK 一起提供的 Java 编译器 javac。用来将 Java 代码编译成字节码的命令是:
javac Sample1.java
第三步是创建 C/C++ 头文件,它定义本机函数说明。完成这一步的方法之一是使用 javah.exe,它是随 SDK 一起提供的本机方法 C 存根生成器工具。这个工具被设计成用来创建头文件,该头文件为在 Java 源代码文件中所找到的每个 native 方法定义 C 风格的函数。这里使用的命令是:
javah Sample1
第四步当谈到编写 C/C++ 函数实现时,有一点需要牢记:说明必须和 Sample1.h 的函数声明完全一样。我们将研究用于 C 实现和 C++ 实现的完整代码,然后讨论两者之间的差异
以下是 Sample1.c,它是用 C 编写的实现:
1. #include "Sample1.h"
2. #include <string.h>
3.
4. JNIEXPORT jint JNICALL Java_Sample1_intMethod
5. (JNIEnv *env, jobject obj, jint num) {
6. return num * num;
7. }
8.
9. JNIEXPORT jboolean JNICALL Java_Sample1_booleanMethod
10. (JNIEnv *env, jobject obj, jboolean boolean) {
11. return !boolean;
12. }
13.
14. JNIEXPORT jstring JNICALL Java_Sample1_stringMethod
15. (JNIEnv *env, jobject obj, jstring string) {
16. const char *str = (*env)->GetStringUTFChars(env, string, 0);
17. char cap[128];
18. strcpy(cap, str);
19. (*env)->ReleaseStringUTFChars(env, string, str);
20. return (*env)->NewStringUTF(env, strupr(cap));
21. }
22.
23. JNIEXPORT jint JNICALL Java_Sample1_intArrayMethod
24. (JNIEnv *env, jobject obj, jintArray array) {
25. int i, sum = 0;
26. jsize len = (*env)->GetArrayLength(env, array);
27. jint *body = (*env)->GetIntArrayElements(env, array, 0);
28. for (i=0; i<len; i++)
29. { sum += body[i];
30. }
31. (*env)->ReleaseIntArrayElements(env, array, body, 0);
32. return sum;
33. }
34.
35. void main(){}
步骤 5:创建共享库文件 第 13 页(共16 页)
接下来,我们创建包含本机代码的共享库文件。大多数 C 和 C++ 编译器除了可以创建机器代码可执行文件以外,也可以创建共享库文件。用来创建共享库文件的命令取决于您使用的编译器。下面是在 Windows 和 Solaris 系统上执行的命令。
Windows: cl -Ic:\jdk\include -Ic:\jdk\include\win32 -LD Sample1.c -FeSample1.dll
Solaris: cc -G -I/usr/local/jdk/include -I/user/local/jdk/include/solaris Sample1.c -o Sample1.so
最后一步是运行 Java 程序,并确保代码正确工作。因为必须在 Java 虚拟机中执行所有 Java 代码,所以需要使用 Java 运行时环境。完成这一步的方法之一是使用 java,它是随 SDK 一起提供的 Java 解释器。所使用的命令是:
java Sample1
当运行 Sample1.class 程序时,应该获得下列结果:
PROMPT>java Sample1
intMethod: 25
booleanMethod: false
stringMethod: JAVA
intArrayMethod: 33
PROMPT>
来自ibm的jni教程
如果还是不懂加MSN:[email protected],我做个例子给你!
我的任务是,人家给我一个.h(用c写的)然后我用java的jni去掉用人家写好的方法,我只是模拟一个小例子,就这么简单的任务,没想到这么复杂,终于有了一点点的进步,网上的例子很多都是对于.dll里很简单的方法调用,没有参数传递,要么就是一个空方法,然后自己去实现,可恶得很,下面就介绍我写的吧!
首先是要有一个.c文件,然后对应他的.h文件,动态连接库的工程名称是helllo(本来想起hello的,可是我写错了)
Source Files:
.c文件名:mydll2.cpp(和c一样)#include "mydll2.h"
源码:
int ReturnY(int x, int y, int z){ return x+y+z; }.h文件名:mydll2.h
源码:
#ifndef _MYDLL2__H__
#define _MYDLL2__H__
#ifdef __cplusplus
extern "C" {
#endif
//extern "C" __declspec(dllimport) ReturnX(int x, int y);
extern "C" int __declspec(dllexport) ReturnY(int x, int y, int z);
#ifdef __cplusplus
}
#endif
#endifok,如果你得.c编译成功就对了,这个mydll2.h就是你要用java调用的,其中里面有个方法叫做ReturnY,下面就是写一个java了
.java文件名:head.java
源码:
public class head
{
public native int ReturnY(int x,int y,int z);
public static void main(String[] args)
{
System.loadLibrary("helllo");
head h = new head();
int square = h.ReturnY(1,2,3);
System.out.println("intMethod: " + square);
}
}
看着很熟悉吧,然后javac head.java生成.class文件,javach head生成.h文件,按照上编日志,把.h文件导入工程的Header Files里。
下面我们就编写自己的.c文件了,目的是生成自己的.dll库文件供java去掉用,好累,快写完了。
.c文件名:head.c
源码:
#include <jni.h>
JNIEXPORT jint JNICALL Java_head_ReturnY (JNIEnv *ev, jobject obj, jint x, jint y,jint z)
{
return ReturnY(x,y,z);
}
这里的ReturnY(x,y,z)实际上是调用mydll2.h所对应的mydll2.cpp里的c函数。
可是如果.h文件里有结构体,我该怎么办呢?我又不知道java如何调用结构体
int index; /*index, start from 1*/
int status; /*read, unread*/
int type; /*-1-can't parser 0-normal, 1-flash, 2-mms*/
int storage; /*SMS_SIM, SMS_MT*/
char date[24];
char number[32];
char text[144];
} SmsEntry; int SmsInit(void);
int SmsSend(char *phonenum, char *content);
int SmsRead(SmsEntry *entry, int storage, int index);