目前,我正在尝试将自定义C ++库包装在Java(最终是Android)中。我的库使用OpenCV Mat
和Size
类作为输入。下面是我到目前为止的SWIG界面示例:
%module customLib
%include <std_vector.i>
%include <std_string.i>
%{
#include "opencv2/core/core.hpp"
#include "../include/myinc/CustomLib.h"
%}
namespace cv {
class Mat {};
class Size {};
}
namespace myinc {
CustomType preprocessMatrix(const cv::Mat& src, cv::Mat& dst, const cv::Size& ksize);
}
OpenCV已经为Mat
和Size
提供了Java包装器;我想知道一旦我添加了OpenCV自己的Java框架,我在这里所做的事情是否会引起命名冲突。这是通过SWIG包含对外部库类的引用的正确方法吗?或者,有没有更好的方法来完成这类事情?
答案 0 :(得分:1)
我终于想到了这一个!我花了一些时间来理解SWIG的Java类型映射系统是如何工作的(大多数例子都掩盖了一些重要的概念)。
如果其他人在理解如何编写Java类型地图时遇到困难,这是一种帮助我的方法。我认为最简单的方法是从上到下查看类型图(即Java - &gt;中间JNI - &gt; JNI)。首先,将jstype
定义为您希望在Java类中看到的类型(例如,module_name.java)。使用javain
告诉SWIG如何将变量从Java类传递到中间JNI类(例如,module_nameJNI.java)。接下来,将jtype
定义为与javain
相同的类型。例如,$javainput.getNativeObjectAddr()
会返回long
,因此这将成为我的jtype
。最后,将jni
定义为实际JNI函数将使用的内容。
下面是我想出的在OpenCV的Java界面上运行的SWIG图谱(从2.4.5开始):
%typemap(jstype) cv::Mat& "org.opencv.core.Mat"
%typemap(javain) cv::Mat& "$javainput.getNativeObjAddr()"
%typemap(jtype) cv::Mat& "long"
%typemap(jni) cv::Mat& "jlong"
%typemap(in) cv::Mat& {
$1 = *(cv::Mat **)&$input;
}
%typemap(jstype) cv::Size& "org.opencv.core.Size"
%typemap(javain) cv::Size& "$javainput"
%typemap(jtype) cv::Size& "org.opencv.core.Size"
%typemap(jni) cv::Size& "jobject"
%typemap(in) cv::Size& {
jclass sizeClass = JCALL1(GetObjectClass, jenv, $input);
jfieldID widthFieldId = JCALL3(GetFieldID, jenv, sizeClass, "width", "D");
jfieldID heightFieldId = JCALL3(GetFieldID, jenv, sizeClass, "height", "D");
double width = JCALL2(GetDoubleField, jenv, $input, widthFieldId);
double height = JCALL2(GetDoubleField, jenv, $input, heightFieldId);
$1 = new cv::Size((int)width, (int)height);
}
%typemap(freearg) cv::Size& {
delete $1;
}