2017-08-23 08:27:35 zhanghui_new 阅读数 3030
  • VC++动态链接库(dll)编程视频教学

    动态链接库的开发编译属于VC++程序员技能。 本课程学习之后能够理解动态链接库原理,学会编译静态库、动态库,学会通过lib和头文件链接动态库,学会直接通过代码访问dll中函数

    10116 人正在学习 去看看 夏曹俊

Java_JNI调用C/C++代码

JNI,是Java Native Interface的简称,中文是“Java本地调用”。通过这种技术可以做到以下两点:

  • Java程序中的函数可以调用Native语言写的函数,Native一般指的是C/C++编写的函数。
  • Native程序中的函数可以调用Java层的函数,也就是说在C/C++程序中可以调用Java的函数。

JNI并不是什么特别神奇的东西,当初SUN推出它的目的是为了屏蔽不同操作系统平台的差异性,通过Java语言来调用Native语言的功能模块,避免重复制作车轮,最主要是这两个目的。
主要步骤如下:

  • 首先在Java类中声明一个native的方法
  • 使用Javah命令生成native方法的声明的C/C++头文件
  • 按照生成的C/C++头文件来编写C/C++源文件
  • 将C/C++源文件编译成动态链接库(DLL)
  • 将DLL文件加入到PATH环境变量下

在eclipse中创建一个Java项目

这里写图片描述

创建了一个命为:JNI的项目,新建包名为bingcao,新建类为TestJNI
接着在TestJNI类当中声明我们的本地方法:

package bingcao;

/**
 * @author troy
 *         2017-08-22  下午19:28
 *
 */
public class TestJNI {
    // 声明本地方法
    public native double nativeMethod();

    public static void main(String[] args) {

        /*long startTime = System.currentTimeMillis(); // 获取开始时间
        // // 加载动态链接库
        System.load("D:/documents/visual studio 2013/Projects/nativeDLL/x64/Debug/nativeDLL.dll");

        TestJNI nativeCode = new TestJNI();
        double result = nativeCode.nativeMethod();
        System.out.println(result);
        System.out.println("JNI成功调用dll!!!");

        long endTime = System.currentTimeMillis(); // 获取结束时间

        System.out.println("程序运行时间: " + (endTime - startTime) + "ms");*/
    }
}

/* ……*/ 内注释掉的代码后面很快会用到,暂时不用管。

用jdk中javah命令来为我们生成对应的头文件,在命令可以敲入javah -help:

这里写图片描述

格式为:javah 包名.文件名

成功运行后,在当前路径下生成的.h文件:
这里写图片描述

javah命令生成native头文件。编辑器打开头文件,有以下代码:

接着在Visual studio中创建一个win32控制台应用程序,取名为nativeDLL

最后在Eclipse中使用Java调用我们的Native代码:

package bingcao;

/**
 * @author troy
 *         2017-08-22  下午19:28
 *
 */
public class TestJNI {
    // 声明本地方法
    public native double nativeMethod();

    public static void main(String[] args) {

        long startTime = System.currentTimeMillis(); // 获取开始时间
        // // 加载动态链接库
        System.load("D:/documents/visual studio 2013/Projects/nativeDLL/x64/Debug/nativeDLL.dll");

        TestJNI nativeCode = new TestJNI();
        double result = nativeCode.nativeMethod();
        System.out.println(result);
        System.out.println("JNI成功调用dll!!!");

        long endTime = System.currentTimeMillis(); // 获取结束时间

        System.out.println("程序运行时间: " + (endTime - startTime) + "ms");
    }
}

运行,调用成功
这里写图片描述

Java_JNA调用DLL

JNA(Java Native Access)框架是一个开源的Java框架,是SUN公司主导开发的,建立在经典的JNI的基础之上的一个框架。

你只需要下载一个jar包,就可以使用JNA的强大功能方便地调用动态链接库中的C函数。

1,下载jna.jar: jna.jar的下载地址

2,在Java项目中引入jna.jar包;

这里写图片描述

3,创建一个类;

package bingcao;

import com.sun.jna.*;

/**
 * @author troy
 *         2017-08-22  下午19:28
 *
 */
public class TestJNA {

    public interface nativeDLL extends Library {

        ///当前路径是在项目下,而不是bin输出目录下。
        nativeDLL INSTANCE = (nativeDLL) Native
                .loadLibrary(
                        "D:/documents/visual studio 2013/Projects/nativeDLL/x64/Debug/nativeDLL",
                        nativeDLL.class);

        public double Java_bingcao_TestJNI_nativeMethod();
    }

    public static void main(String[] args) {

        // TODO Auto-generated method stub
        long startTime = System.currentTimeMillis(); // 获取开始时间
        double result = nativeDLL.INSTANCE.Java_bingcao_TestJNI_nativeMethod();
        System.out.println(result);
        System.out.println("JNA成功调用dll!!!");
        long endTime = System.currentTimeMillis(); // 获取结束时间
        System.out.println("程序运行时间: " + (endTime - startTime) + "ms");

    }

}

4,加载上面生成的DLL,运行结果如下:

这里写图片描述

2011-01-20 22:00:00 archfree 阅读数 1096
  • VC++动态链接库(dll)编程视频教学

    动态链接库的开发编译属于VC++程序员技能。 本课程学习之后能够理解动态链接库原理,学会编译静态库、动态库,学会通过lib和头文件链接动态库,学会直接通过代码访问dll中函数

    10116 人正在学习 去看看 夏曹俊

Java中Java Native Interface的使用方法介绍

   JNI是Java Native Interface的缩写,中文为JAVA本地调用。从Java 1.1 开始,Java Native Interface (JNI)标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用其他语言,只要调用约定受支持就可以了。

JNI是Java Native Interface的缩写,中文为JAVA本地调用。从Java 1.1 开始,Java Native Interface (JNI)标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用其他语言,只要调用约定受支持就可以了。

使用java与本地已编译的代码交互,通常会丧失平台可移植性。但是,有些情况下这样做是可以接受的,甚至是必须的,比如,使用一些旧的库,与硬件、操作系统进行交互,或者为了提高程序的性能。JNI标准至少保证本地代码能工作在任何Java 虚拟机实现下。

 

编写带有native声明的方法的java类

·使用javac命令编译所编写的java类

·使用javah -jni java类名生成扩展名为h的头文件

·使用C/C++实现本地方法

·将C/C++编写的文件生成动态连接库

·ok

1) 编写java程序:这里以HelloWorld为例。

代码1:

class HelloWorld {
public native void displayHelloWorld();
static {
System.loadLibrary("hello");
}
public static void main(String[] args) {
new HelloWorld().displayHelloWorld();
}
}

声明native方法:如果你想将一个方法做为一个本地方法的话,那么你就必须声明改方法为 native的,并且不能实现。其中方法的参数和返回值在后面讲述。 Load动态库:System.loadLibrary("hello");加载动态库(我们可以这样理解:我们的方法 displayHelloWorld()没有实现,但是我们在下面就直接使用了,所以必须在使用之前对它进行初始化)这里一般是以static块进行加载的。同时需要注意的是System.loadLibrary();的参数“hello”是动态库的名字。

2)编译

没有什么好说的了 javac HelloWorld.java

3)生成扩展名为h的头文件

javah -jni HelloWorld

头文件的内容:

     /* DO NOT EDIT THIS FILE - it is machine generated */
1. include
/* Header for class HelloWorld */
1. ifndef _Included_HelloWorld 2. define _Included_HelloWorld 3. ifdef __cplusplus
extern "C" {
1. endif
/*
* Class: HelloWorld
* Method: displayHelloWorld
* Signature: ()V
* /
JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld (JNIEnv *, jobject);
1. ifdef __cplusplus
}

1. endif 2. endif(这里我们可以这样理解:这个h文件相当于我们在java里面的接口,这里声明了一个 Java_HelloWorld_displayHelloWorld (JNIEnv *, jobject);方法,然后在我们的本地方法里面实现这个方法,也就是说我们在编写C/C++程序的时候所使用的方法名必须和这里的一致)。

4) 编写本地方法实现和由javah命令生成的头文件里面声明的方法名相同的方法。

代码2:

1 #include "jni.h" 2 #include "HelloWorld.h"
3 //#include other headers
4 JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld(JNIEnv *env, jobject obj)
{
printf("Hello world!/n");
return;
}

注意代码2中的第1行,需要将jni.h(该文件可以在%JAVA_HOME%/include文件夹下面找到)文件引入,因为在程序中的JNIEnv、 jobject等类型都是在该头文件中定义的;另外在第2行需要将HelloWorld.h头文件引入(我是这么理解的:相当于我们在编写java程序的时候,实现一个接口的话需要声明才可以,这里就是将HelloWorld.h头文件里面声明的方法加以实现。当然不一定是这样)。然后保存为 HelloWorldImp.c就ok了。

5)生成动态库

这里以在Windows中为例,需要生成dll文件。在保存HelloWorldImpl.c 文件夹下面,使用VC的编译器cl成。 cl(字母L的小写表示) -I(字母i的大写表示,与后面的路径之间没有空格)%java_home%/include -I%java_home%/include/win32 -LD HelloWorldImp.c -Fehello.dll 注意:生成的dll文件名在选项-Fe后面配置,这里是hello,因为在HelloWorld.java文件中我们loadLibary的时候使用的名字是hello。当然这里修改之后那里也需要修改。另外需要将-I%java_home%/include -I%java_home%/include/win32参数加上,因为在第四步里面编写本地方法的时候引入了jni.h文件。

6) 运行程序 java HelloWorld就ok.、

2011-01-11 18:05:00 ppl2046 阅读数 1459
  • VC++动态链接库(dll)编程视频教学

    动态链接库的开发编译属于VC++程序员技能。 本课程学习之后能够理解动态链接库原理,学会编译静态库、动态库,学会通过lib和头文件链接动态库,学会直接通过代码访问dll中函数

    10116 人正在学习 去看看 夏曹俊

    前些日子,就在两天前,由于公司业务上的需求,需要用Java调用另外一Delphi公司编写的代码,然后再用WebService做相对应的数据交互。当时,彼公司提供了一套测试代码,当然是delphi的代码和一套DLL, 另附DOC接口文档一套。由于公司内部没有Delphi的编程经验,只能写相关的java代码来调用彼公司提供的DLL。

    而Java调用DLL有两种方法, 一种就是JNI,Java Native Interface,另外一种就是JNA,Java Native Access。这两种调用方法前一个是JAVA内置支持的,但对DLL的编写有一定的约束,也就是说如果你先写java代码,然后用相关的约束再编写DLL是可行的。另一种情况就是我公司碰到的情况,两个毫无业务来往的公司写的程序,突然之间需要产生调用关系,也就是说DLL的编写是没有任何约束的,这样使用JNI就显得相当困难,除非两个公司能够很好的合作,否则调用将异常困难。当然解决方法就是采用JNA,但JAVA本身并不支持JNA,需要第三方类库的支持,也就是JNA.JAR,这个类库可以在java.net上找到该开源工程的主页,里面有对应的文档和示例代码。

    但不管是JNI还是JNA,其与DLL交互的原理都是通过计算机系统的底层来实现的。拿windows来说,java与dll的交互是通过windows的com组件来交互的,也就是说com是中间的接口。那么java调用DLL的最基本的约束就出来了:

    java调用DLL时,如果涉及到参数传递时,那么参数的类型必须在com中有相关的对应关系,否则不可能产生调用关系(Type Mapping可以参考http://www.dynamsoft.com/help/TWAIN/Guide_DataMapping.htm)。

    拿DLL中的结构体来说,C、C++中都是用struct来声明,Delphi中是用record来声明,如果你调用一个带有结构体的参数的方法,那么在DLL的源码中,如果你直接将结构体做为参数传入涵数里面,那么这个结构体在COM中是没有对应的数据类型的,调用将不可能成功。你所需要做的是将这个结构体的引用或指针做为参数传入,这时这个参数也就是一个地址,一个十六进制对应的数字,这样一来调用就不会存在问题。

例如,拿Delphi的代码来说:

 

 

这时copyw这个函数将不可能被JAVA调用,你需要将每一个参数的数据类型改为指针PTman或者引用@Tman,这样才能产生正确的调用。

 

以上就是这次技术碰撞我所体会到的,写出来供大家分享一下,请多多指教。

 

2017-03-01 22:21:19 SkyeBeFreeman 阅读数 426
  • VC++动态链接库(dll)编程视频教学

    动态链接库的开发编译属于VC++程序员技能。 本课程学习之后能够理解动态链接库原理,学会编译静态库、动态库,学会通过lib和头文件链接动态库,学会直接通过代码访问dll中函数

    10116 人正在学习 去看看 夏曹俊

什么是Native方法?

Native方法是Java程序与C程序的接口,能够实现Java程序调用C代码,提升Java程序的性能。


前提条件:

1. Java环境配置完成(百度一大堆请自行搜索)

2. 把C:\Program Files\Java\jdk1.8.0_91\include中的jni.h和C:\Program Files\Java\jdk1.8.0_91\include\win32中的jni_md.h一起复制到D:\Microsoft Visual Studio 14.0\VC\include目录中。(不然编译DLL的时候会找不到相关文件)



正文:

1. 编写Java程序文件,注意需要把要实现的Native方法的关键字加入native字段。同时,在静态初始化块中确定将来要链接的DLL文件的名字。最后在main方法调用我们将要实现的Native方法来验证程序的正确。

class HelloWorld {
    public native void printHelloWorld();

    {
        System.loadLibrary("helloDLL");
    }

    public static void main(String[] args) {
        new HelloWorld().printHelloWorld();
    }

}

2. 编译Java代码,javac生成.class文件,javah生成.h文件。


.h文件类似这样:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloWorld */

#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     HelloWorld
 * Method:    printHelloWorld
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_HelloWorld_printHelloWorld
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif


3. 使用VS 2015生成DLL文件。

(1)新建Win32项目。



(2)选择DLL后点击完成。



(3)把之前生成的HelloWorld.h添加进项目中,修改HelloWorld.cpp为实现.h文件中的函数,这个函数也就是Native方法c语言的实现

#include "stdafx.h"

#include <iostream>
#include "HelloWorld.h"

JNIEXPORT void JNICALL Java_HelloWorld_printHelloWorld(JNIEnv *, jobject) {
    std::cout << "HelloWorld!" << std::endl;
    return;
}


(4)将生成的参数调至“Release”和“x64”(主要看个人的机子来决定是x64还是x86,64位的就选x64咯),然后编译。


生成一个错误弹框可以无视,点击确定。



(5)在C:\Users\92801\Desktop\helloworld\HelloWorld\x64\Release中把复制到一开始HelloWorld.java的目录中并改名为“helloDLL”(一开始约定好的,见第一点)。命令行运行,即可看到输出的“HelloWorld!”




2019-07-11 19:11:14 skytering 阅读数 15
  • VC++动态链接库(dll)编程视频教学

    动态链接库的开发编译属于VC++程序员技能。 本课程学习之后能够理解动态链接库原理,学会编译静态库、动态库,学会通过lib和头文件链接动态库,学会直接通过代码访问dll中函数

    10116 人正在学习 去看看 夏曹俊

1.Native关键字

native关键字表示声明的方法不是用Java语言实现,而是用C/C++语言实现的,其被编译成了动态链接库DLL,通过调用DLL来实际完成,即:JNI,java native interface;

2.构建JNI步骤

2.1.建立JNI工具类

package com.test; 
public class MyLib { 
	public static native void nativeDoSomething();
 
}

2.2. 编译工具类

1、编译类文件
javac MyLib.java

2、javah 生成实现本地方法所需的 C 头文件
javah -classpath E:\workspace_eclipse\ht002\src\main\java -jni com.test.MyLib
将生成com_test_MyLib.h 头文件

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_test_MyLib */

#ifndef _Included_com_test_MyLib
#define _Included_com_test_MyLib
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_test_MyLib
 * Method:    nativeDoSomething
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_test_MyLib_nativeDoSomething
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

2.3.C++实现DLL(VS2017)

2.3.1.创建动态链接库项目

在这里插入图片描述

2.3.2.加入相关头文件

jni.h(com_test_MyLib.h中需要使用,位于jre/jdk的安装目录下include目录下)
jni_md.h(jni.h中使用,,位于jre/jdk的安装目录下include/win32目录下)
com_test_MyLib.h
在这里插入图片描述

2.3.3.实现函数体

myNativeLib.cpp文件中实现

#include "stdafx.h"
#include "com_test_MyLib.h"
#include <iostream>
using namespace std;

JNIEXPORT void JNICALL Java_com_test_MyLib_nativeDoSomething
(JNIEnv *, jclass)
{
	cout << "start to dosomething" << endl;
	cout << "~~~~~~~~~" << endl;
	cout << ">>  dosomething finished " << endl;
}

2.3.4.生成

选平台版本,这里x64(因为jre安装的是64位版本)
在这里插入图片描述

1>myNativeLib.cpp
1>正在生成代码...
1>  正在创建库 E:\workspace_vs2017\myNativeLib\x64\Debug\myNativeLib.lib 和对象 E:\workspace_vs2017\myNativeLib\x64\Debug\myNativeLib.exp
1>myNativeLib.vcxproj -> E:\workspace_vs2017\myNativeLib\x64\Debug\myNativeLib.dll
========== 生成: 成功 1 个,失败 0 个,最新 0 个,跳过 0 个 ==========

在项目目录下x64\Debug目录中生产了动态链接库myNativeLib.dll
将其拷贝到某一个目录,如E:\jni目录中。

2.4.Java调用native方法

编写测试类

package com.test;

public class TestNative {
	  
	public static void main(String [] args){
		System.load("E:\\jni\\myNativeLib.dll");

		MyLib.nativeDoSomething();
	}
}

运行结果

start to dosomething
~~~~~~~~~
>>  dosomething finished 

正是对应C++代码语句实现的效果

	cout << "start to dosomething" << endl;
	cout << "~~~~~~~~~" << endl;
	cout << ">>  dosomething finished " << endl;

java native

阅读数 1183

java native 调dll

阅读数 3

java native关键字

阅读数 25238

java native

阅读数 101

没有更多推荐了,返回首页