java中怎样调用现有的dll文件

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java中怎样调用现有的dll文件相关的知识,希望对你有一定的参考价值。

使用jni调用
具体如下:
JAVA通过JNI调用本地方法,而本地方法是以库文件的形式存放的(在WINDOWS平台上是DLL文件形式,在UNIX机器上是SO文件形式)。通过调用本地的库文件的内部方法,使JAVA可以实现和本地机器的紧密联系,调用系统级的各接口方法。

简单介绍及应用如下:

一、JAVA中所需要做的工作

在JAVA程序中,首先需要在类中声明所调用的库名称,如下:

static

System.loadLibrary(“goodluck”);



在这里,库的扩展名字可以不用写出来,究竟是DLL还是SO,由系统自己判断。

还需要对将要调用的方法做本地声明,关键字为native。并且只需要声明,而不需要具体实现。如下:

public native static void set(int i);

public native static int get();

然后编译该JAVA程序文件,生成CLASS,再用JAVAH命令,JNI就会生成C/C++的头文件。

例如程序testdll.java,内容为:

public class testdll



static



System.loadLibrary("goodluck");



public native static int get();

public native static void set(int i);

public static void main(String[] args)



testdll test = new testdll();

test.set(10);

System.out.println(test.get());





用javac testdll.java编译它,会生成testdll.class。

再用javah testdll,则会在当前目录下生成testdll.h文件,这个文件需要被C/C++程序调用来生成所需的库文件。

二、C/C++中所需要做的工作

对于已生成的.h头文件,C/C++所需要做的,就是把它的各个方法具体的实现。然后编译连接成库文件即可。再把库文件拷贝到JAVA程序的路径下面,就可以用JAVA调用C/C++所实现的功能了。

接上例子。我们先看一下testdll.h文件的内容:

/* DO NOT EDIT THIS FILE - it is machine generated */

#include <jni.h>

/* Header for class testdll */

#ifndef _Included_testdll

#define _Included_testdll

#ifdef __cplusplus

extern "C"

#endif

/*

* Class: testdll

* Method: get

* Signature: ()I

*/

JNIEXPORT jint JNICALL Java_testdll_get

(JNIEnv *, jclass);

/*

* Class: testdll

* Method: set

* Signature: (I)V

*/

JNIEXPORT void JNICALL Java_testdll_set

(JNIEnv *, jclass, jint);

#ifdef __cplusplus



#endif

#endif

在具体实现的时候,我们只关心两个函数原型

JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass);



JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint);

这里JNIEXPORT和JNICALL都是JNI的关键字,表示此函数是要被JNI调用的。而jint是以JNI为中介使JAVA的int类型与本地的int沟通的一种类型,我们可以视而不见,就当做int使用。函数的名称是JAVA_再加上java程序的package路径再加函数名组成的。参数中,我们也只需要关心在JAVA程序中存在的参数,至于JNIEnv*和jclass我们一般没有必要去碰它。

好,下面我们用testdll.cpp文件具体实现这两个函数:

#include "testdll.h"

int i = 0;

JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass)



return i;



JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint j)



i = j;



编译连接成库文件,本例是在WINDOWS下做的,生成的是DLL文件。并且名称要与JAVA中需要调用的一致,这里就是goodluck.dll

把goodluck.dll拷贝到testdll.class的目录下,java testdll运行它,就可以观察到结果了。追问

dll 文件是人家给我的啊,现在已经有一个了,我还需要再生成dll文件吗?

追答

dll文件如果不是通过jni生成的头文件的话,用java很难直接调用,需要重新为java编译一个新的dll

参考技术A 不太明白你的意思,是不是在Java里面调用C++写的DLL?
如果那个DLL不是专门为Java调用而编写的话,就需要用JNI再写一个DLL,在那里面调用你原有的DLL。
本回答被提问者采纳
参考技术B 当然不用重新生成.dll文件了,直接在java文件中声明并调用就可以了。
当然了,下面的这个工作还是要做的:

在JAVA程序中,首先需要在类中声明所调用的库名称,如下:
static

System.loadLibrary(“goodluck”);
追问

这样怎么调用啊,需要声明未实现的native方法吗?
当我师父好不!我拜师!!+QQ654180503

Unity与 DLL文件 ☀️| 怎样使用VC++生成一个DLL文件并调用!(包括 在VS 中调用 和 在Unity中调用)


📢前言

  • 前一篇博客讲了一下DLL的基本概念,链接在这:Unity与 DLL文件 ☀️| 什么是DLL✨?
  • 还讲了怎样通过 C# 类库 生成一个DLL文件并调用
  • 在上一篇文章中也说了,生成DLL文件的方式有很多种,还有一个是通过VC C++来生成
  • 那本篇文章就对怎样通过VC C++ 生成一个DLL文件做一个概述
  • 生成之后有两种调用方式,分别是在VS中调用在Unity中调用,本篇文章都会提到!
  • 一起来看一下怎样生成一个简单的DLL并进行调用吧!
  • 本篇文章使用的是VS2017!不同版本可能会有差异,敬请理解!

🎬通过VC 生成DLL文件

这里再来简单看一下DLL的定义,方便理解

动态链接库(英语:Dynamic-link library,缩写为DLL)是微软公司在微软视窗操作系统中实现共享函数库概念的一种实现方式。这些库函数的扩展名是.DLL、.OCX(包含ActiveX控制的库)或者.DRV(旧式的系统驱动程序)。所谓动态链接,就是把一些经常会共用的代码(静态链接的OBJ程序库)制作成DLL档,当可执行文件调用到DLL档内的函数时,Windows操作系统才会把DLL档加载存储器内,DLL档本身的结构就是可执行档,当程序有需求时函数才进行链接。透过动态链接方式,存储器浪费的情形将可大幅降低。静态链接库则是直接链接到可执行文件。DLL的文件格式与视窗EXE文件一样——也就是说,等同于32位视窗的可移植执行文件(PE)和16位视窗的New
Executable(NE)。作为EXE格式,DLL可以包括源代码、数据和资源的多种组合。
————维基百科

🎥在VS中生成DLL文件

🏳️‍🌈第一步:新建一个dll项目

打开我们的VS2017文件 -> 新建 -> 项目


然后找到这个VC++ 里面的 动态链接库(DLL),改好名称和路径,然后点击确定!

(别的文章可能新建项目时 和这里我写的不一样,那可能是VS版本的问题)

🏳️‍🌈第二步:新建一个.h头文件.cpp源文件

第一步确定并等待VS新建项目完成之后,我们还需要手动新建两个文件

右键这个头文件添加 -> 新建项,如下所示

如果没找到这个图中右边这个解决方案资源管理器,那就点击 菜单栏的视图 -> 解决方案资源管理器 ,就可以调出来了!

选择头文件,改个名称路径,点击添加

然后同样的方法 在解决方案管理器 右键源文件 -> 添加 ->新建项

然后这次选择.cpp文件,改个名称路径,点击添加

🏳️‍🌈第三步:在.h头文件.cpp源文件中编写代码

这里代码是C++语言,就简单写个方法进行调用测试即可!

firstDLLTest.cpp代码

#include "pch.h"
//加载头文件
#include "firstDLLTest.h"

int firstTest(int i, int(*call_back)(int a, int b))
{
	int aa;
	aa = i * i;
	call_back(i, aa);
	return 0;
}

firstDLLTest.h代码:

__declspec(dllexport) int firstTest(int i, int(*call_back)(int a, int b));

🏳️‍🌈第四步:生成dll和lib文件

.h和.cpp代码编写完毕之后,生成 -> 重新生成解决方案,如下图所示

然后我们到这个项目的路径的Debug文件夹下就可以找到生成的dll和lib文件了!

这样的话对应的DLL文件就算是生成了!!


🎥在VS中进行调用DLL文件

现在我们已经拿到刚才的项目生成的dll文件了,所以新建一个项目来进行调用测试!

🚩第一步:先来新建一个项目

文件 -> 新建 -> 项目,这次是新建一个控制台应用,如下图,别搞错了!

然后改个名字和路径点击添加即可

🚩第二步:复制firstDLLTest.dll和firstDLLTest.lib文件和上一个项目的头文件firstDLLTest.h

将刚才生成的firstDLLTest.dll和firstDLLTest.lib文件,还有上一个项目的头文件firstDLLTest.h,全复制到当前项目的文件夹下
复制dll和lib文件

复制.h头文件

🚩第三步:在新项目里面添加C++代码

将上一步的三个文件都复制到当前项目后,开始写代码进行调用,如下

#include <stdio.h>
#include "firstDLLTest.h"
int firstTest_call_back(int a, int b)
{
	int c;
	c = a + b;
	printf("输出:%d\\n", c);
	return 11;
}
void main()
{
	int p = 10;
	int test;
	test = firstTest(p, firstTest_call_back);
	printf("输出2:%d\\n", test);
}

🚩第四步:添加头文件firstDLLTest.h和firstDLLTest.lib文件

将这两个文件添加到当前项目

添加完之后,效果如下图所示

🚩第五步:点击重新生成解决方案

上述操作都做完了之后点击重新生成解决方案,然后运行项目即可!

运行效果如下:

这个110是我们在main方法中将p的值传给了DLL文件中的方法firstTset,在firstTest方法中进行了相乘操作

使我们调用firstTest_call_back方法时,a和b的值变成了10和100,所以在方法中相加输出了110

test则直接返回了firstTest中的0

好了,这就是一个完整的生成DLL文件并在VS中进行调用的方法!


🎥在Unity中调用这个DLL文件

上面讲的是在VS中直接调用生成的这个DLL文件,那接下来就讲一下怎样生成一个DLL文件给Unity进行调用

两种方法其实相差不大,就是对应的代码会有些差别,那我还是从头将所有过程都写一下方便学习!

🏁第一步:新建一个项目

文件 -> 新建 -> 项目,简单改个名字路径即可

🏁第二步:新建一个.h头文件和.cpp源文件

这一步其实跟第一种方法都是一样的,简单说一下!



Dll2.h代码

#ifndef __NativeCode_H__
#define __NativeCode_H__

#ifndef EXPORT_DLL
#define EXPORT_DLL __declspec(dllexport) //导出dll声明
#endif

extern "C"
{
	EXPORT_DLL int MyAddFunc(int _a, int _b);
}
#endif

Dll2.cpp代码

#include "pch.h"
#include "Dll2.h"

#define _DLLExport extern "C" _declspec(dllexport)

_DLLExport int MyAddFunc(int _a, int _b)
	{
		return _a + _b;
	}


extern “C”:指定c编译器编译

🏁第三步:生成DLL文件

需要注意的只有一个地方,就是下图中这里要改成x64,最好前边也改成Release

然后生成即可

然后我们就可以在这个项目的文件夹下找到对应生成的x86的DLL文件

🏁第四步:新建一个Unity工程,并新建一个文件夹Plugins

我们新建一个Unity工程后,在Assets下新建一个Plugins文件夹

然后将上面生成的DLL文件放到这个文件夹下!

🏁第五步:新建一个脚本写代码调用DLL文件

新建一个脚本,脚本内容如下:

using UnityEngine;
using System.Runtime.InteropServices; //调用c++中dll文件需要引入

public class Test : MonoBehaviour
{
    [DllImport("Dll2")]
    static extern int MyAddFunc(int a, int b);

    void Start()
    {
        int i = MyAddFunc(10, 20);
        Debug.Log("数值:" + i);

    }
}

这里再简单说一下,在Unity中调用DLL文件和so都是一样的方法

代码中的[DllImport("DLLName")]是调用 DLL文件so文件 的 固定调用方法,前边调用so文件的时候也提到过!

🏁第六步:将脚本挂载到场景中一个物体上

将这个脚本挂载到场景中一个物体上,然后启动运行Unity

打印结果如下,成功调用了DLL文件中的方法


👥总结

本文对如何生成一个DLL文件在 VS 和 Unity中 进行调用

分别将全过程介绍出来了,整体而言并不是很难

因为我们的C++代码写的很简单,但那是在真正的项目中就是会麻烦很多了

但是我们只要学会了这个方法,那一切都可以融会贯通了!

那本篇文章就到此结束了,如果觉得文章有用就给一波点赞收藏关注吧!谢谢啦~


🚀往期优质文章分享


🚀 优质专栏分享 🚀
  • 🎄如果感觉文章看完了不过瘾,可以来我的其他 专栏 看一下哦~
  • 🎄比如以下几个专栏:Unity基础知识学习专栏Unity游戏制作专栏Unity实战类项目 算法学习专栏
  • 🎄可以学习更多的关于Unity引擎的相关内容哦!直接点击下面颜色字体就可以跳转啦!
🎄 Unity基础知识学习专栏 🎄
⭐️ Unity游戏制作专栏 ⭐️
🍇 Unity实战类项目 🍇
💦 小Y学算法 💦

以上是关于java中怎样调用现有的dll文件的主要内容,如果未能解决你的问题,请参考以下文章

java怎样调用dll动态库实现打印。

怎样查看一个dll文件的调用方法

c#编程添加引用dll文件后怎样调用

关于delphi中动态调用dll时出现的问题

怎样知道某个应用程序调用哪些dll文件?

Java如何将dll文件打包到jar中?