0

目前,我正在尝试包装我的自定义 C++ 库以用于 Java(最终是 Android)。我的库使用 OpenCVMatSize类作为输入。下面是我到目前为止所拥有的示例 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 已经有 Java 包装MatSize;我想知道一旦我添加了 OpenCV 自己的 Java 框架,我在这里所做的是否会导致命名冲突。这是通过 SWIG 包含对外部库类的引用的正确方法吗?或者,有没有更好的方法来完成这类事情?

4

1 回答 1

1

我终于想通了这个!我花了一点时间来理解 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;
    }
于 2013-04-24T20:38:44.070 回答