栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

使用Swig…将Java对象传递给C ++,然后返回Java

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

使用Swig…将Java对象传递给C ++,然后返回Java

您可以通过一些工作克服您喜欢的约束(即不维护弱引用的映射)来执行此操作。事实证明,这比我最初预期的要少。我将首先讨论该解决方案,然后再对我第一次尝试执行此操作的方式进行一些讨论,以致于难以完成。

工作解决方案的高级视图是,我们添加了三件事:

  1. 通过
    %extend
    内部人员尝试动态强制转换的某些C ++代码
    Director*
    (即,SWIG总监层次结构的一个基础)。如果存在,它将保存对原始Java类的jobject引用。因此,我们可以简单地返回该jboject,如果强制转换失败,则返回NULL。
  2. 一些Java代码将返回我们的C ++代码的结果,或者
    this
    如果不合适的话,将返回它们。然后,我们可以从witihin的javadirectorin类型映射中注入调用,以允许从新代理“升级”到原始对象。
  3. 琐碎的类型映射形式的另一个技巧是
    %extend
    自动将JNIEnv对象传递到#1方法中,因为通常无法直接在该方法中访问它,即使它可能会这样暴露。

因此,您的接口文件将变为:

%module(directors="1") c_backend%{#include "c_backend.h"#include <iostream>%}%feature("director") Person;%feature("director") JobPool;// Call our extra Java pre to figure out if this was really a Java object to begin with%typemap(javadirectorin) Person * "$jniinput == 0 ? null : new $*javaclassname($jniinput, false).swigFindRealImpl()"// Pass jenv into our %extend pre%typemap(in,numinputs=0) JNIEnv *jenv "$1 = jenv;"%extend Person {    // return the underlying Java object if this is a Director, or null otherwise    jobject swigOriginalObject(JNIEnv *jenv) {        Swig::Director *dir = dynamic_cast<Swig::Director*>($self);        std::cerr << "Dynamic_cast: " << dir << "n";        if (dir) { return dir->swig_get_self(jenv);        }        return NULL;    }}%typemap(javapre) Person %{  // check if the C++ pre finds an object and just return ourselves if it doesn't  public Person swigFindRealImpl() {     Object o = swigOriginalObject();     return o != null ? ($javaclassname)o : this;   }%}%include "c_backend.h"

我向stderr发出了一封邮件,以证明它确实有效。

在实际代码中,您可能想要添加一个javaout类型映射,该类型映射也可以反映javadirectorin类型映射的功能。您也可以在宏中整齐地打扮它,因为编写所有代码都是为了避免采用固定的类型名称。

如果我不得不猜测为什么SWIG在默认情况下不会做类似的事情,那几乎可以肯定是因为那将强制使用RTTI,但是它过去一直很流行,会

-fno-rtti
“为了提高性能” 而传递到您的编译器中,因此有很多代码库尽量避免假设可以依靠动态转换。


如果您仅关心解决方案,请立即停止阅读。但是这里包含的参考是我最终放弃的原始方法。它开始像这样:

//c_backend.i%module(directors="1") c_backend%{#include "c_backend.h"%}%feature("director") Person;%feature("director") JobPool;%typemap(jtype) Person * "Object"%typemap(jnitype) Person * "jobject"%typemap(javadirectorin) Person * "$jniinput instanceof $*javaclassname ? ($*javaclassname)$jniinput : new $*javaclassname((Long)$jniinput), false)"%typemap(directorin,descriptor="L/java/lang/Object;") Person * {    SwigDirector_$1_basetype *dir = dynamic_cast<SwigDirector_$1_basetype*>($1);    if (!dir) {        jclass cls = JCALL1(FindClass, jenv, "java/lang/Long");        jmid ctor = JCALL3(GetMethodID, jenv, cls, "<init>", "J(V)");        $input = JCALL3(NewObject, jenv, cls, ctor, reinterpret_cast<jlong>($1));    }    else {        $input = dir->swig_get_self(jenv);    }}%include "c_backend.h"

后者更改了

Person
类型以从包装器代码一直返回
Object
/
jobject
。我的计划是,它要么是一个实例
Person
或者
java.lang.Long
,我们会动态地决定基于instanceof的比较构造什么样的。

但是,这样做的问题是jnitype和jtype
tyemaps在使用它们的上下文之间没有区别。因此,任何其他用法

Person
(例如,构造函数,函数输入,director
out,director代码的其他位)都需要更改为使用
Long
对象而不是
long
原始类型。即使通过在变量名上匹配类型映射,它仍然不能避免过度匹配。(尝试一下,并注意c_backendJNI.java中长成为Person的地方)。因此,在要求非常明确地命名类型映射方面,这将是很丑陋的,但仍然与我想要的内容不匹配,因此需要对其他类型映射进行更侵入性的更改。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/401990.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号