操做系統:windows 7
IDE:Microsoft Visual Studio Professional 2015
SWIG: 3.0.12html
詳細介紹可看官網,一下貼出官網上的原話:c++
SWIG is a software development tool that connects programs written in C and C++ with a variety of high-level programming languages. SWIG is used with different types of target languages including common scripting languages such as Javascript, Perl, PHP, Python, Tcl and Ruby. The list of supported languages also includes non-scripting languages such as C#, Common Lisp (CLISP, Allegro CL, CFFI, UFFI), D, Go language, Java including Android, Lua, Modula-3, OCAML, Octave, Scilab and R. Also several interpreted and compiled Scheme implementations (Guile, MzScheme/Racket, Chicken) are supported. SWIG is most commonly used to create high-level interpreted or compiled programming environments, user interfaces, and as a tool for testing and prototyping C/C++ software. SWIG is typically used to parse C/C++ interfaces and generate the ‘glue code’ required for the above target languages to call into the C/C++ code. SWIG can also export its parse tree in the form of XML and Lisp s-expressions. SWIG is free software and the code that SWIG generates is compatible with both commercial and non-commercial projects.express
如下是個人理解(注:如下這段話並非上段話的翻譯):
Swig主要是爲了將c++/c中的代碼所實現的功能移植到別的語言上。通常咱們要將c++/c移植到別的語言上,基本操做是將c++中的實現代碼轉變成dll,而後再供別的語言調用,這樣安全性高,且易於調用。可是由於各類語言不相同,若是不借助swig,本身去封裝。在調用dll時就會有不少類型(包括基本類型,結構體和類)轉換須要注意,好比c#調c++ dll,可能得本身造一個相對應與c++的結構體和類才能成功調用。可是若是咱們用了swig,這些咱們都不用考慮,咱們只須要考慮swig給咱們的接口類型是什麼,而後咱們只要按照swig給的接口類型傳入參數,就OK了。說白了就是swig代替了咱們利用c#去從新定義dll中所須要傳入的參數類型(如結構體或類)這個工做。c#
進入以下網址:http://www.swig.org/download.html
因爲我是windows系統,因此安裝以下版本:
下載後,將其解壓至制定目錄,如:D:\SDK\swigwin-3.0.12windows
一、創建以下c++項目(應用程序類型選擇dll類型)和c#項目,還沒實現代碼,都是空項目。主要有.h .cpp .idl .cs文件(具體這四個文件怎麼建立我就不贅述了,想必能找到這篇博文就說明已具有了建立此文件的能力)。
安全
二、填寫代碼:
(1) c++_file.idl:
(網上說的都是.i文件,其實就是vs裏的.idl文件)ide
%module cppdll %{ /* 在包裝代碼中包含頭文件 */ #include "c++_file.h" %} /* 解析頭文件生成包裝代碼 */ %include "c++_file.h"
(2) c++_file.cpp函數
#include "c++_file.h" int CPlusPlusClass::Add(int a, int b) { return a + b; }
(3)c++_file.hvisual-studio
#pragma once class CPlusPlusClass { public: // 測試對C++模塊中定義的Class的調用 int Add(int a, int b); };
(4)Program.cs測試
CPlusPlusClass fromCPlusPlus = new CPlusPlusClass(); Console.WriteLine("1+2=" + fromCPlusPlus.Add(1,2)); Console.ReadKey();
三、build .idl接口文件。在.cpp所在目錄下用命令框輸入
D:\SDK\swigwin-3.0.12\swig.exe -csharp -c++ c++_file.idl
回車後會發現當前文件夾中出現如下幾個文件:
四、分別在c++項目和c#項目中引用各自須要的文件,引用完後,應該和以下圖同樣。
五、在生成dll以前,先將.idl文件的屬性改成以下圖所示:
六、生成c++ dll:從新生成 c++項目便可,在debug文件夾中會發現有一個c++_project.dll文件,說明生成成功。
七、運行c#項目,將c#項目設爲啓動項。將c++_project.dll該名爲.idl文件中的module名(cppdll.dll),並放入bin/debug/中.以下圖所示:
八、而後直接運行可得以下結果:
Intptr參數的轉換:
Intptr是c#中的句柄,有點相似於c++指針,但又不是一個東西,指針指向的是一個地址,可是Intptr只是某個資源的編號。
這個也是最不可控的一點,我在這上面花費了很大的精力。我準備是利用swig將c++實現的人臉識別代碼用c#來調用,由於c#作殼子挺方便的。可是我經過swig調用的時候,他傳入的圖像參數類型是intptr的,可是我是bitmap類型的。而後我遇到了一下棘手的問題:
最後我也把我解決這個問題的代碼貼出來吧:
(1)BitmapExtensions.cs:
internal static class BitmapExtensions { /// <summary> /// 將圖像轉換爲RGB圖像 /// </summary> /// <param name="self"></param> /// <returns></returns> public static Bitmap ConvertToRgb24(this Bitmap self) { if (self.PixelFormat != PixelFormat.Format24bppRgb) { var convertImage = new Bitmap(self.Width, self.Height, PixelFormat.Format24bppRgb); using (var g = Graphics.FromImage(self)) { g.DrawImage(self, 0, 0); } return convertImage; } return self; } /// <summary> /// 獲取位圖數據的像素數據 /// </summary> /// <param name="self"></param> /// <param name="useNativePixelFormat"></param> /// <param name="pixelSize"></param> /// <returns></returns> public static byte[] GetBitmapData(this Bitmap self, out int pixelSize, bool useNativePixelFormat = false) { var rect = new Rectangle(0, 0, self.Width, self.Height); var bmpData = self.LockBits(rect, ImageLockMode.ReadOnly, useNativePixelFormat ? self.PixelFormat : PixelFormat.Format24bppRgb); var dataPtr = bmpData.Scan0; var bytesCount = Math.Abs(bmpData.Stride) * self.Height; var data = new byte[bytesCount]; Marshal.Copy(dataPtr, data, 0, bytesCount); self.UnlockBits(bmpData); pixelSize = bmpData.Stride / bmpData.Width; return data; } }
外部實現代碼:
Bitmap gray = new Bitmap(image.Width, image.Height, PixelFormat.Format8bppIndexed); gray = new Grayscale(0.2125, 0.7154, 0.0721).Apply(image); int pixelSize; var imageData = BitmapExtensions.GetBitmapData(gray,out pixelSize,true); var pImageData = Marshal.AllocHGlobal(imageData.Length); //未釋放 Marshal.Copy(imageData, 0, pImageData, imageData.Length);
http://www.swig.org/ (官網)
http://blog.csdn.net/lee353086/article/details/40707305 (創建一個示例)
http://www.technical-recipes.com/2013/getting-started-with-swig-interfacing-between-c-and-c-visual-studio-projects/ (創建一個示例)
http://www.swig.org/Doc1.3/CSharp.html#csharp_directors_example (講解swig與c#)
良心教程(建議英語好的能夠看這個教程,官網教程太含糊了):
http://www.jenkinssoftware.com/raknet/manual/swigtutorial.html
https://blog.csdn.net/liu14lang/article/details/78882539