• java调用c/c++代码简单实现以及遇见的坑


    以下内容均来自互联网,感谢你们的分享,我只是使用的时候看这方便,可以称呼我“搬运工”

    如有不合适的地方请与我联系,我会及时改正

    首先你可能会遇见以下错误

    第一个错误是你在vs编译器没有选择使用release版的,而是用debug版的

    详细见http://blog.csdn.net/niuxinlong/article/details/4176612

    F:\java>java testdll
    Exception in thread "main" java.lang.UnsatisfiedLinkError: F:\java\testdll.dll:
    应用程序无法启动,因为应用程序的并行配置不正确。有关详细信息,请参阅应用程序事件
    日志,或使用命令行 sxstrace.exe 工具。
            at java.lang.ClassLoader$NativeLibrary.load(Native Method)
            at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1941)
            at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1857)
            at java.lang.Runtime.loadLibrary0(Runtime.java:870)
            at java.lang.System.loadLibrary(System.java:1122)
            at testdll.<clinit>(testdll.java:5)                             

    第二个是在64位运行了一个32位dll

    C:\testjni\testdll\x64\Debug>java testdll
    Exception in thread "main" java.lang.UnsatisfiedLinkError: C:\testjni\testdll\x6
    4\Debug\testdll.dll: Can't load AMD 64-bit .dll on a IA 32-bit platform
            at java.lang.ClassLoader$NativeLibrary.load(Native Method)
            at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1807)
            at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1732)
            at java.lang.Runtime.loadLibrary0(Runtime.java:823)
            at java.lang.System.loadLibrary(System.java:1028)
            at testdll.<clinit>(testdll.java:5)
    Could not find the main class: testdll.  Program will exit.

     第三个当然是编码问题喽,编译class时使用encoding参数

    C:\Users\Dmeck\Desktop\Java\winbox>javac -encoding gb2312 Testwin.java
    
    C:\Users\Dmeck\Desktop\Java\winbox>java Testwin
    8
    234
    中文乱码                                                               

     —————————————————————Body———————————————————————————————————

    好了下面一个xp简单实现,

    环境:java1.6、MinGw、sublime、xp32、vs2008

    在硬盘准备一个目录

    编写一个java加载JNi的本地实现

    testdll.java

    public class testdll 
    { 
        static 
        { 
            System.loadLibrary("testdll"); 
        } 
        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()); 
        } 
    }

    cmd进入以上目录

    运行

    javac testdll.java
    得到class
    javah testdll
    得到c的头文件

    此处有两种方式:

    一个把java安装目录的include目录

    jni.h以及32目录下的jni_md.h复制当前工作目录

    第二个是直接进行下一步

    下一步:查看并修改刚刚编译的头文件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

    修改全局引用为本地目录引用

    #include <jni.h>
    改为
    #include ”jni.h“

    之后在当前目录编写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;
    }

    接着运行gcc

    当然本例是winxp32位默认编译是32位dll
    以下是博客参考博客地址
    https://www.zhihu.com/question/36666057/answer/68516501
    事实上很多情况下那样调用都是不成功的,生成dll代码一般这样最完整
    gcc -Wl,--add-stdcall-alias -I "C:\Program Files\Java\jdk1.6.0_31\include" -I "C:\Program Files\Java\jdk1.6.0_31\include\win32" -shared -o testdll.dll testdll.cpp
    当你使用gcc的-m64编译64位dll会出现
    C:\Documents and Settings\Administrator\桌面\java1>gcc -m64 -Wl,--add-stdcall-al
    ias -I "C:\Program Files\Java\jdk1.6.0_31\include" -I "C:\Program Files\Java\jdk
    1.6.0_31\include\win32" -shared -o testdll.dll testdll.cpp
    testdll.cpp:1:0: sorry, unimplemented: 64-bit mode not compiled in
     #include "testdll.h"

    所以这时候用编译工具最合适了vs2008很老,但相关博客比较多

     
    本例是在windows下做的,生成的是dll文件。并且名称要与java中需要调用的一致,这里就是testdll.dll (跟testdll.java没有关系)
    把testdll.dll 拷贝到testdll.class的目录下,java testdll运行它,就可以观察到结果了
    C:\Documents and Settings\Administrator\桌面\java1>java testdll
    1000

    下面介绍vs2008下编译64位

    参考http://blog.csdn.net/a_little_e/article/details/45397557

     

    ——————————————————————————END——————————————————————————————————

    同样最后我们只需要三个文件

    testdll.class、testdll32.dll、testdll64.dll

    当然testdll.class需要对应的testdll.java源码,来修改

    System.loadLibrary("testdll"); 
    对应的加载库
  • 相关阅读:
    正则表达式
    cookie和session的区别(转载)
    Http协议
    10倍工程师
    10倍工程师
    HTML介绍
    HTML介绍
    网络基础之网络协议篇
    网络基础之网络协议篇
    计算机中的进制和编码
  • 原文地址:https://www.cnblogs.com/dmeck/p/8514955.html
Copyright © 2020-2023  润新知