Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/372.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我可以参考C++;使用JNI的Java代码中的对象?_Java_C++_Java Native Interface - Fatal编程技术网

我可以参考C++;使用JNI的Java代码中的对象?

我可以参考C++;使用JNI的Java代码中的对象?,java,c++,java-native-interface,Java,C++,Java Native Interface,我在任何地方都没有看到过这一点(或者可能我是jsut simple没有看到),但是有没有一种方法可以使用JNI返回c/c++对象并在java中使用该对象 例如(非常简单): 在我的java代码中,我将如何执行以下操作: ... simpleClass sc = new simpleClass(); sc.setIntVar(9); System.out.println(sc.getIntVar()); ... 我意识到这是一个非常简单的例子,但我只是在寻找概念——我在C++中的这个类非常大,我

我在任何地方都没有看到过这一点(或者可能我是jsut simple没有看到),但是有没有一种方法可以使用JNI返回c/c++对象并在java中使用该对象

例如(非常简单):

在我的java代码中,我将如何执行以下操作:

...
simpleClass sc = new simpleClass();
sc.setIntVar(9);
System.out.println(sc.getIntVar());
...
<>我意识到这是一个非常简单的例子,但我只是在寻找概念——我在C++中的这个类非常大,我希望避免创建大量的包装方法……<
如果不可能,那也没关系,只是希望节省几天的编码时间,哈哈

不,你不能。C++和java abi完全不同,C++一个也不定义。而且C++确实有很多无法映射到java的特性,这根本不能工作。你希望java如何处理C++模板?指向原语的指针?不是指针的对象


现在您可以做的是,使用SWIG为您生成正确的包装器方法-这将实际起作用,并且不会比您计划的多做多少工作:)

JNI仅为基本(或相当基本)类型以及内存缓冲区传递/管理函数定义其接口。没有映射复杂对象类型的功能。但是,您可以通过编写自己的(单个)序列化/反序列化函数来实现此效果,如中所示。

您的Java版本的SimpleClass应该做两件事。一,保持一个私有的长值,它将C++指针的值存储到后备的本地对象(可能需要使用大整数取决于本地指针的大小)。第二,使公共方法(例如,
setIntVal
)成为本机方法

然后在JNI代码中实现这些本机方法。<代码> iNITNATESPICAL()/>代码>方法将是一个新的支持C++实例的代码> SimpleClass < /C>。然后,
destroyNativeSimpleClass()
方法将删除该实例。访问器方法将使用
nativePtr
的值,将其强制转换为实际指针,并对本机备份实例执行适当的操作


这个习惯用法带来了内存泄漏的真正风险,因为类的用户在处理实例时必须调用destroy。如果没有,则可能无法正确销毁支持本机实例。正如我在示例中所示,您可以重写
finalize
来调用本机销毁程序函数,但是关于finalize如何不可靠的所有警告仍然适用。销毁时,将代码< > nATVEPTR > /CUT>值设置为0,如果破坏被多次调用,则避免SEG错误(C++中安全删除空)。注意:C++模板与此问题无关,因为模板是用C++编译的。JNI必须支持从这些模板实例化的类,这些类看起来与常规类没有什么不同。@Dan如果您编写的是一个非头模板类,那么您必须能够告诉编译器在客户机代码中实例化新版本的类,因此我认为编译器也必须了解模板(虽然不知道这是否是标准要求的,但实际上从来没有这样做过)@Voo编译时需要模板的定义来生成实例化。一旦为所使用的每种必要类型生成了目标代码,就好像您为每种类型编写了一个类一样。如果不包含cpp文件,您就不能引用不在翻译单元中的模板,除非其定义为ent我也同样依赖内联。@ VoO,这些东西(指向原语等的指针)我绝对没有考虑过。这让我觉得我只是想绕过包装方法:“@ ReHOT,正如我所说,看一下,它基本上对你的C++接口进行了简单的描述(通常足够的是头)。并为您生成正确的包装。我自己并没有在Java中使用它,但它在Python中工作得很好,我也从Java中使用它的人那里听到了一些好消息。它的优点是:从长远来看,工作量少,B)意味着包装器和C++文件永远不会同步。这并不避免创建包装器功能,但这是唯一使用JNI来在原生类上放置java前线的方法。我绝对喜欢这样。我不得不说,我喜欢这比“使用”好。C++对象:它提供了一种文档来记录我使用本机方法的方法。谢谢有趣…这是一个非常有趣的概念。谢谢你的链接!谢谢
...
simpleClass sc = new simpleClass();
sc.setIntVar(9);
System.out.println(sc.getIntVar());
...
public class SimpleClass {
    private long nativePtr;

    public SimpleClass() {
        nativePtr = initNativeSimpleClass();
    }

    public void destroy() {
        destroyNativeSimpleClass();
        nativePtr = 0L;
    }

    protected void finalize() throws Throwable {
        destroyNativeSimpleClass();
        nativePtr = 0L;
    }

    public native int getIntVal();
    public native void setIntVal(int val);

    private native long initNativeSimpleClass();
    private native void destroyNativeSimpleClass();
}