生活随笔
收集整理的這篇文章主要介紹了
Windows 平台下的C++代理类(供C # 使用)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
轉自 :? http://blog.csdn.net/starlee/article/details/2864588
現在在Windows下的應用程序開發,VS.Net占據了絕大多數的份額。因此很多以前搞VC++開發的人都轉向用更強大的VS.Net。在這種情況下,有很多開發人員就面臨了如何在C#中使用C++開發好的類的問題。下面就用一個完整的實例來詳細說明怎樣用托管C++封裝一個C++類以提供給C#使用。
??? 比如,現在有一個工程名為NativeCppDll的由C++編寫的DLL,里面輸出了一個CPerson類。下面是具體的代碼:
#pragma?once #ifndef?LX_DLL_CLASS_EXPORTS ????#define?LX_DLL_CLASS?__declspec(dllexport) #else ????#define?LX_DLL_CLASS?__declspec(dllimport) #endif class?LX_DLL_CLASS?CPerson { public: ????CPerson(); ????CPerson(const?wchar_t?*pName,?const?wchar_t?cSex,?int?iAge); ????void?SetName(const?wchar_t?*pName); ????wchar_t?*?GetName(); ????void?SetSex(const?wchar_t?cSex); ????wchar_t?GetSex(); ????void?SetAge(int?iAge); ????int?GetAge(); ????wchar_t?*?GetLastError(); private: ????wchar_t?m_szName[128]; ????wchar_t?m_cSex; ????int?m_iAge; ????wchar_t?m_szLastError[128]; ????void?ShowError(); }; #include?"stdafx.h" #include?"NativeCppDll.h" #include?<iostream> #include?<tchar.h> using?namespace?std; CPerson::CPerson() { ????wcscpy_s(m_szName,?_T("No?Name")); ????m_cSex?=?'N'; ????m_iAge?=?0; ????wcscpy_s(m_szLastError,?_T("No?Error")); } CPerson::CPerson(const?wchar_t?*pName,?const?wchar_t?cSex,?int?iAge) { ????wcscpy_s(m_szLastError,?_T("No?Error")); ????SetName(pName); ????SetSex(cSex); ????SetAge(iAge); } void?CPerson::SetName(const?wchar_t?*pName) { ????if?((pName?==?NULL)?||?(wcslen(pName)?==?0)?||?(wcslen(pName)?>?127)) ????{ ????????wcscpy_s(m_szName,?_T("No?Name")); ????????wcscpy_s(m_szLastError,?_T("The?length?of?the?input?name?is?out?of?range.")); ????????ShowError(); ????????return; ????} ????wcscpy_s(m_szName,?pName); } wchar_t?*?CPerson::GetName() { ????return?m_szName; } void?CPerson::SetSex(const?wchar_t?cSex) { ????if?((cSex?!=?'F')?&&?(cSex?!=?'M')?&&?(cSex?!=?'m')?&&?(cSex?!=?'f')) ????{ ????????m_cSex?=?'N'; ????????wcscpy_s(m_szLastError,?_T("The?input?sex?is?out?of?[F/M].")); ????????ShowError(); ???????? ????????return; ????} ????m_cSex?=?cSex; } wchar_t?CPerson::GetSex() { ????return?m_cSex; } void?CPerson::SetAge(int?iAge) { ????if?((iAge?<?0)?||?(iAge?>?150)) ????{ ????????m_iAge?=?0; ????????wcscpy_s(m_szLastError,?_T("The?input?age?is?out?of?range.")); ????????ShowError(); ????????return; ????} ????m_iAge?=?iAge; } int?CPerson::GetAge() { ????return?m_iAge; } wchar_t?*?CPerson::GetLastError() { ????return?m_szLastError; } void?CPerson::ShowError() { ????cerr?<<?m_szLastError?<<?endl; }
??? 這是一個很典型的由C++開發的DLL,輸出一個完整的C++類。如果現在要求開發一個C#工程,需要用到這個DLL中輸出的C++類CPerson,該怎么辦呢?針對這個例子來說,類CPerson非常小,可以用C#重新寫一個跟這個C++類一樣的類。可是,如果需要的C++類很大,或者很多的時候,重寫工程將非常龐大。而且這樣沒有對現有的代碼進行重用,浪費了現有資源,開發起來費時費力。
??? 當然,還是有方法解決這個問題的。那就是用托管C++將C++類給封裝一下,然后再提供給C#來使用。下面就用代碼來詳細說明怎樣用托管C++來封裝上面的那個C++類。
??? 首先,要創建一個托管C++的DLL工程ManageCppDll,然后在里面添加下面的代碼:???
#pragma?once #define?LX_DLL_CLASS_EXPORTS #include?"../NativeCppDll/NativeCppDll.h" using?namespace?System; namespace?ManageCppDll? { ????public?ref?class?Person ????{ ???? ????public: ????????Person(); ????????Person(String?^?strName,?Char?cSex,?int?iAge); ????????~Person(); ????????property?String?^?Name ????????{ ????????????void?set(String?^?strName); ????????????String?^?get(); ????????} ????????property?Char?Sex ????????{ ????????????void?set(Char?cSex); ????????????Char?get(); ????????} ????????property?int?Age ????????{ ????????????void?set(int?iAge); ????????????int?get(); ????????} ????????String?^?GetLastError(); ????private: ???????? ????????CPerson?*m_pImp; ????}; };
??? 從這個頭文件就能看出來,這是對C++類CPerson的包裝。類Person的所有公有成員函數都跟C++類CPerson一樣,只不過成員函數的參數和返回值就改成了托管C++的類型,這也是讓類Person能在C#中使用的首要條件。當然只需要對公有成員函數進行封裝,對于保護成員函數和私有成員函數則不必做任何封裝。
??? 類Person僅有一個私有的成員變量:一個類CPerson的指針。而類Person的所有成員函數的實現都是靠這個CPerson指針來調用類CPerson的相應成員函數來實現。
??? 下面是具體的實現代碼:
#include?"stdafx.h" #include?"ManageCppDll.h" #include?<vcclr.h> namespace?ManageCppDll? { ???? ???? ????Person::Person() ????{ ????????m_pImp?=?new?CPerson(); ????} ????Person::Person(String?^?strName,?Char?cSex,?int?iAge) ????{ ???????? ????????pin_ptr<const?wchar_t>?wcName?=?PtrToStringChars(strName); ????????m_pImp?=?new?CPerson(wcName,?cSex,?iAge); ????} ????Person::~Person() ????{ ???????? ????????delete?m_pImp; ????} ????void?Person::Name::set(String?^?strName) ????{ ????????pin_ptr<const?wchar_t>?wcName?=?PtrToStringChars(strName); ????????m_pImp->SetName(wcName); ????} ????String?^?Person::Name::get() ????{ ????????return?gcnew?String(m_pImp->GetName()); ????} ????void?Person::Sex::set(Char?cSex) ????{ ????????m_pImp->SetSex(cSex); ????} ????Char?Person::Sex::get() ????{ ????????return?m_pImp->GetSex(); ????} ????void?Person::Age::set(int?iAge) ????{ ????????m_pImp->SetAge(iAge); ????} ????int??Person::Age::get() ????{ ????????return?m_pImp->GetAge(); ????} ????String?^?Person::GetLastError() ????{ ????????return?gcnew?String(m_pImp->GetLastError()); ????} };
??? 如果要在C#中使用類Person,首先要添加對ManageCppDll.dll的引用,然后就可以像用普通的C#類一樣的使用類Person了。比如下面這樣的代碼:
using?ManageCppDll; Person?person?=?new?Person(); person.Name?=?"StarLee"; person.Sex?=?'M'; person.Age?=?28;
??? 熟悉設計模式的看了上面的代碼肯定會發現,這樣的設計跟BRIDGE模式如出一轍。其實,上面的方法也算是一種BRIDGE模式,由托管C++充當了C#中使用用C++開發的類的橋梁。另外,這種形式也可以理解為ADAPTER模式,托管C++類Person就是C++類CPerson的一個適配器。通過這個橋梁,可以很容易的重用以前用C++開發的類,讓這些C++類繼續在C#中發揮它們的效用,讓開發變得事半功倍。
總結
以上是生活随笔為你收集整理的Windows 平台下的C++代理类(供C # 使用)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。