使用 SWIG 将 C++ 自定义单元类型转换为原始 Java 类型

问题描述 投票:0回答:1

我有 C++ 代码,正在尝试使用 SWIG 提供 Java 绑定。

struct meters_t : public boost::units::quantity<boost::units::si::length> {};

我希望尝试将

meters_t
的所有引用替换为
double
Java.lang.Double

我在我的 SWIG 界面

.i
文件中尝试了以下操作:

%typemap(jstype) meters_t "java.lang.Double"
%typemap(jtype) meters_t "java.lang.Double"
%typemap(jni) meters_t "jdouble"
...
// Duplicated for const, const&, &
%ignore meters_t
%include "my_include.h"

但是我目前遇到类型转换错误

error C2440: 'type cast': cannot convert from 'meters_t *' to 'jdouble'
error C2440: 'type cast': cannot convert from `jdouble` to `meters_t *`

有人有任何建议来纠正这个问题吗?我很快就失去了将

meters_t
转换为简单
double
的想法是可能的:/

更新: 我还添加了以下内容

%typemap(javain) meters_t "$javainput"

这使得可以构建 Java 绑定,但是当我尝试使用 Java 绑定时(在不同的

struct
上,将
meters_t
作为构造函数参数),它会立即抛出错误

A fatal error has been detected by the Java Runtime Environment
EXCEPTION_ACCESS_VIOLATION

更新2.0

我现在已经将

meters_t
SWIG 包裹起来。我的新问题是一个带有 boost 默认参数的类,我遇到了难以捉摸的
Syntax error in input(3).
错误

Foo(meters_t meters = meters_t{ 0.0 * boost::units::si::meters });
java c++ swig
1个回答
0
投票

您已经开始使用 typemaps 走上正确的轨道。这些对于 C++ 和 Java 之间的类型转换至关重要。但这些错误表明 SWIG 在

meters_t
jdouble
之间自动转换时遇到问题。

您可能需要提供 custom 类型映射来显式处理此转换。您需要为 SWIG 提供一种方法来了解如何将

meters_t
转换为
jdouble
,反之亦然。

尝试并为

%typemap(in)
实施
%typemap(out)
meters_t
。这些类型映射将定义从 C++ 传递到 Java 时如何将
meters_t
对象转换为 Java
double
,反之亦然。

SWIG 对解析复杂的默认参数]的支持有限。一种解决方案是简化 SWIG 接口文件中的默认参数,或者提供没有默认参数的构造函数的重载版本,以便 SWIG 进行包装。

在您的 SWIG 接口文件中,实现类型映射:

%typemap(in) meters_t {
    // Code to convert from jdouble to meters_t
}

%typemap(out) meters_t {
    // Code to convert from meters_t to jdouble
}

// For the constructor issue
%ignore Foo::Foo(meters_t);
%extend Foo {
    Foo() {
        return new Foo(meters_t{0.0 * boost::units::si::meters});
    }
}

您需要根据

meters_t
如何与
double
相互转换来填写转换逻辑。


关于“

Code to convert from jdouble to meters_t
”,从Java转换为C++时,您将收到一个Java
double
(在C++ JNI代码中表示为
jdouble
)。您需要将其转换为
meters_t
对象。
假设
meters_t
可以从
double
构造或分配,则类型映射可能如下所示:

%typemap(in) meters_t {
    $1 = meters_t($input * boost::units::si::meter);
}

在此类型图中:

  • $1
    是 C++ 参数的占位符(在本例中为
    meters_t
    )。
  • $input
    表示来自 Java 的输入(a
    jdouble
    )。
  • 表达式
    $input * boost::units::si::meter
    从 Java double 构造一个
    meters_t
    对象,假设
    meters_t
    可以通过这种方式初始化。

对于“

Code to convert from meters_t to jdouble
”:

从 C++ 转换为 Java 时,您需要从

double
对象中提取
meters_t
值:

%typemap(out) meters_t {
    $result = (jdouble)$1.value();
}

在此类型图中:

  • $1
    是 C++
    meters_t
    对象的占位符。
  • $result
    是您要映射到的 Java 类型的 JNI 表示形式(在本例中为
    jdouble
    )。
  • $1.value()
    是一种从
    double
    对象中提取
    meters_t
    值的假设方法或方式。您需要将其替换为从
    meters_t
    类型中提取数值的实际方法或途径。

确保

meters_t
可以由
double
构造而成,并具有将其值提取为
double
的方法。如果没有,您将需要调整代码以适应
meters_t
的实际界面。
这些类型映射假设
boost::units::si::meter
是合适的转换单位。如有必要,请根据您的具体实施
meters_t
进行调整。

© www.soinside.com 2019 - 2024. All rights reserved.