JNA学习(一)C++ 类库(Dll)创建及调用


前言

最近在刚好碰到了在跨平台下调用代码的需求,特别是Java下调用C++的的核心代码,是比较常见的一种情况。在不断的摸索下,目前发现想实现上诉功能发手段主要有:JNI、JNA和JNR三种。

本文以最为简单的JNA入手,记录从C++类库的生成到Java下成功调用的整个过程。笔者本身主要以 C++ 的开发为主,以下过程也主要以 C 开发者的角度展开。


一、JNA简介

JNA (Java native access) 在 JNI(Java native interface) 的基础上,提供了从 Java 到 C++ 下函数接口的动态映射,从而简化了对本地共享库调用过程。

二、环境准备

1、软件环境

  • Visual Studio 2022 Community
  • IntelliJ IDEA Community Edition 2023.1
  • JDK-8u333
  • Maven 3.6.3

2、引入库

主要是对 JNA Jar包的导入。
新建 Maven工程(配置不在此处赘述,详见参考文献),在 “pom.xml” 中添加依赖项 com.sun.jna ,这里用的是较旧的 3.0.9 版本。

    <dependencies>
        <dependency>
            <groupId>com.sun.jna</groupId>
            <artifactId>jna</artifactId>
            <version>3.0.9</version>
        </dependency>
    </dependencies>

编译结束后,如本地环境中生成了我们所需的依赖库,说明库引入成功。

二、C++ 生成标准动态库(.dll)

如果只是 C++ 下动态库的生成其实很简单,这里详细记录一点。
首先在VS2022中创建新项目,选择 动态链接库(Dll) ,名称为 CTest
在这里插入图片描述
新建完成后,向项目中再添加新的3个代码文件,分别命名为:

  • CTESTInterface.h
  • CTESTImpl.h
  • CTESTImpl.cpp

CTESTInterface 负责定义对外公开的类型及函数接口,CTESTImpl 为对函数接口的具体实现。

CTESTInterface.h 通过宏定义需要导出的函数接口。

#define CTEST_API extern "C" __declspec(dllexport)

extern “C” 关键字用于确保在编译过程中函数名不发生改变。
同时定义用于测试的函数接口:求一个数组中的最大值。

CTEST_API int CTEST_Max(int vec[], int size);

CTESTImpl.cpp 实现已定义的函数接口。

#include "CTESTInterface.h"
#include "CTESTImpl.h"

int CTEST_Max(int vec[], int size)
{
	int maxVal = 0;
	if (size > 1)
	{
		vec[0] = -10;
		maxVal = vec[0];
	}
	for (int i = 0; i < size; i++)
	{
		if (vec[i] > maxVal)
		{
			maxVal = vec[i];
		}
	}

	return maxVal;
}

此时对工程进行编译,在 Debug 目录下,出现了三个编译后文件:CTest.dll , CTest.lib, CTest.exp ,说明简单的一个动态库已经构建完成。
其中 .dll 是包含实际的函数实现,.lib 用于编译过程中对 .dll 中的函数进行定位,.exp 除非相互链接,一般用不上。

三、C++下动态库调用

同解决方案下新建一个名为 TestConsoleApp 控制台应用,对上文的动态库进行测试。
TestConsoleApp 工程上右键->属性->连接器->输入->附加依赖项,编辑后添加一个新的库引用。

..\x64\Debug\CTest.lib

这里需要确保两个项目的输出目录保持一致,我这里都在 x64下的Debug目录下。

在这里插入图片描述

TestConsoleApp.cpp 中添加如下代码:

#include <iostream>
#include "..\CTest\CTESTInterface.h"

int main()
{
	std::cout << "Hello World!\n";

	//测试封装库内函数
	int nums [] = {1,2,3,4,5};
	int max = CTEST_Max(nums, 5);
	//输出
	std::cout << "最大值为:" << max << "\n";

	char wait;
	std::cin >> wait;

	return 0;
}

运行后输出为:

Hello World!
最大值为:5

总结

  • __declspec(dllexport) 定义导出函数接口
  • .lib 文件为编译过程中使用,编译完成后,运行仅需要将对应的 .dll 文件放入运行目录下
  • 对库内函数的调用也可以使用隐式的方式(不需要 Interface.h
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值