【问题标题】:Using JNA, how do I create a 'C++ class' and pass it to a C++ function,?使用 JNA,如何创建“C++ 类”并将其传递给 C++ 函数?
【发布时间】:2014-10-02 13:04:46
【问题描述】:

我需要调用具有以下原型的专有 DLL 函数(为清楚起见进行了简化):

int J_Image_OpenStream(J_IMG_CALLBACK_OBJECT obj, J_IMG_CALLBACK_FUNCTION function);

类型定义为:

class CJDummyClass
{
};
typedef CJDummyClass * J_IMG_CALLBACK_OBJECT;
typedef void (CJDummyClass::*J_IMG_CALLBACK_FUNCTION)(J_tIMAGE_INFO * pAqImageInfo);

我之前在 JNA 中使用过 HOOKPROC 回调,但没有使用 Callback。看来我在这里连Callback 都不能用了。

由于我不知道如何在 Java 中扩展 CJDummyClass 类,我只是尝试了这个:

public class MyCallback implements Callback {
    public void callback() { System.out.println("Here"); }
}

MyCallback callback = new MyCallback();
lib.J_Image_OpenStream(callback.getClass, callback);

它给出: IllegalArgumentexception: Unsupported argument type java.lang.Class at parameter 0 of function J_Image_OpenStream

【问题讨论】:

标签: java oop callback jna


【解决方案1】:

简短回答:你不能(假设你说的是 C++ 而不是 C)

我会稍微简化一下,因为您似乎希望更深入地了解 C++ 和 Java 类。

C++ 中的类包含许多不同的细节,但您可以将其视为一组函数指针,每个函数指针都有一个隐含的第一个参数,表示作为该类实例化的对象。当您创建该类的实例时,您会得到一个装满东西的盒子,其中包括对象数据和对这些函数指针的引用。每个 C++ 编译器都以稍微不同的方式将这些东西放在一起。

您可以认为 Java 端的类具有大致相同的概念,但以完全不同的方式实现。为了让 Java 类假装它与 C++ 类相同,您必须知道本机编译器如何将事物组合在一起,以及如何将 Java 类的每个部分转换为 C++ 类中的相应部分。并非所有内容都可以翻译,虽然您可以映射很多常见的东西,但这是大量的工作,并且通过将本机编译器合并到任务中最容易完成(请参阅下面的 JavaCPP 参考)。

还有其他解决方案允许您在 Java 中定义类,这些类使用 JNI 与 C++ 中类似定义的类进行通信。不幸的是,它们涉及一定量的编写和/或编译本机代码并将其粘合到 Java 位。

SWIG JavaCPP

现在,如果您正在谈论调用仅使用 C 数据类型的函数(包括函数指针,也就是回调),那么 JNA 绝对能够做您想做的事。 C 语言使用一种定义良好的方法来使共享库中的函数可用。只要您知道函数名称并以正确的顺序排列参数,您就可以使用几乎任何语言的共享库。 JNA 使用定义良好的共享库结构来自动转换您的 Java 原始数据类型(以及一些复合数据类型,如 Structure),以成功调用共享库中的方法。

【讨论】:

  • 是的,我已经提供了一个有效的 JNI 实现,但是我的上级要求我将每个 JNI 项目都转换为 JNA。这是剩下的最后一个。
  • 所以,当这个方法包含参数时,可以很容易地使用 jna 从共享库中调用一个方法,当这个方法可以用 java 本机代码表示时,但是一个带有唯一参数的方法呢?(结构) ,如何使用 jna 从我的 java 代码中将参数传递给此类方法?
  • JNA 将容纳 struct, struct*、数组和其他聚合数据类型。如果没有相当多的额外工作,它将不会执行 C++ 类。
猜你喜欢
  • 2010-10-02
  • 1970-01-01
  • 1970-01-01
  • 2023-03-06
  • 1970-01-01
  • 2013-10-29
  • 1970-01-01
  • 1970-01-01
  • 2011-11-29
相关资源
最近更新 更多