项目有一个需要控制ipc的功能,我之前取巧用了visca协议,走网口的,结果同组的C++的同事听闻我这样控,问了我控制方法,发现我这样控制很简单,而他使用onvif协议写了很多内容,遂验证该协议是否能对其他大厂的IPC进行控制,测了一个海康威视的摄像头就不行了,上网查了一下发现visca协议大多支持串口,网口实现的较少,相比之下Onvif协议比较通用,遂准备重新实现Onvif协议,刚开始写这个功能的时候也了解过,但是因为较麻烦又刚好从其他人那里知道了visca协议才没有实现,确实很麻烦,然后向C++同事请教控制流程,问过之后听他说可以用Java直接调C++的方法,我之前确实学完就忘了,然后重新学了一遍Jni,踩了不少坑记录一下

 

1.创建一个类,里面有 native 修饰的方法,可以是 static 修饰的

1 import java.util.Map;
2 
3 public class Hello {
4     public native String hello(Map map);
5 
6 }

 2. 类路径下使用dos命令 {javac 类.java} ,编译出class 文件

1 C:\>javac Hello.java

3. 类路径下使用{javah 类名},生成 .h文件在同一路径下

1 C:\>javah Hello

这个地方有一个坑,刚开始测试的时候在类路径下这样执行是没问题的,但是正式放入项目中使用时报错了,

1 package com.x.hello;

放在项目中使用时要根据在package的最外层包下执行,也就是包含这个包com,项目路径下的src文件下执行,生成的文件在执行dos命令的路径下

1 C:\>javah -classpath . -jni 包名.类名

4. 打开VS2019(其他版本均可,我习惯性下最高版本),创建一个空项目

点击源文件,添加,类,头文件名改为生成文件名,然后点击添加,

Java实现onvif服务端_头文件

 

 

 

 5.打开头文件中生成的 头文件,把javah编译后生成的头文件内容复制到里面

Java实现onvif服务端_Java_02

 

 

 这一步第一次的话也有一个坑,需要打开项目的属性页,点击c/C++,在附加目录中添加Java底层C++文件的路径,jdk安装目录下include文件夹和include文件夹下的win32文件夹,

如:

C:/jdk/include

C:/jdk/include/win32

Java实现onvif服务端_Java实现onvif服务端_03

 

 

 

6. 打开源文件在添加的类中放入以下内容

1 #include<iostream>
2 #include "hello.h"
3 
4 using namespace std;
5 
6 JNIEXPORT void JNICALL Java_Hello_hello(JNIEnv* env, jobject f)
7 {
8      printf("hello123");
9 }

点击项目名生成即可。

需要注意的是这个设置内容需要和Java安装的环境一样,在这里32位不兼容64位,暂不清楚原因

Java实现onvif服务端_Java实现onvif服务端_04

 

 7. 根据生成路径,在路径下找到 后缀位 .dll 和项目同名的文件,复制到C:/windows/system32  下即可

Java实现onvif服务端_java_05

 

 

Java实现onvif服务端_头文件_06

 

 8. 打开Hello.java ,添加main方法调用native修饰方法,调用前使用

System.loadLibrary("C++项目名,不要后缀");

,试试效果,刚开始时也可直接写main方法,不过其中刚开始写可能会有语法问题,所以不建议生成头文件时就写main方法

1 package com.xh.server.utils;
 2 
 3 public class OnvifUtil {
 4     static {
 5         System.loadLibrary("OnvifUtil");
 6     }
 7 
 8     public native void hello();
 9 
10     public static void main(String[] args){
11         OnvifUtil onvifUtil = new OnvifUtil();
12        
13         onvifUtil.hello();
14 
15     }
16 
17 }