gpt4 book ai didi

java - SWIG 和 shared_ptr : javaout typemap not applied to map template

转载 作者:太空宇宙 更新时间:2023-11-03 21:52:56 25 4
gpt4 key购买 nike

问题

我正在开发一个 Android 应用程序,其中我必须在 Java 代码和 C++ 代码之间传递 OpenCV Mat。为此,我创建了以下工作正常的 SWIG 类型映射:

%include "std_map.i"
%include "std_shared_ptr.i"
...
%shared_ptr(cv::Mat)
...
// normal typemaps for cv::Mat w/o shared_ptr
%typemap(jstype) cv::Mat, cv::Mat& "org.opencv.core.Mat"
%typemap(javain) cv::Mat, cv::Mat& "$javainput.getNativeObjAddr()"
%typemap(jtype) cv::Mat, cv::Mat& "long"
%typemap(jni) cv::Mat, cv::Mat& "jlong"

%typemap(in) cv::Mat, cv::Mat& {
$1 = *(cv::Mat **)&$input;
}
%typemap(javaout) cv::Mat, cv::Mat& {
return new org.opencv.core.Mat($jnicall);
}

// rather hacky javaout typemap override for the shared_ptr
%typemap(javaout) std::shared_ptr< cv::Mat > {
long cPtr = $jnicall;
return (cPtr == 0) ? null : new org.opencv.core.Mat(cPtr);
}

无论如何,在某些时候我必须返回一个 std::map<std::string, std::shared_ptr<cv::Mat>>到 java 。我使用带有

的 map 模板完成了此操作
%template(Map_String_Shared_ptr_Mat) std::map<std::string, std::shared_ptr<cv::Mat>>;

产生以下 get Java 中的方法:

public org.opencv.core.Mat get(String key) {
long cPtr = xyJNI.Map_String_Shared_ptr_Mat_get(swigCPtr, this, key);
return (cPtr == 0) ? null : new org.opencv.core.Mat(cPtr, true);

}

它没有使用之前提供的 javaout 类型映射。 (它适用于返回 std::shared_ptr<cv::Mat> 但不在 map 模板中的函数)

到目前为止我尝试了什么

我尝试插入自己的 get方法通过

%typemap(javacode) std::map<std::string, std::shared_ptr<cv::Mat>> %{
public org.opencv.Mat get{
...
}
%};

但这会导致冲突,因为存在两个 get 方法。

此外,当我尝试 %ignore get方法一,对应xyJNI.Map_String_Shared_ptr_Mat_get(swigCPtr, this, key);未创建,因此我无法提供自己的 get 实现

问题

现在我需要一种方法来告诉 SWIG 应用该 javaout 类型映射。但我也可以用一种方法来覆盖 get方法主体,为 Mat 使用正确的构造函数。

我希望有人能帮我解决这个问题

注意:我不关心 Map_String_Shared_ptr_Mat不是真实的Map在 java 。这对我来说不是问题

编辑:添加了 shared_ptr javaout 类型映射

最佳答案

不幸的是,我无法找到将 javaout 类型映射应用于 Mat_String_Shared_ptr_Mat.get() 的解决方案,也无法替换 的方法内容>Mat_String_Shared_ptr_Mat.get().

我最终得到的是一个变通方法,它在 getPlain() 中返回引用的 cv::Mat(所以不是 shared_ptr) > 应用类型映射的方法。

这当然不是我一直在寻找的完美解决方案,但它可能会帮助其他面临类似问题的人。


解决方案

%include "std_map.i"

// 1.
%typemap(javaout) cv::Mat, cv::Mat& {
return new org.opencv.core.Mat($jnicall);
}

...

// 2.
%ignore std::map<std::string, std::shared_ptr<cv::Mat>>::get;

// 3.
%template(Map_String_Shared_ptr_Mat) std::map<std::string, std::shared_ptr<cv::Mat>>;

// 4.
%extend std::map<std::string, std::shared_ptr<cv::Mat>>{
const cv::Mat& getPlain(const std::string& key) throw (std::out_of_range) {
std::map<std::string,std::shared_ptr< cv::Mat > >::iterator i = self->find(key);
if (i != self->end())
return *i->second;
else
throw std::out_of_range("key not found");
}
}
  1. 应用于包装映射的 cv::Mat 类型映射(与 shared_ptr 类型映射不同)
  2. 忽略get函数(第4步会自行实现)
  3. 让 SWIG 通过 std_map.i 中定义的模板创建包装器
  4. 通过向 map 添加 getPlain 函数来扩展包装器。此函数返回引用的 cv::Mat 对象本身,而不是 shared_ptr。创建 Java 代码时应用步骤 1 的 javaout 类型映射

输出

运行 SWIG 后,Java 类 Map_String_Shared_ptr_Mat 包含所需的 getPlain 方法:

public org.opencv.core.Mat getPlain(String key) {
return new org.opencv.core.Mat(xyJNI.Map_String_Shared_ptr_Mat_getPlain(swigCPtr, this, key));
}

更新

注意:这部分是cv::Mat特有的

由于 cv::Mat 在 Java 中的实现,我不得不更改实现以在 C++ 中执行按引用调用。

这是因为 Java Mat 实现存储了一个指向 C++ Mat 的指针。在 finalize 方法中,C++ 对象被释放。在之前的实现中,对象可能已经被删除,这将导致 SIGSEGV 崩溃。

因此将实现更改为以下内容:

%extend std::map<std::string, std::shared_ptr<cv::Mat>>{
void getPlain(const std::string& key, cv::Mat& dest) throw (std::out_of_range) {
std::map<std::string,std::shared_ptr< cv::Mat > >::iterator i = self->find(key);
if (i != self->end()){
(*i->second).copyTo(dest);
} else{
throw std::out_of_range("key not found");
}
}

它将数据复制到第二个参数中的 Mat,它本身是用 Java 创建的(因此不会产生已释放的段错误)。


可以调整解决方案以分别为 set 和其他函数创建/包装实现。

注意:我最后还使用了这篇文章中介绍的一些方法:Passing Java Map<String, String> to C++ method using SWIG ,绝对值得一看。

关于java - SWIG 和 shared_ptr : javaout typemap not applied to map template,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32071433/

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