jsmubanlogo
  • 首页
  • 网页模板
  • 特效代码
  • 博文源码
  • 插件下载
  •    

java调用c++的第三方dll动态库详解

收藏    

作者第十天    2021-12-05

      

由于在项目中用到了java调用c++的SDK动态库的例子,博主之前没有接触过,所以一直在网上百度,千篇一律,经过几天的努力终于成功了。所以博主想把它记录下来,方便其他人参考。

以下是要调用的接口方法:
/************************************************
方法一:(上传图片)1、fileName:输入参数。
×************************************************ */

M2CCGKEYER_API BOOL CALL_TYPE  M2CLogoCgKeyerUpLoadFile(const char *fileName);

/************************************************
方法二:(图片上线叠加)1、fileName:输入参数。
×************************************************ */

M2CCGKEYER_API BOOL CALL_TYPE M2CLogoCgKeyerSetupLogo(const char *fileName, int x, int y, BOOL bEnabled);


其中M2CLogoCgKeyerUpLoadFile和M2CLogoCgKeyerSetupLogo是方法名称,此方法在第三方提供的.h文件里面,我采用的是jni,之前也查过很多资料,考虑到效率问题我还是选择了我有难度的jni,至少效率比不用写c++的jna要高很多。因为这个函数是需要将图片叠加在视频上,必须要做到毫秒级别的。

第一步:(非必须的,根据项目实际需要)

          下载 dom4j-1.6.1.jar和log4j-1.2.17.jar的jar包,右键选中项目创建文件夹lib,将jar包copy进去,最后build path.(在此说明jni是java自带的所以不需要jar包的,前面两个jar包,是因为我要解析XML文件,并做一个日志输出,我会在后面的文章中逐一讲解的)

第二步:
         还是直接上代码吧,其中MyDLL7是用vs2015生成的dll文件,会在下面详细说明的,而M2CCGKeyer是第三方提供的dll动态库,注意这里加载顺序不能错,必须先加载MyDLL7,其实在这里有个误解,第三方的M2CCGKeyer.dll文件可以不用System.loadLibrary("M2CCGKeyer"),直接右键选中项目把这个文件copy在项目路径下就可以了,到时候会自己找到加载的。但是如果你写了System.loadLibrary("M2CCGKeyer"),那也必须将M2CCGKeyer.dll放在项目路径下。

  

  1. public class Task1 {
  2. package cn.com.plustv;
  3. public class SmartCard {
  4. static {
  5. System.loadLibrary("MyDLL7");//用c++自己编写的dll库文件
  6. System.loadLibrary("M2CCGKeyer");//第三方提供的库文件
  7. }
  8. /*方法一:
  9. * ***********************************************
  10. * 上载logo到设备,支持文件格式有:BMP和TGA。
  11. * 支持BMP和TGA 24bit或32bit像素深度; 支持TGA RLE压缩格式
  12. * 1、fileName:输入参数。 表示本地存储的Logo文件名,例如C://test.tga
  13. * ×************************************************
  14. */
  15. private native boolean M2CLogoCgKeyerUpLoadFile(String fileName);
  16. //使用jni必须要用native修饰,不是我说的哦,因为就这么规定的,好了,接下来该头疼的参数问题了,对于一个没接触过c++的人,可能比较吃力,比如小编我就是,其实java中的String对应c++中的char 但是在编写c++的过程中需要转换,还有释放内存,我会在后面讲解的。而fileName就是输入参数。
  17. private native boolean M2CLogoCgKeyerSetupLogo(String fileName, int x, int y, boolean bEnabled);//M2CLogoCgKeyerSetupLogo这种方法名称必须和第三方提供的接口方法名称保持一致,参数也要保持一一对应。
  18. // 外部类能调用的方法一
  19. public boolean tjSDK(String fileName) {
  20. return this.M2CLogoCgKeyerUpLoadFile(fileName);
  21. }
  22.     //方法三:
  23.     public boolean tjSDK03(String fileName, int x, int y, boolean bEnabled) {
  24.         
  25.         return this.M2CLogoCgKeyerSetupLogo(fileName, x , y , bEnabled);
  26.     }
  27.  }

第三步:

           需要编写一个测试方法,等到dll文件生成后,测试。

  1. public class Task1 {
  2. package cn.com.plustv;
  3. import org.junit.Test;
  4. public class TestSdk {
  5. SmartCard sc = new SmartCard();
  6. @Test
  7. public void test01() {
  8. //测试方法一:通过
  9. boolean tjSDK = sc.tjSDK("D:/200311000100101.tga");
  10. System.out.println(tjSDK);
  11. }
  12.     @Test
  13.     public void test03() {
  14.         // 测试方法三:通过
  15.         boolean tjSDK03 = sc.tjSDK03("/logo/200311000100103.tga", 0, 0, true);
  16.         System.out.println(tjSDK03);
  17.     } }

第四步:


然后使用javac  cn/com/plustv/SmartCard.java回车,再使用javah  cn.com.plustv.SmartCard  回车,你会发现在src下会生成一个.h的文件,如下图所示:


第五步:(编写dll文件)

          1、 打开visual Studio2015,新建一个项目,选择Win32—>win32项目,项目名称为:MyDLL5。如下图所示:


           2、 点击确定,然后点击下一步,进入应用程序设置的页面,如下图所示:在应用程序类型下选择”DLL”,在附加选项中选中”导出符号”,点击完成。如下图所示:


生成的项目的目录结构如下图所示:


          3、 在VS工程中,添加c/c++工程中外部头文件及库的基本步骤:(重要)
a、添加工程的头文件目录:工程---属性---配置属性---c/c++---常规---附加包含目录:加上头文件存放目录。(此处需加上自己用javah生成的.h文件目录和第三方提供的.h文件目录)
b、添加文件引用的lib静态库路径:工程---属性---配置属性---链接器---常规---附加库目录:加上lib文件存放目录。(此处加上第三方提供的lib文件目录)然后添加工程引用的lib文件名:工程---属性---配置属性---链接器---输入---附加依赖项:加上lib文件名。(此处加上第三方提供的lib文件名)

          4、在MyDLL7.cpp中加入以下代码:

// dllmain.cpp : 定义 DLL 应用程序的入口点。
// MyDll.cpp : 定义 DLL 应用程序的导出函数。
//
#include "jni.h"
#include "stdafx.h"
#include "cn_com_plustv_SmartCard.h"
#include "M2CCGKeyerDll.h"
#include "stdafx.h"
#include <tchar.h>
#include <iostream>
using namespace std;

#ifdef __cplusplus
extern "C" {undefined
#endif


    //方法一:
    JNIEXPORT jboolean JNICALL Java_cn_com_plustv_SmartCard_M2CLogoCgKeyerUpLoadFile
    (JNIEnv * env, jobject obj, jstring fileName)
    {undefined
        //char strText[256] = { 0 };
        //char buf[128];
        //测试
        //    MessageBox(0, (LPCWSTR)"OK", 0, 0);
        BOOL result = 0;
        jboolean jb = JNI_TRUE;
        const char* strDeviceInfo = (*env).GetStringUTFChars(fileName, &jb);
        //printf("String1 = [s]\n", strDeviceInfo);
        //执行商家提供的方法
        //sprintf_s(strText, 128, "fileName: s", strDeviceInfo);
        //MessageBox(NULL, strText, "UpLoadFile", 0);
        if (strDeviceInfo == NULL) {undefined
            return NULL;
        }
        result = M2CLogoCgKeyerUpLoadFile(strDeviceInfo);


        //释放资源
        //在使用完你所转换之后的对象之后,需要显示调用ReleaseStringUTFChars方法,
        //让JVM释放转换成UTF-8的string的对象的空间,如果不显示的调用的话,JVM中会一直保存该对象,不会被垃圾回收器回收,因此就会导致内存溢出
        env->ReleaseStringUTFChars(fileName, strDeviceInfo);
        return (jboolean)result;
    }


    //JNIEXPORT jboolean JNICALL Java_cn_com_plustv_SmartCard_M2CLogoCgKeyerSetupLogo
    //(JNIEnv *, jobject, jstring, jint, jint, jboolean);
    //M2CCGKEYER_API BOOL CALL_TYPE M2CLogoCgKeyerSetupLogo(const char *fileName, int x, int y, BOOL bEnabled);
    //方法三:jint 和 c或c++的 signed int 是等同的
    JNIEXPORT jboolean JNICALL Java_cn_com_plustv_SmartCard_M2CLogoCgKeyerSetupLogo
    (JNIEnv * env, jobject obj, jstring fileName, jint x, jint y, jboolean bEnabled)
    {undefined
        //    MessageBox(0, (LPCWSTR)"OK", 0, 0);
        BOOL result = 0;
        jboolean jb = JNI_TRUE;
        const char* strDeviceInfo = (*env).GetStringUTFChars(fileName, &jb);    
        //执行商家提供的方法
        result = M2CLogoCgKeyerSetupLogo(strDeviceInfo, x, y, bEnabled);
        //释放资源
        //在使用完你所转换之后的对象之后,需要显示调用ReleaseStringUTFChars方法,
        //让JVM释放转换成UTF-8的string的对象的空间,如果不显示的调用的话,
        //JVM中会一直保存该对象,不会被垃圾回收器回收,因此就会导致内存溢出
        (*env).ReleaseStringUTFChars(fileName, strDeviceInfo);
        return (jboolean)result;
    }

#ifdef __cplusplus
}
#endif


说明:代码具体的实现涉及到jni中的类型和vc++中类型的对应转换的操作,第三方提供的dll中的函数参数是c/c++中的类型,而通过java方法传进来的参数通过jni的处理转变为java和c/c++之间的一种过渡类型,比如jstring等,此时,就需要我们调用jni中的对应方法来转换该类型,具体需参照jni文档。

第六步:(生成dll文件)

如下图所示,在解决方案配置中选择”Dubug”,点击”启动调试”按钮,在这里我选择32位,最好跟第三方用的操作系统保持一致。


这时,就会在工程下的Dubug文件夹下生成MyDLL5.dll。我的是在:C:\Users\java\Documents\Visual Studio2015\Projects\MyDLL5\Debug路径下。注:在解决方案配置中如果选择Release,则会在工程下的Release文件夹下生成MyDLL5.dll

第七步:(测试)

将dll文件放到java项目中将生成的MyDLL5.dll和商家提供的M2CCGKeyer.dll文件拷贝到项目的目录下,如下图:


说明:在我的项目中是通过网络连接第三方那个设备,所以我需要将netconfig.ini(里面是一个ip地址)文件放在自己的jre的bin目录下。

           最后运行测试方法会在控制台打印一个true.


我不能保证写的每个地方都是对的,但是至少是我仔细思考过的,希望大家多多指教,面对压力,我可以挑灯夜战、不眠不休;面对困难,我愿意迎难而上、永不退缩。


免责声明:
      1、 资源售价只是赞助,不代表代码或者素材本身价格。收取费用仅维持本站的日常运营所需。
      2、 本站资源来自用户上传,仅供用户学习使用,不得用于商业或者非法用途,违反国家法律一切后果用户自负。用于商业用途,请购买正版授权合法使用。
      3、 本站资源不保证其完整性和安全性,下载后自行检测安全,在使用过程中出现的任何问题均与本站无关,本站不承担任何技术及版权问题,不对任何资源负法律责任。
      4、 如有损害你的权益,请联系275551777@qq.com及时删除。

关于我们 | 积分获取 | 联系我们 | 用户协议 | 标签搜索 | 网站地图.html | 网站地图.xml | 网站地图.txt

Copyright © 2021-2023 All Right Reserved
陕公网安备 61082202000148号      陕ICP备2025078528号-1
js模板网 -陕西千手码农科技有限责任公司