目錄:
1.非托管方式
2.托管方式
3.介紹 extern "C"
4.介紹 DllImport
1.非托管方式
第一種,非托管方式:調用類和方法https://www.codeproject.com/Articles/18032/How-to-Marshal-a-C-Class
非托管方式,只能調用函數,並且函數在extern "C"的體里面
有一下幾種方式,把函數都寫了,把接口寫了。
//創建對象的方法 extern "C" EXAMPLEUNMANAGEDDLL_API CUnmanagedTestClass* CreateTestClass() { return new CUnmanagedTestClass(); } //釋放對象 extern "C" EXAMPLEUNMANAGEDDLL_API void DisposeTestClass(CUnmanagedTestClass* pObject) { if(pObject != NULL) { delete pObject; pObject = NULL; } } //調用函數 extern "C" EXAMPLEUNMANAGEDDLL_API void CallPassInt(CUnmanagedTestClass* pObject, int nValue) { if(pObject != NULL) { pObject->PassInt(nValue); } } //調用函數 extern "C" EXAMPLEUNMANAGEDDLL_API void CallPassString(CUnmanagedTestClass* pObject, char* pchValue);
extern "C"{
EXAMPLEUNMANAGEDDLL_API char* CallReturnString(CUnmanagedTestClass* pObject)
}
C++的調用
把生成的TestClassDLL.dll放到 bin/Debug/下,然后在C#中調用
public class CSUnmanagedTestClass : IDisposable { #region PInvokes [DllImport("TestClassDLL.dll")] static private extern IntPtr CreateTestClass(); [DllImport("TestClassDLL.dll")] static private extern void DisposeTestClass(IntPtr pTestClassObject); [DllImport("TestClassDLL.dll")] static private extern void CallPassInt(IntPtr pTestClassObject, int nValue); . . . #endregion PInvokes #region Members private IntPtr m_pNativeObject; // Variable to hold the C++ class's this pointer #endregion Members public CSUnmanagedTestClass() { // We have to Create an instance of this class through an exported // function this.m_pNativeObject = CreateTestClass(); } public void Dispose() { Dispose(true); } protected virtual void Dispose(bool bDisposing) { if(this.m_pNativeObject != IntPtr.Zero) { // Call the DLL Export to dispose this class DisposeTestClass(this.m_pNativeObject); this.m_pNativeObject = IntPtr.Zero; } if(bDisposing) { // No need to call the finalizer since we've now cleaned // up the unmanaged memory GC.SuppressFinalize(this); } } // This finalizer is called when Garbage collection occurs, but only if // the IDisposable.Dispose method wasn't already called. ~CSUnmanagedTestClass() { Dispose(false); } #region Wrapper methods public void PassInt(int nValue) { CallPassInt(this.m_pNativeObject, nValue); } . . . #endregion Wrapper methods }
2.托管方式
我手上有一個C++寫的類(NativeClass),想在C#下調用這個類,可是C#是沒有簡單的像Dllimport這樣的方法獲取非托管C++ dll里的類。我的解決方法是,生成一個托管C++的dll,然后在C#下引用這個dll。因為托管代碼與非托管代碼是不能在一個文件里混編的,所以我必須將非托管C++寫的NativeClass用托管C++的手段封裝一下,然后生成一個dll,以供C#調用。
https://www.cnblogs.com/stemon/p/4246165.html
3.介紹 extern "C"
:https://www.cnblogs.com/xiangtingshen/p/10980055.html
extern "C"包含雙重含義,
- 被extern "C"修飾的變量和函數是按照C語言方式進行編譯和鏈接的:這點很重要!!!!
-
extern "C"的使用要點總結
1,可以是如下的單一語句:
extern "C" double sqrt(double);
2,可以是復合語句, 相當於復合語句中的聲明都加了extern "C"
extern "C" { double sqrt(double); int min(int, int); }
3,可以包含頭文件,相當於頭文件中的聲明都加了extern "C"
extern "C" { #include <cmath> }
4.介紹 DllImport
https://www.cnblogs.com/fer-team/archive/2017/12/13/8033413.html
要使用DllImport需要引用命名空間: System.Runtime.InteropServices;
DllImport 屬性定義
如下:
namespace System.Runtime.InteropServices { [AttributeUsage(AttributeTargets.Method)] public class DllImportAttribute: System.Attribute { public DllImportAttribute(string dllName){...} //定位參數為dllName public CallingConvention CallingConvention; //入口點調用約定 public CharSet CharSet; //入口點采用的字符接 public string EntryPoint; //入口點名稱 public bool ExactSpelling; //是否必須與指示的入口點拼寫完全一致,默認false public bool PreserveSig; //方法的簽名是被保留還是被轉換 public bool SetLastError; //FindLastError方法的返回值保存在這里 public string Value {get {...}} } }
說明:
1、DllImport只能放置在方法聲明上。
2、DllImport具有單個定位參數:指定包含被導入方法的 dll 名稱的 dllName 參數。
3、DllImport具有五個命名參數:
a、CallingConvention 參數指示入口點的調用約定。如果未指定CallingConvention,則使用默認值CallingConvention.Winapi。
b、CharSet參數指定用在入口點的字符集。如果未指定CharSet,則使用默認值CharSet.Auto。
c、EntryPoint參數給出dll中入口點的名稱。如果未指定EntryPoint,則使用方法本身的名稱。
d、ExactSpelling參數指示EntryPoint是否必須與指示的入口點的拼寫完全匹配。如果未指定ExactSpelling,則使用默認值false。
e、PreserveSig參數指示方法的簽名被保留還是被轉換。當簽名被轉換時,它被轉換為一個具有HRESULT返回值和該返回值的一個名為retval的附加輸出參數的簽名。如果未指定PreserveSig,則使用默認值true。
f、SetLastError參數指示方法是否保留Win32“上一錯誤”。如果未指定SetLastError,則使用默認值false。
4、它是一次性屬性類。
5、用DllImport屬性修飾的方法必須具有extern修飾符。