我终于想通了这个!我花了一点时间来理解 SWIG 的 Java 类型映射系统是如何工作的(大多数示例都掩盖了一些重要的概念)。
如果其他人无法理解如何编写 Java 类型映射,这里有一种方法可以帮助我。我认为从自上而下的角度(即 Java -> 中间 JNI -> JNI)查看类型映射是最简单的。首先,将 定义jstype
为您希望在 Java 类中看到的类型(例如,module_name.java)。用于javain
告诉 SWIG 如何将变量从 Java 类传递到中间 JNI 类(例如,module_nameJNI.java)。接下来,将 定义jtype
为与将要的类型相同的类型javain
。例如,$javainput.getNativeObjectAddr()
返回 a long
,所以这将成为 my 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;
}