SWIG (Java):如何调用带有 void* out 参数的函数?

SWIG (Java): How can I call a function with a void* out parameter?

背景

我正在使用 C++ 代码库为 Android 开发一个实时通信应用程序。我使用 SWIG 生成一个 JNI 桥,以从 Java 访问本机代码。为了跟踪活动呼叫,void* 用作句柄(它指向包含有关正在进行的呼叫的信息的地址)。以下函数头是如何使用它的示例:

void initiateCall(void** callHandleRef);

void closeCall(void* callHandle);

initateCall 获取一个 void**,分配一个结构并将其地址(作为 void*)写入 callHandleRef。它作为一个“输出”参数工作,因为您将它作为参数传递并期望向它写入一些内容。当 closeCall 被调用时,原始指针被传递,允许 C++ 库访问与该特定调用关联的数据。

问题描述

我想从 Java 调用 initiateCallcloseCall,使用 SWIG 生成执行此操作所需的 JNI 代码。然而。 SWIG 分别生成类型“SWIGTYPE_p_p_void”和“SWIGTYPE_p_void”,我无法按照上述方式使用它们。如何设置我的 SWIG 接口文件以允许我执行此操作?

Flexo 对这个问题的评论对我有用,如 所示。这是我的解决方案,或多或少 copy-pasted 来自他们的回答。

C++ 头文件(call.h):

typedef void* CALL_HANDLE;

int initiateCall(const char* name, CALL_HANDLE* handle);
int closeCall(CALL_HANDLE handle);

SWIG 接口(call.i):

%module bridge

%include <cpointer.i>

%pointer_class(CALL_HANDLE, inst_ptr);
%javamethodmodifiers initiateCall "private";
%pragma(java) modulecode=%{
  public static SWIGTYPE_p_void initiateCall(String name) {
      inst_ptr ptr = new inst_ptr();
      final int err = initiateCall(name, ptr.cast());
      if (0 != err) {
          // Throw error or something like that
      }
      return ptr.value();
  }
%}

%include "include/call.h"

extern int initiateCall(const char* name, CALL_HANDLE* handle);
extern int closeCall(CALL_HANDLE handle);

主要 activity (MainActivity.kt):

class MainActivity : AppCompatActivity() {
    private lateinit var callHandle: SWIGTYPE_p_void

    fun call(name: String) {
        callHandle = bridge.initiateCall(name)
    }

    fun hangup() {
        bridge.closeCall(callHandle)
    }
}