使用SWIG引用外部库中的特定类

时间:2013-04-20 22:24:49

标签: java c++ opencv swig

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

1 个答案:

答案 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;
    }