Hello jna

记录下这几天用jna3.5.0调c++写的dll的经历

os:win7

用jna调dll首先需要一个dll文件并有可调的方法,然后根据方法的名称,参数,返回值编写一个interface

c++需要包含一个头文件,方法需要用extern "C" __declspec(dllexport)修饰

c与java类型的对应关系详见https://java-native-access.github.io/jna/3.5.0/javadoc/的Marshalling/Unmarshalling (Java/Native Type Conversions)这一节

example:

Hello.h

extern "C" __declspec(dllexport) char** hello();

Hello.cpp

char** hello(){
    char** result = new char*[3]
    result[0] = "123";
    result[1] = "321";
    result[2] = NULL;// 注意,数组的最后一个元素必须为NULL
    return;
}

以上是c++源码,打包成Hello.dll放到某个目录下,比如这里移动到D:\Hello\Hello.dll,注意平台要选择x64,否则64位jdk可能会找不到库

Hello.java

public interface Hello{
    String[] hello();
}

Main.java

public class Main{
    public static void main(String[] args){
        Native.setProtected(true);// 等效于jna.protected=true,这项设置会使本地方法发生异常时生成java异常,如果为false则本地方法发生异常时会使jvm崩溃,无法try-catch,默认false,注意此方法只适合在windows上测试时使用
        NativeLibrary.addSearchPath("Hello", "D:\\Hello");// 注意这里参数一不带dll后缀,参数二是文件所在的文件夹路径而不是文件路径
        Hello hello = (Hello) Native.loadLibrary("Hello", Hello.class);
        System.out.println(Arrays.toString(hello.hello()));
    }
}

Native.loadLibrary(String, Class);

这个方法第一个参数填加载dll的名称,不含.dll后缀。

搜索dll的路径是:
1)项目的根路径
2)操作系统的全局路径、
3)path指定的路径。

摘自https://blog.csdn.net/jimmy609/article/details/19076557

这里因为调用了addSearchPath方法所以不用在乎这些限制,dll可以放在任意位置

配合visual studio调试:

首先dll需要以debug模式编译,然后以debug模式运行java,在调用本地方法之前打好断点,在vs中选择调试-附加到进程,选择java的进程,进程id可以通过ManagementFactory.getRuntimeMXBean.getName()方法看到,前面的数字就是进程id,在vs中打好断点,放开java的断点就可以进来了。

另外提一句,String和char*之间会根据jna.encoding(默认utf8)转换,而中文系统是用的GBK编码,中文会乱码,可以通过手动设置jna.encoding参数解决,不过这里推荐使用wchar_t替换char,WString替换String

posted @ 2018-11-13 12:59  世界知名伟人  阅读(266)  评论(0编辑  收藏  举报