利用JNI调用c++函数

在公司项目中遇到这么一个难题

客户有一个基板,这个基板通过数据线可以连接到电脑上,装上驱动就可以调用基板提供的函数.

但是程序是java开发的,所以就需要通过java调用基板函数,但是基板函数允许C++调用不支持java,所以就用到java调用C++

基板函数按照返回值大致分为两种

1.调用后直接返回数字,一般属于命令型函数,比如打开电源,返回0表示打开成功

2.调用后返回数组,比如需要获取采集的数据

第一种类型比较容易,用JNA、JNI都可以实现。因为只返回一个int,java比较容易接收。

第二种返回数组,因为C++有指针,当时机器函数返回的是一个内存地址,这个时候如果直接调用java是无法访问内存地址的。

因此需要转换。

当初也尝试过将返回的数组转为用逗号分割的字符串,但是长度超过300就会类似内存溢出的错误,所以最后放弃这种方式。

 

重点说一下第二种情况的解决方法

JAVA的代码

public class OASSInterface {
    //方法
    public native int[] SDFArray(String jsonStr,int[] iarr);
    public native int getButtonStatus();
    //加载dll
    static{
		File directory = new File(OASSInterface.class.getResource("/").getPath());
		System.load(directory+ "\\Interface.dll");
	}

}


//直接调用即可
int[] resultArr = oASSInterface.SDFArray(jsonStr, arr,)

 

C++代码

最后C++要生成的是一个DLL文件

JNIEXPORT jintArray JNICALL Java_css_OASSInterface_SDFArray(JNIEnv *env, jobject obj, jstring jsonstr, jintArray arr){

    jstring jReturn;
	Json::Reader reader;
	Json::Value json_object;
	const char* json_document = (char*)env->GetStringUTFChars(jsonstr,0);  
	if (!reader.parse(json_document, json_object))
      return 0;
    //json解析获取其中的值
    int nTotalChannel=json_object["nTotalChannel"].asInt();
    //声明数组,这是最后机器返回的数值
    long long nNetIntensity[100] = {};
    //re是自定义错误编码,nStandDataAcq方式是项目的业务函数
    int re = nStandDataAcq(nTotalChannel*2 nNetIntensity);
    //最后要返回的数组
    jintArray intArray= env->NewIntArray(nTotalChannel+1);  
    jboolean* pb;

    //就是将nNetIntensity里面的值放到pint里面
    //由于有些业务逻辑,我删除了部分代码,for循环就是放值,不要照抄代码
    jint* pint=new jint[nTotalChannel+1];
	for(int k=0;k<nTotalChannel;k++){
		pint[k] = -999;
	}
    
	for(int j=0;j<nTotalChannel;j++){
	    pint[j]=nNetIntensity[j];
	}  
	//std::cout << nNetIntensity[i] << std::endl;
    pint[nTotalChannel] = re;
    env->ReleaseIntArrayElements(intArray,pint,JNI_COMMIT);//JNI_COMMIT=1
    delete []pint; //如果使用GetIntArrayElements()得到该指针则不可以!!!否则Java直接崩溃了  
    return intArray;
 }

int nStandDataAcq(int nTotalChannel,long long*nNetIntensity){
    //项目业务逻辑  
    ...
}

只是贴的部分代码,直接粘贴下来不能运行!

有几点需要说明一下

1.方法名 Java_css_OASSInterface_SDFArray   不可以随意命名,java开头,css是包名,OASSInterface是类名,SDFArray是方法名.

2.因为参数过多所以使用json作为参数传递,如果参数不多可以不使用json

3.C++的数组不能直接返回,需要转成jintArray

jni入门教程(里面包含如何创建C++程序)

http://www.runoob.com/w3cnote/jni-getting-started-tutorials.html

JNI详解

https://blog.csdn.net/hui12581/article/details/44832651

java调用C++会出现很多坑

一开始直接调用C++,出现C++返回指针地址,java无法读取问题

随后又改为返回字符串,出现字符串过长内存溢出问题

改为int数组解决问题后,换了版本高的基板后发现,第一次调用函数没有问题,第二次调用就卡主问题.

但是用C++直接运行没有问题,最后发现使用Win7系统不行,但是使用Win10就没有问题.项目结束也没有找到具体原因

开发过程中也出现好多问题,加上C++开发经验少,解决过程也是比较痛苦。出现问题请不要轻易放弃,网上有很多资料,当你解决了就会发现其实问题不是多么的复杂

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页