結合多語言(如 Visual C++ 與 Visual C#)以便利軟體開發是.NET framework的重點核心之一。
廢話不多說,先來看如何在Visual C++中使用自己所產生出來的Dll[1]。
有了這個基本概念後,就可以知道要在Visual C++中創造一個dll,在該function/method的header file中要加上__declspec(dllexport),已確保該function/method可以被export到Dll中。
而對應的.cpp檔就只是單純的實做對應method的內容。
如[2]所說,微軟只提供C-function的marshal對應的方法(也就是以function-based的marshal,並沒有class level的marshal)。
所以如果要marshal一個C-functions的Dll還蠻容易的,可以參考[3] (注意,如果使用visual studio系列,把.so換成.dll就可以了)。
如果更複雜一些,需要marshal C++ class的Dll話(unmanaged Dll),可以參考[2]。
主要的做法就是利用C-functions的做法為該Class做封裝(Wrap),例如說可以提供function-based的方式存取以開發/設計好的class。(不過要Wrap的話有點複雜就是了 :( )
此外,如果要用C-function的marshal,需要額外注意C與C++之間的call convention的差異[4]。
底下列出小弟測試好的程式碼:
1. 定義已編好的C-functions DLL
---------- c_MathFuncsDll.h----------
#ifndef c_MathFuncsDll_H #define c_MathFuncsDll_H #include stdio.h; extern "C"{ // Returns a + b __declspec(dllexport) double Add(double a, double b); // Returns a - b __declspec(dllexport) double Subtract(double a, double b); // Returns a * b __declspec(dllexport) double Multiply(double a, double b); // Returns a / b __declspec(dllexport) double Divide(double a, double b); } #endif
---------- c_MathFuncsDll.cpp----------
#include "c_MathFuncsDll.h" double Add(double a, double b) { return a + b; } double Subtract(double a, double b) { return a - b; } double Multiply(double a, double b) { return a * b; } double Divide(double a, double b) { if (b == 0) { return -1; } return a / b; }
1. 定義要呼叫C-functions Dll的C#檔(xxx/c_MathFuncsDll.dll為欲使用的library檔案)
using System; using System.Runtime.InteropServices; namespace Csharp_MyMathFuncs { class Program { [DllImport("xxx/c_MathFuncsDll.dll", EntryPoint = "Add")] static extern double Add(double a, double b); [DllImport("xxx/c_MathFuncsDll.dll", EntryPoint = "Subtract")] static extern double Subtract(double a, double b); [DllImport("xxx/c_MathFuncsDll.dll", EntryPoint = "Multiply")] static extern double Multiply(double a, double b); [DllImport("xxx/c_MathFuncsDll.dll", EntryPoint = "Divide")] static extern double Divide(double a, double b); static void Main(string[] args) { double d1 = 5.0d; double d2 = 20.0d; Console.Write(Add(d1,d2)); } } }
參考連結:
[1] Walkthrough: Creating and Using a Dynamic Link Library
[2] How to Marshal a C++ Class
[3] PInvoke ( How to Call C from C# )
[4] LIst of Calling Conventions and Mangling Names in C++