Now the application development under Windows, VS. NET occupies the majority of the share. So many people who used to develop VC + + have turned to use more powerful vs.net. In this case, there are many developers who are faced with the problem of how to use C + + to develop good classes in C #. Here is a complete example of how to encapsulate a C + + class in Managed C + + for use in C #.
For example, there is now a DLL written by C + + with the project named Nativecppdll, which outputs a CPerson class. Here is the specific code:
- NativeCppDll.h
- #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 ();
- };
- NativeCppDll.cpp
- #include "stdafx.h"
- #include "NativeCppDll.h"
- #include
- #include
- 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 was out ofrange."));
- 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;
- }
This is a typical DLL developed by C + +, outputting a complete C + + class. What if you need to develop a C # project now and use the C + + class CPerson output from this DLL? For this example, class CPerson is very small and can be used to re-write a class like this C + + class in C #. However, if the required C + + classes are large, or many times, rewriting works will be very large. And it's not reusing existing code, wasting existing resources, and creating time-consuming and laborious development.
Of course, there are ways to solve this problem. That is to encapsulate the C + + class with managed C + + and then provide it to C # for use. The following code is used to describe in detail how to encapsulate the C + + class with managed C + +.
First, create a managed C + + DLL project Managecppdll, and add the following code inside:
- ManageCppDll.h
- #pragma once
- #define Lx_dll_class_exports
- #include ". /nativecppdll/nativecppdll.h "
- using namespace System;
- namespace Managecppdll
- {
- Public ref class person
- {
- //Wrapper public member functions for all class CPerson
- 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:
- //Class CPerson pointer, used to invoke the member function of class CPerson
- CPerson *m_pimp;
- };
- };
As you can see from this header file, this is the wrapper for C + + class CPerson. All public member functions of the class person are the same as the C + + class CPerson, except that the parameters and return values of the member functions are changed to the managed C + + type, which is the first condition for the class person to be used in C #. Of course, only the public member functions need to be encapsulated, and no encapsulation is necessary for the protection of member functions and private member functions.
The class person has only one private member variable: A pointer to a class CPerson. The implementation of all member functions of the class person is accomplished by invoking the corresponding member function of the class CPerson by this cperson pointer.
Here is the specific implementation code:
- ManageCppDll.cpp
- #include "stdafx.h"
- #include "ManageCppDll.h"
- #include
- namespace Managecppdll
- {
- //Create an object of class CPerson in the constructor and destroy the object in the destructor
- //All member function implementations are implemented by pointer M_pimp calling the corresponding member function of class CPerson
- Person::P Erson ()
- {
- M_pimp = new CPerson ();
- }
- Person::P Erson (String ^ strName, Char csex, int iage)
- {
- //Convert string to a pointer that C + + can recognize
- pin_ptr<</span>const wchar_t> wcname = PtrToStringChars (strName);
- M_pimp = new CPerson (Wcname, Csex, iage);
- }
- Person::~person ()
- {
- //Delete the CPerson object in the destructor
- Delete m_pimp;
- }
- void Person::name::set (String ^ strName)
- {
- pin_ptr<</span>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 ());
- }
- };
If you want to use class person in C #, first add a reference to ManageCppDll.dll, and then you can use the class person as you would with a normal C # class. such as the following code:
- using Managecppdll;
- Person person = New person ();
- Person. Name = "Starlee";
- Person. Sex = ' M ';
- Person. Age = 28;
Familiar with the design pattern to see the above code will certainly find that this design is the same as bridge mode. In fact, the above method is also a bridge pattern, managed C + + serves as a bridge for C # to use classes developed in C + +. In addition, this form can also be understood as adapter mode, managed C + + class person is the C + + class CPerson an adapter. With this bridge, it is easy to reuse classes that were previously developed in C + +, so that these C + + classes continue to play their role in C #, making development more effective.
Blog Source: http://blog.csdn.net/starlee/article/details/2864588
Classes written in C # using C + +-encapsulated with managed C + + [go]