• JNI学习


    最近需要用到JNI,所以抽时间学习了下,对于我这个N年没用过C/C++的,从没用过VS2005的java码农来说,真不容易,编译个dll都遇到莫名其妙的问题~~

    下面就来一步一步开始JNI之路。

    一、通过java类得到.h头文件

    首先,我们写一个java类,声明几个native方法

    package jni.test;
    
    public class JNIWrapper {
    
        public native void display();
    
        public native double sum(double x, double y);
        
        public native double divide(double x, double y);
    }

    然后,依次执行如下命令,依次得到class和.h文件

    编译class
    ...\src>javac jni\test\JNIWrapper.java
    
    生成头文件
    ...\src>javah jni.test.JNIWrapper

    到这里就得到了一个名为“jni_test_JNIWrapper.h”的头文件,其内容如下:

    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class jni_test_JNIWrapper */
    
    #ifndef _Included_jni_test_JNIWrapper
    #define _Included_jni_test_JNIWrapper
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     jni_test_JNIWrapper
     * Method:    display
     * Signature: ()V
     */
    JNIEXPORT void JNICALL Java_jni_test_JNIWrapper_display
      (JNIEnv *, jobject);
    
    /*
     * Class:     jni_test_JNIWrapper
     * Method:    sum
     * Signature: (DD)D
     */
    JNIEXPORT jdouble JNICALL Java_jni_test_JNIWrapper_sum
      (JNIEnv *, jobject, jdouble, jdouble);
    
    /*
     * Class:     jni_test_JNIWrapper
     * Method:    divide
     * Signature: (DD)D
     */
    JNIEXPORT jdouble JNICALL Java_jni_test_JNIWrapper_divide
      (JNIEnv *, jobject, jdouble, jdouble);
    
    #ifdef __cplusplus
    }
    #endif
    #endif
    jni_test_JNIWrapper.h

    经过转换之后,方法名、变量类型什么的都变了,不过都挺有规律的:Java_包名+类名(点都换成下划线)_方法名

    二、创建一个dll工程

    首先,在VS2005中,点击新建,出现下图

    输入Name之后,点击[OK],出现下图:

    选择dll,点击finish完成即可创建dll工程

    三、编写C/C++代码,生成dll

    将步骤一种生成的头文件拷贝到工程中“Header Files”目录下,然后新建一个cpp文件,或者直接在默认生成的jnitest.cpp中编码

    // jnitest.cpp : Defines the entry point for the DLL application.
    //
    
    #include "stdafx.h"
    #include "jni_test_JNIWrapper.h"
    #include <jni.h> //一定要加上这个
    
    #ifdef _MANAGED
    #pragma managed(push, off)
    #endif
    
    BOOL APIENTRY DllMain( HMODULE hModule,
                          DWORD  ul_reason_for_call,
                          LPVOID lpReserved
                          )
    {
        return TRUE;
    }
    
    #ifdef _MANAGED
    #pragma managed(pop)
    #endif
    
    
    
    JNIEXPORT void JNICALL Java_jni_test_JNIWrapper_display (JNIEnv *env, jobject obj)
    {
        printf("Hello World,JNI!\n");
        return;
    
    }
    
    /*
    * Class:     jni_test_JNIWrapper
    * Method:    sum
    * Signature: (DD)D
    */
    JNIEXPORT jdouble JNICALL Java_jni_test_JNIWrapper_sum (JNIEnv *env, jobject obj, jdouble a, jdouble b)
    {
        return a + b;
    }
    
    
    JNIEXPORT jdouble JNICALL Java_jni_test_JNIWrapper_divide(JNIEnv *env, jobject obj, jdouble a, jdouble b)
    {
        return a/b;
    }

    然后我们就可以开始编译了。

    如果提示找不到“jni.h”,只需要做如下操作即可解决:

    在%JAVA_HOME%\include\下找到 jni.h,
    在%JAVA_HOME%\include\win32\下找到jni_md.h和jawt_md.h
    把他们复制到“Visual Studio目录\VC\include\”下

    四、继续完成Java代码调用dll

    将步骤三得到的jnitest.dll放到java工程的根目录,注意是java项目的根目录,不是src目录

    写个test方法测试下

    package jni.test;
    
    public class JNITest {
        static {
            System.loadLibrary("jnitest");
        }
        
        
        public static void main(String[] args) {
            JNIWrapper wrapper = new JNIWrapper();
            wrapper.display();
            System.out.println(wrapper.sum(1.0, 9.9999));
            System.out.println(wrapper.divide(8.4, 2.4));
        }
    
    }

    不过,多数情况下,我们会把System.loadLibrary("jnitest")放在JNIWrapper中,即,

    package jni.test;
    
    public class JNIWrapper {
    
        static {
            System.loadLibrary("jnitest");
        }
    
        public native void display();
    
        public native double sum(double x, double y);
    
        public native double divide(double x, double y);
    }
    JNIWrapper

    运行一下,输入结果为

    10.9999
    3.5000000000000004
    Hello World,JNI!

    不知道打印“Hello World,JNI!”怎么最后执行~奇怪~

    到这里,整个JNI调用过程就over了~~

    不过还有类型转换什么的,以后再整理了....

    推荐资料:http://www.iteye.com/topic/304594

  • 相关阅读:
    No enclosing instance of type Test is accessible. Must qualify the allocation with an enclosing instance of type Test (e.g. x.new A() where x is an instance of Test).
    java中的static
    java gui 2
    Java GUI
    Java练习2
    安装docker后,原来正常的vagrant up启动出现了错误
    PHP Fatal error: Allowed memory size of 536870912 bytes exhausted (tried to allocate 17295719 bytes) in
    Class 'ZipArchive' not found解決
    从google storage上传或者下载文件
    使用python获取pptx文件的文本内容范例
  • 原文地址:https://www.cnblogs.com/yejg1212/p/3125372.html
Copyright © 2020-2023  润新知