C#利用SWIG呼叫C++的DLL
/MD編譯的c++DLL可以利用託管C++,/MT編譯的DLL不能利用託管C++與C#粘合,
找了很久,今天偶爾發現了SWIG技術,經測試可以滿足第二中要求,特此記錄一下。
環境:
Win10+VS2019+SWIG4.0.2
1.首先下載SWIG,我是Win10,需要選擇swigwin版
http://www.swig.org/download.html
下載後解壓到指定定目錄,如:D:\swigwin402,為方便呼叫,可以把此路徑新增到系統路徑:
2.建立C#控制檯應用程式SwigCSharp
3.在此解決方案中新增C++動態連結庫專案:SwigC
以上所有由VS自動建立的內容完全不必做任何更改。
4.我在C++dll中新增兩個類CAdd、CMul展示應用效果,
5.向剛才新增的兩個C++類增加程式碼(粗斜體部分):
CAdd.h
#pragma once class CAdd { public: CAdd(); ~CAdd(); // 測試對C++模組中定義的Class的呼叫 int Add(int a, int b); };
CAdd.cpp
#include "pch.h" #include "CAdd.h" CAdd::CAdd() {} CAdd::~CAdd() {} int CAdd::Add(int a, int b) {return a + b; }
CMul.h
#pragma once class CMul { public: CMul(); ~CMul(); // 測試對C++模組中定義的Class的呼叫 int Mul(int a, int b); };
CMul.cpp
#include "pch.h" #include "CMul.h" CMul::CMul() {} CMul::~CMul() {} int CMul::Mul(int a, int b) { return a * b; }
6.在SwigC專案資料夾中新增兩個檔案:SwigC.bat和SwigC.i,內容如下:
SwigC.bat內容
@echo off
swig -csharp -c++ SwigC.i
@echo 'Success'
pause
SwigC.i內容
%module DLLNameWithoutEXT
%{
#include "CAdd.h"
#include "CMul.h"
%}
%include "CAdd.h"
%include "CMul.h"
紅色字可以隨便寫,但是後續生成的c++ DLL的檔名(不含副檔名)要與紅字相同
7.雙擊bat檔案,會自動生成幾個cs檔案和一個cxx檔案:
向C++專案新增SwigC_wrap.cxx檔案,並修改為“不使用預編譯頭”
向C#專案新增四個cs檔案CAdd.cs、CMul.cs、DLLNameWithoutEXT.cs、DLLNameWithoutEXTPINVOKE.cs
全部新增完後項目如圖所示:
8.修改C# 專案的程式碼:
namespace SwigCSharp { class Program { static void Main(string[] args) { CAdd add = new CAdd(); Console.WriteLine("{0}+{1}={2}", 5, 6, add.Add(5, 6)); CMul mul = new CMul(); Console.WriteLine("{0}*{1}={2}", 5, 6, mul.Mul(5, 6)); Console.ReadLine(); } } }
9.編譯C++dll,並把dll複製到C#輸出目錄中,再編譯執行C# 專案:
10.出錯了!fxxk
11.原來是c++dll是x86的,而c#程式為AnyCPU,修改C#為x86,重新生成C#程式
12.哦耶!
13.把c++dll改為/MT 編譯,重新使用dll,仍然成功!