java调用dll库
来源:互联网 发布:jc js jk 编辑:程序博客网 时间:2024/05/22 16:45
最近项目需要用到java调用dll库。于是学习了一番,中间遇到一些问题,这里记录一下整体过程。
首先是把需要调用的函数用java写出来。这里写两个函数:
package com.tgb.controller;/** * Created by Chan on 2016/6/24. */public class picture { static { System.loadLibrary("puppet"); } public native static String compare(String disign , String scan , int param); public native static String test(int i);}
特别需要注意的地方是这里有package com.tgb.controller。后来才发现有package和没有package的区别是相当大的。
然后需要编译这个文件。因为是在SpringMVC里面做的,这里的路径是
springmvcTest\src\main\java\com\tgb\controller\picture.java
然后在controller目录下,shift+鼠标右键调出cmd窗口,然后javac编译这个文件。
javac picture.java
接着,需要生成一个c++用的头文件。转到目录java下,即
springmvcTest\src\main\java\
用javah命令生成头文件。
javah com.tgb.controller.picture
没有后缀名,命令执行完之后就会在java目录下生成一个叫com_tgb_controller_picture.h的文件,这就是我们后来要用到的头文件。
如果picture.java没有包的话直接在与它相同的目录下javah picture就可以了。
然后打开VS,开始c++这边的编写。不过在那之前需要做些准备工作。
首先,将以下三个文件拷贝到工程目录下,或者是放到VS/VC/include/下
- com_tgb_controller_picture.h
- JDK/include/jni.h
- JDK/include/win32/jni_md.h
然后打开VS。。。。
打开之后新建项目–win32项目—然后见下图:
然后点完成就行了。
接着新建一个源文件,头三句话就是这个:
#include"jni.h"#include"jni_md.h"#include"com_tgb_controller_picture.h"
这里先不接着写,我们先打开com_tgb_controller_picture.h看一下有些啥。
/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class com_tgb_controller_picture */#ifndef _Included_com_tgb_controller_picture#define _Included_com_tgb_controller_picture#ifdef __cplusplusextern "C" {#endif/* * Class: com_tgb_controller_picture * Method: compare * Signature: (Ljava/lang/String;Ljava/lang/String;I)Ljava/lang/String; */JNIEXPORT jstring JNICALL Java_com_tgb_controller_picture_compare (JNIEnv *, jclass, jstring, jstring, jint);/* * Class: com_tgb_controller_picture * Method: test * Signature: (I)Ljava/lang/String; */JNIEXPORT jstring JNICALL Java_com_tgb_controller_picture_test (JNIEnv *, jclass, jint);#ifdef __cplusplus}#endif#endif
一大堆东西其实不用管,可以看到里面声明了两个函数:
JNIEXPORT jstring JNICALL Java_com_tgb_controller_picture_compare (JNIEnv *, jclass, jstring, jstring, jint);
JNIEXPORT jstring JNICALL Java_com_tgb_controller_picture_test (JNIEnv *, jclass, jint);
可以看到函数名还是比较直观,前两个参数不用管,我们需要的参数从第三个开始。这就是我们之前在java写的两个方法的对应,我们只需要在这里实现这两个函数就行了。
源文件如下:
#include"jni.h"#include"jni_md.h"#include"com_tgb_controller_picture.h"#include<stdlib.h>#include<string.h>char* jstringTostring(JNIEnv* env, jstring jstr){ char* rtn = NULL; jclass clsstring = env->FindClass("java/lang/String"); jstring strencode = env->NewStringUTF("utf-8"); jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B"); jbyteArray barr = (jbyteArray)env->CallObjectMethod(jstr, mid, strencode); jsize alen = env->GetArrayLength(barr); jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE); if (alen > 0) { rtn = (char*)malloc(alen + 1); memcpy(rtn, ba, alen); rtn[alen] = 0; } env->ReleaseByteArrayElements(barr, ba, 0); return rtn;}jstring stoJstring(JNIEnv* env, const char* pat){ jclass strClass = env->FindClass("Ljava/lang/String;"); jmethodID ctorID = env->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V"); jbyteArray bytes = env->NewByteArray(strlen(pat)); env->SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte*)pat); jstring encoding = env->NewStringUTF("utf-8"); return (jstring)env->NewObject(strClass, ctorID, bytes, encoding);}JNIEXPORT jstring JNICALL Java_com_tgb_controller_picture_compare(JNIEnv * env, jclass, jstring design, jstring scan, jint param) { char *desChar = jstringTostring(env, design); char *scanChar = jstringTostring(env, scan); FILE *designpic = fopen(desChar,"r"); FILE *scanpic = fopen(scanChar, "r"); if (designpic == NULL || scanpic == NULL) { return stoJstring(env, "cannot open file."); } fclose(designpic); fclose(scanpic); return stoJstring(env, "files open succeed");}JNIEXPORT jstring JNICALL Java_com_tgb_controller_picture_test(JNIEnv * env, jclass, jint n) { if (n == 0) { return stoJstring(env, "test succeed"); } else return stoJstring(env, "test failure");}
char* jstringTostring(JNIEnv* env, jstring jstr)和jstring stoJstring(JNIEnv* env, const char* pat)是两个类型转换用的函数,因为java中的string和c++的字符串还有点不一样,所以在用的时候转换一下会方便很多。函数的功能很简单,看代码就行了。
接着,我们需要生成dll库,首先看java是多少位的。
如果是64位的就
32位的就
然后生成解决方案就可以了。
然后dll文件可以在VS项目中的debug文件夹中找到。将这个文件放到java项目目录下,或者C:\windows\system32目录下都可以。
然后在回到java中,我们写了一个简单的HelloController
package com.tgb.controller;import org.springframework.stereotype.Controller;import org.springframework.ui.ModelMap;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;@Controller@RequestMapping("/")public class HelloController { @RequestMapping(method = RequestMethod.GET) public String printWelcome(ModelMap model) { model.addAttribute("message", "Hello world!"); int n = 0; System.out.println("been here"); String ret = picture.compare("D:\\1.jpg","D:\\2.jpg",1); String testRet = picture.test(n); System.out.println(ret+" "+testRet); return "hello"; }}
然后直接跑。控制台输出如下:
说明本地库调用成功,至于为什么调用了三次有待进一步的学习。初步猜想是@RequestMapping(“/”)map到了所有的请求。
- java调用dll库
- java 调用 dll动态库
- Java调用dll库源码
- java调用动态库(.dll或.so)
- Java调用C++动态库dll
- java调用动态链接库(dll)
- java调用c++动态库dll
- JNI java调用动态链接库dll
- java调用dll动态库方法
- Java通过JNI调用DLL动态库
- java调用动态库dll文件
- Java调用dll动态库-笔记
- JAVA调用动态链接库(dll)
- 使用Java调用dll动态链接库
- java调用dll动态库文件方法
- java调用动态链接库 dll
- java调用dll
- JAVA调用DLL(1)
- 在Mac上面搭建Android开发环境
- MVC C# Html.TextBox等Html控件设置样式
- jdbc中单引号与双引号的作用
- 基于朴素贝叶斯的文本分类器
- javascript:void(0)是什么意思?JS的几种跳转
- java调用dll库
- [linux]进程 task_struct
- js原型链原理看图说明
- EventBus 3.0 使用
- Elasticsearch java API (9)更新的API
- Android OTA升级(2):开启升级过程
- IT职场人生-札记
- GMT,UTC,CST
- hdu4862Jump【最大费用最大流,判断是否满流】2014多校联合