2013-04-20 94 views
0

目前,我正在試圖封裝自定義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

我終於明白了這一點!我花了些時間瞭解SWIG的Java類型映射系統是如何工作的(大多數例子都掩蓋了一些重要的概念)。

如果其他人在理解如何編寫Java類型映射時遇到困難,這是一種幫助我的方法。我認爲從上到下的角度(即Java - >中間JNI - > JNI)查看類型映射是最容易的。首先,將jstype定義爲您希望在Java類中看到的類型(例如,module_name.java)。使用javain告訴SWIG如何將變量從Java類傳遞給中間JNI類(例如,module_nameJNI.java)。接下來,將jtype定義爲與javain相同的類型。例如,$javainput.getNativeObjectAddr()返回long,所以這將成爲我的jtype。最後,將jni定義爲實際的JNI函數將使用的內容。

下面,是SWIG typemaps我想出了OpenCV的上的Java接口上運行(如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; 
    }