gpt4 book ai didi

java - Swig 类型映射将变量地址作为参数传递?

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:23:13 24 4
gpt4 key购买 nike

我为以下 C++ 代码创建了 JNI 包装器。

add.h

class MyClass
{
public:
int add(int x, int y, int &z);
int sub(int x, int y);
};

上面提到的代码就是.h文件

添加.cpp

int MyClass::add(int x, int y, int &sum)
{
sum=x+y;
return 0;
}

int MyClass::sub(int x, int y)
{
return x - y;
}

swig.i

%module algo

%{
#define SWIG_FILE_WITH_INIT
#include "add.h"
%}
%include "arrays_java.i"
%include "typemaps.i"

%include "add.h"

对于上面提到的 .cpp 文件,我需要生成 JNI 包装器并将其用于 Java 代码。当我尝试执行 swig 命令时,我得到了 SWIGTYPE_p_int.java 文件和 JNI 文件。谁能帮我解决这个问题?

最佳答案

要包装 C++“通过非常量引用返回”函数,有很多选项可供选择。简而言之,您可以执行以下操作之一:

  1. 使用 %extend 提供一个返回的重载。 (可选择隐藏原件)
  2. 使用类型映射将其转换为返回值(并可选择将其映射到
  3. 更多地使用 SWIGTYPE_p_int。 (可选择在 Java 内部构建重载)
  4. 使用现有的 SWIG OUTPUT 类型映射通过数组获得按引用语义传递
  5. 使用结构体来获得按引用传递的语义

我将在此处展示每个选项的示例。


1。使用 %extend 提供重载

这里的基本思想是,我们将在此处编写一个全新的重载,SWIG 对其进行简单包装。使用下面的 %extend 语法,我们可以创建一个新的、仅包装器的重载,它使用临时存储值,然后在一切顺利时返回它。

%module algo

%{
#define SWIG_FILE_WITH_INIT
#include "add.h"
#include <exception>
%}

%extend MyClass {
int add(int x, int y) {
int z;
const int result = $self->add(x,y,z);
if (0 == result) return z;
throw std::exception();
// TODO: use SWIG's exception support
}
}

%ignore MyClass::add(int,int,int&); // Optional: hide the original overload
%include "add.h"

由于原始返回的 int 似乎指示函数本身的成功/失败,我们可以更自然地将其映射到 Java 中的异常。 (此处略去,详见我在XXX的回答)

2。使用类型映射返回它

这个解决方案的效果和上一个类似,只是实现方式不同。在这里,我们使用带有 numinputs=0in 类型映射来设置一个我们可以在调用发生时使用的临时变量 (tmpz) .然后 out 类型映射只检查来自真实函数调用的返回代码,argout 类型映射将 tempoary 复制到结果中。我在这里包含了比实际需要更多的类型映射,因为碰巧 z 和现有函数返回的类型相同,但如果不是这种情况,我们将需要它们。

%module algo

%{
#define SWIG_FILE_WITH_INIT
#include "add.h"
#include <exception>
%}

// These aren't actually needed here because the fuction already returns in
%typemap(jni) int MyClass::add "jint";
%typemap(jtype) int MyClass::add "int";
%typemap(jstype) int MyClass::add "int";
%typemap(javaout) int MyClass::add {
return $jnicall;
}

// These create a temporary and map it to the return value for us
%typemap(argout) int& z {
$result = (jint)tmpz$argnum;
}
%typemap(out) int MyClass::add {
if ($1 != 0) {
throw std::exception();
// TODO: exceptions as in other examples
}
}
%typemap(in,numinputs=0) int& z (int tmpz) {
$1 = &tmpz;
}
%include "add.h"

3。使用 SWIG 指针函数

在这里,我们将使用 SWIG 的 cpointer.i 库来帮助我们处理 SWIGTYPE_p_int 对象,并为我们的 Java 用户透明地执行此操作。为此,我们使用 javacode 类型映射为 z 创建了一个临时变量,然后将其传递给原始 SWIG 生成的函数(可以将其设为私有(private)以隐藏它)。与其他示例一样,我们可以通过抛出异常来处理返回值指示错误的情况,尽管这次已经是 Java 代码在执行抛出,这稍微简单一些。

%module algo

%{
#define SWIG_FILE_WITH_INIT
#include "add.h"
%}
%include "cpointer.i"
%pointer_class(int,IntPointer);
%typemap(javacode) MyClass %{
public int add(int x, int y) {
IntPointer z = new IntPointer();
int ret = this.add(x,y,z.cast());
if (ret != 0) throw new Exception();
return z.value();
}
%}
%javamethodmodifiers MyClass::add(int,int,int&) "private" // Optional
%include "add.h"

4。使用 OUTPUT 类型映射

这在功能上与之前的解决方案非常相似,不同的是我们使用数组而不是使用 SWIG 提供的辅助类型来处理 int 指针,并在底层利用 Java 的“按引用传递数组”语义来实现同样的结果。

%module algo

%{
#define SWIG_FILE_WITH_INIT
#include "add.h"
%}
%include <typemaps.i>
%apply int *OUTPUT { int & z };
%typemap(javacode) MyClass %{
public int add(int x, int y) {
int[] z = new int[1];
int ret = this.add(x,y,z);
if (ret != 0) throw new Exception();
return z[0];
}
%}
%javamethodmodifiers MyClass::add(int,int,int&) "private"
%include "add.h"

5.使用我们自己的结构进行引用传递

您可以使用 %inline 添加其他类型。然后欺骗 SWIG 使用它而不是 int& 引用。只要我们允许隐式转换就可以了。

%module algo

%{
#define SWIG_FILE_WITH_INIT
#include "add.h"
%}
%inline %{
struct IntWrapper {
int value;
// Enable transparent conversion for the SWIG argument
operator int&() {
return value;
}
};
%}
class MyClass
{
public:
int add(int x, int y, IntWrapper& z); // lie to SWIG, but we'll make it up later with implict conversion
int sub(int x, int y);
};
//%include "add.h" // Don't do this now because we need the lie above

与前面的示例一样,我们可以选择通过重载和方法修饰符的使用对 Java 用户隐藏此实现细节。

有关以上几个示例中提出的异常点的更多信息,请参阅 here , 或 here .

关于java - Swig 类型映射将变量地址作为参数传递?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44568507/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com