After turning to. net, there are still old modules on hand to be reused. Maybe these modules are written in Delphi, maybe C/C ++, or other programming languages ...... To port them to. Net or call them in. net, To be or not to be, that is a question.
Here, I took a few notes on several scenarios I encountered at work. However, this does not include the abnormal need to completely use C # to rewrite the program originally written in C ++. When you are asked to do this, please think twice ...... This is a kind of inhuman torture.
Scenario 1: Call windowsapi or DLL in. net.
This is a common requirement. Generally, for simple function calls, C #/VB. NET can be directly used, and functions can be called through the dllimport attribute packaging. For example:
[Dllimport ("kernel32.dll", entrypoint = "movefilew", setlasterror = true,
Charset = charset. Unicode, exactspelling = true,
Callingconvention = callingconvention. stdcall)]
Public static extern bool movefile (string SRC, string DST );
Because there are many people using windowsapi, there is a dedicated wiki site to collect information in this area: http://www.pinvoke.net/, which is very helpful for common users. Of course, if you have relevant materials and examples, you can also contribute your strength and help others.
Scenario 2: Use hosted C ++ to package existing DLL for C # Call
When the parameters or return values of a function are complex, or there are many functions, this method is really a torment for people. These interfaces and definitions often require thousands of lines of code, and cannot be guaranteed to be correct. These errors are often displayed at runtime, and even some errors may cause memory leakage or other more concealed errors.
In this case, C ++/managed code is the most reasonable choice. Because the hosted C ++ code can directly reference the original header file and directly call the unmanaged function without declaring it. In this way, the workload is reduced and errors are avoided. The disadvantage is that this method will add a DLL. Note that hosted and unmanaged strings are different and need to be converted (especially Unicode string and multi-byte String Conversion ).
Take movefile as an example. This is relatively simple:
# Include <windows. h>
# Include <vcclr. h>
Using namespace system;
Namespace wrapper
{
Public ref class apiwrapper {
Public:
Bool static movefile (string ^ lpexistingfilename, string ^ lpnewfilename)
{
Pin_ptr <const wchar_t> src = ptrtostringchars (lpexistingfilename );
Pin_ptr <const wchar_t> DST = ptrtostringchars (lpnewfilename );
Return: movefile (SRC, DST );
}
};
}
Then, in C #, reference the DLL file generated by the above code, you can directly call it:
Wrapper. apiwrapper. movefile (@ "C: \ Debug. log", @ "C: \ debug.txt ");
If the original code is based on COM, it would be great. Ide such as Visual Studio will automatically generate a DLL for packaging for you to call. Of course, manual encoding for special needs is another thing.
Scenario 3: The original C ++ code, which is packaged and called by C.
The original code of C ++ can be directly compiled into managed code. MFC or ATL ...... In this way, it seems that the most powerful programming language in. NET is C ++: it can not only write hosted programs, but even compile the Standard C ++ code into a hosted program! In fact, the most powerful part of VC ++ lies in the ability to write programs that mix hosted and unmanaged code !!! In this way, the biggest benefit is not only to directly compile key code into unmanaged code, but also to avoid being decompiled.
Assume that the existing C ++ code is as follows:
Class unmanagedclass {
Public:
Lpcwstr getpropertya () {return l "Hello! ";}
Void methodb (lpcwstr ){}
};
We only need to add another packaging class to the project file:
Namespace wrapper
{
Public ref class managedclass {
Public:
// Allocate the native object on the C ++ heap via a constructor
Managedclass (): m_impl (New unmanagedclass ){}
// Deallocate the native object on a destructor
~ Managedclass (){
Delete m_impl;
}
Protected:
// Deallocate the native object on the finalizer just in case no destructor is called
! Managedclass (){
Delete m_impl;
}
Public:
Property string ^ get_propertya {
String ^ get (){
Return gcnew string (m_impl-> getpropertya ());
}
}
Void methodb (string ^ thestring ){
Pin_ptr <const wchar> STR = ptrtostringchars (thestring );
M_impl-> methodb (STR );
}
PRIVATE:
Unmanagedclass * m_impl;
};
}
Then, change the compilation option to "use public Language extension/CLR. In this way, we can compile the code into a DLL file and call it in other. NET languages.
Finally, C # can call the C ++ class like the following code:
Managedclass MC = new managedclass ();
MC. methob ("hello ");
String S = mc. get_propertya;
Scenario 4: How to mix managed and unmanaged code in managed C ++ code
It is very easy to use, as long as the program starts from # pragma unmanaged compilation instructions, one-rate compilation into unmanaged code; to restore to managed code, you just need to use # pragma managed. For example:
# Pragma unmanaged
# Include <iostream>
Using namespace STD;
Template <typename T>
Void F (t ){
Cout <t <Endl;
}
# Pragma managed
Using namespace system;
Void M (string ^ s ){
Console: writeline (s );
}
Void main (){
F ("hello ");
M ("world ");
}
After the EXE file is generated, use the decompilation program to view the f function:
[Preservesig, methodimpl (methodimploptions. Unmanaged, methodcodetype = methodcodetype. Native), suppressunmanagedcodesecurity]
Public static unsafe void modopt (callconvcdecl) F <char const *> (sbyte modopt (issignunspecifiedbyte) modopt (isconst )*);
The source code is not visible, and the method property is marked as unmanaged.
If # pragma unmanaged is not added, the decompiled F function is:
Internal static unsafe void modopt (callconvcdecl) F <char const *> (sbyte modopt (issignunspecifiedbyte) modopt (isconst) * t)
{
STD. basic_ostream <char, STD: char_traits <char>. <(STD. operator <struct STD: char_traits <char> (* (basic_ostream <char, STD: char_traits <char> * modopt (isimplicitlydereferenced )*) & __ imp_std.cout), (basic_ostream <char, STD: char_traits <char> * modopt (Signature) modopt (callconvcdecl) * (basic_ostream <char, STD :: char_traits <char> * modopt (isimplicitlydereferenced) _ UNEP @? Endl @ STD $ fyaaav? $ Basic_ostream @ du? $ Char_traits @ d @ STD @ 1 @ aav21 @ Z );
}
The function content is clear at a glance. If your function does not call class libraries that are hard to understand, the decompiled code is almost the same as the source code.
Happy moment: I only know C ++ does not understand. Net does not understand C #. How to Write. net programs?
It is very simple. You can still use your c ++ to write your program. After testing that there is no error, change the compilation option to/CLR. Okay, rebuild. Your program is now.. net.
Spoof: "I would like to ask, when the existing C ++ code can be directly encapsulated and called by C #, instead of calling the DLL, that is, the DLL is not generated, can I directly call the VC project source file in C?"
I think, do you mean that the current C ++ source code doesn't need to be converted into C # source code, but you want to compile it with C.
So I gave an extremely abnormal method. However, I do not recommend using this abnormal method. The method is as follows:
1. First, use the C ++ source code, use the CLR compilation option, and compile it into the. NET assembly (DLL file ).
2. Use reflector and other decompilation software to decompile the code into C # and export the code (reflector has a dedicated export plug-in ).
3. Add the exported C # code to the newly written C # code for compilation.
The code generated by this method is terrible. It is strongly recommended that you do not lose the C ++ source code. Otherwise, the consequences will be borne by yourself.