【问题标题】:JNI Java using DLL function which takes an object as paramJNI Java使用以对象为参数的DLL函数
【发布时间】:2019-12-21 02:09:16
【问题描述】:

我需要使用一个外部的、未知的 DLL 并围绕它构建一个 java 包装器。我现在没有 DLL 也没有头文件,可能连头文件都没有,但我想自己准备。 (我没有 C++ 经验)

以下情况:

假设这个 DLL 有一个函数,它包含一个或多个 C++ 类作为方法签名。那我怎么能用 JNI 调用这个函数,因为在我的 java 项目中,DLL 中的那些自定义类不存在?是否有将 C++ 类“克隆”或“移植”到 java 的选项?我可以使用 Dependency Walker 之类的工具来解决这个问题吗?

实现该目标的最佳/最简单方法是什么?

这是我已经尝试过的一些代码,以了解它的行为方式:

带有 main 的 Java 类

public class FourthJNI {

    public static native int returnAgeOfHuman(int zuQuadrierendeZahl);

    public static void main(String[] args) {
//      /* This message will help you determine whether
//        LD_LIBRARY_PATH is correctly set
//       */
//      System.out.println("library: "
//              + System.getProperty("java.library.path"));

        Human testHuman = new Human("abcde", 23, "M");

        /* Call to shared library */
        int ageOfHuman = FourthJNI.returnAgeOfHuman(5);
        System.out.println(testHuman.toString());
        System.out.println("Age: " + ageOfHuman);
    }
} 

生成 h 文件

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

#ifndef _Included_FourthJNI
#define _Included_FourthJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     FourthJNI
 * Method:    returnAgeOfHuman
 * Signature: (I)I
 */
JNIEXPORT jint JNICALL Java_FourthJNI_returnAgeOfHuman
  (JNIEnv *, jclass, jint);

#ifdef __cplusplus
}
#endif
#endif

【问题讨论】:

  • 您最初是如何完成这项任务的?对于没有 C++ 经验的人来说,这不是一份工作。不,没有办法克隆/移植整个东西 - 即使 .H 文件可用。如果幸运的话,DepWalk 可以提供一些帮助(例如,界面不太繁琐),但这仍然是一项非常手动的工作。要回答您的问题,最好的方法是放弃这项任务。
  • 我将添加到之前的评论中。除非您知道并且真正了解 C++,否则执行 JNI 工作对您来说不会太顺利。 JNI 本身就是脆弱的,需要有经验的人才能知道如何解决脆弱性。
  • 这个“未知 DLL”的确切详细信息是什么?您需要了解详细信息,然后才能判断任务是否可以完成。因为您根本无法编写调用“未知”事物的代码。
  • @sstankov 这就是我的全部观点。你应该“包装”什么? “为此写一个包装器。”你:“它有什么作用?” “未知。”你甚至知道这个“未知的 DLL”是不是一个32- or 64-bit DLL?
  • 还有另一种方法。找一个对 C++ 和 JNI(以及可能对已编译代码进行逆向工程)有丰富经验的人,然后付给他们一大笔钱。从财务上讲,这对管理层有多重要? OBTW,C++ 没有反射。

标签: java c++ c dll java-native-interface


【解决方案1】:

这里最好的方法是使用适配器模式 (https://en.wikipedia.org/wiki/Adapter_pattern)。在JNI 代码中,您必须按照C++ API 的预期,通过创建所有对象来调用DLL

您可以在此处找到示例:http://jnicookbook.owsiak.org/recipe-No-021/ 和此处https://github.com/mkowsiak/jnicookbook/tree/master/recipes/recipeNo025

您还可以查看一个共享库 (JNI) 调用另一个共享库的代码:http://jnicookbook.owsiak.org/recipe-No-023/

基本上,您需要做的是创建基于 JNI 的包装器代码,它将对本机方法的 Java 调用转换为 C++ 调用,反之亦然 - 将返回值转换为预期值的代码Java。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-08-11
    • 1970-01-01
    • 1970-01-01
    • 2017-03-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-20
    • 2020-01-07
    相关资源
    最近更新 更多