zoukankan      html  css  js  c++  java
  • JNI

    实验于JDK8

    1、新建测试Java类  JNIT

    public class JNIT {   
        static { 
            System.loadLibrary("JNIT"); 
        }
        public static native String hello(String msg);       
        public static void  main(String[] args) {    
            String str= hello("Hello, c++!" );
            System.out.print("java get c++ Str:"+str);
        }
    }
     

    2、在JNIT.java文件同目录下执行 javac JNIT.java   在同目录下生成 JNIT.class  文件

    3、在JNIT.class同目录下执行 javah -classpath . -jni  JNIT    ,生成 JNIT.h文件 内容如下

    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include "jni.h"
    /* Header for class JNIT */
    
    #ifndef _Included_JNIT
    #define _Included_JNIT
    #ifdef __cplusplus
    extern "C" {
    #endif
        /*
         * Class:     JNIT
         * Method:    hello
         * Signature: (Ljava/lang/String;)Ljava/lang/String;
         */
        JNIEXPORT jstring JNICALL Java_JNIT_hello
        (JNIEnv *, jclass, jstring);
    
    #ifdef __cplusplus
    }
    #endif
    #endif

    注:
    文件中的 Java_JNIT_hello 说明是Java中的JNIT类的hello方法
    文件中的 #include<jni.h>等 <> 符号在命令行打包动态库时会打包失败 需要改为 “jni.h”

    生成的文件中需要导入的jni.h 和 jni_md.hJAVAHOME/jdk/includeJAVAHOME/jdk/include/win32 目录下,你可以选择直接拷贝或后期配置添加(注意32和64位区分)

    4、在JNIT.h相同目录下新建JNIT.cpp ,实现JNIT.h 中方法

    // dllmain.cpp : 定义 DLL 应用程序的入口点。
    // pch.cpp: 与预编译标头对应的源文件
    
    #include "JNIT.h"
    // 当使用预编译的头时,需要使用此源文件,编译才能成功。
    #include <iostream>
    using namespace std;
    JNIEXPORT jstring JNICALL Java_JNIT_hello
    (JNIEnv * jEnv, jclass jcls, jstring jstr) {
        const char *c_str = NULL;
        char buff[128] = { 0 };
        c_str = (jEnv)->GetStringUTFChars(jstr,false);
        if (c_str == NULL)
        {
            printf("out of memory.
    ");
            
        }
        cout << "c++ get Java Str: "<< c_str << endl;
    
    //    (jEnv)->ReleaseStringUTFChars( jstr, c_str);
    //printf("c++ get Java Str:%s
    ", c_str);
    
        return (jEnv)->NewStringUTF("hello java");
    
    }

    5、准备gcc编译环境

    这里gcc的环境有32位与64位的区分 不然运行会有错误Exception in thread "main" java.lang.UnsatisfiedLinkError: D:eclipsejeeworkspaceJNITsrcJNIT.dll: Can't load IA 32-bit .dll on a AMD 64-bit platform

    6、使用VS2017的命令行编译

     cl -I"%JAVA_HOME%include" -I"%JAVA_HOME%includewin32" -LD HelloWorld.c -FeHelloWorld.dll   
    参数选项说明:
        -I :和 mac os x 一样,包含编译 JNI 必要的头文件
        -LD:标识将指定的文件编译成动态链接库
        -Fe:指定编译后生成的动态链接库的路径及文件名

    6、使用VS2017新建dll项目, 编译打包

    (1)新建dll项目

    (2)将写好的JNIT.cpp粘贴内容粘贴到 dllMain.cpp 中  这里可以对dllMain.cpp 修改名称,将JNIT.h粘贴进项目目录。

    (3)右键项目》属性》c/c++》常规》附加包含目录,将jdk/include和jdk/include/win32添加进去,从而引入jni.h和jni_md.h

    (4)去除编译器默认对pch文件的预编译,右键项目》属性》c/c++》预编译头》预编译头》不使用预编译头

    (5)运行项目,会在控制台输出dll文件路径

    6、使用MinGW 在window命令行,执行编译打包  , 会在当前目录下生成 .dll 文件

    g++ -I%JAVA_HOME%include -I%JAVA_HOME%includewin32 -shared -Wl,–kill-at -s -o lib.dll JNIT.cpp
    解释一下:
    -I(大写字母I,include的意思)是加入自己的库,也就是告诉编译器jni.h的位置。当然不加这个参数也可以,自己把jni.h和jni_md.h文件复制出来和Test.c放一起,另外include改为””
    -shared表示编译成.dll库文件
    -s参数可以大幅减小.dll文件的大小,不加也可以
    -o表示目标文件名,不加也可以,会有默认名,但要自己改成java中导入库的名字,这里是lib
    -Wl,–kill-at  防止编译后的函数名被自动加上@符号,并取消警告。(是小写字母L,不是数字1)

    当你把jni.h 和jni_md.h 粘贴到当前目录下可以使用以下命令
    g++ -shared -Wl,-kill-at -s -o lib.dll JNIT.cpp
    g++ -s -o JNIT.dll JNIT.cpp

    6、linux下g++编译打包,会在当前目录下生成 .so文件    

    g++ -I$JAVA_HOME/include -I$JAVA_HOME/include/linux -fPIC -shared -o JNIT.so  
    参数说明:
        -I: 包含编译JNI必要的头文件
        -fPIC: 编译成与位置无关的独立代码
        -shared:编译成动态库
        -o: 指定编译后动态库生成的路径和文件名

    当你把jni.h 和jni_md.h 粘贴到当前目录下可以使用以下命令
    g++ -shared -Wl,-kill-at -s -o lib.dll JNIT.cpp
    g++ JNIT.cpp -fPIC -shared -o JNIT.so

    7、将生成的.so(linux) 或.dll(window)复制到 之前的JNIT.class 同一目录下,并且修改为JNIT.dll或JNIT.so (与java文件中加载的库名一致)

    8、执行java JNIT 运行代码 .注意不是 java JNIT.class,不然会报无法加载主类

    java JNIT

     




  • 相关阅读:
    递归要记得返回
    git push的时候报Unable to find remote helper for 'https'的错误
    iphone手机上的click和touch事件
    对jquery的conflict方法的解读
    开发富文本编辑器的一些体会
    使用jquery制作动态加载型菜单
    解决jquery$命名符和其它框架的冲突问题
    基于geolocation来获取经纬度地址
    Python学习笔记2解析数据
    Python学习笔记1数据类型
  • 原文地址:https://www.cnblogs.com/the-wang/p/12110812.html
Copyright © 2011-2022 走看看