|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
AbstractC++ managed code introduced us a new string type, namely System.String. You can imagine though, that some conversion functions are needed to work with this new string type when mixing managed and unmanaged code in your project. IntroductionManaged code runs under the .NET runtime Execution Engine, which gives you the advantage of garbage collection, JIT, etc. Currently, as a programmer you can choose between C#, C++ managed extensions and VB.NET to write your managed code (there are also .NET versions of FORTRAN and COBOL, however, these are not widely available at the time of writing - ed. ). However, in some cases, you do want to mix your managed code with unmanaged code : either you still want to continue using your current source code base and plug it in .NET, maybe you want to build .NET interfaces around your existing code, or you decide to write some routines unmanaged because of performance issues. Mixing managed and unmanaged code/CLR If you want to mix managed and unmanaged code in the same sources, your code should be compiled with the /CLR compiler option. This means that - by default – all your functions are managed. For compilation: members of managed classes as well as functions who use managed data types only compile as managed. #pragma managed #pragma unmanaged Using the managed and unmanaged pragmas enables function-level control for compiling functions managed or unmanaged. StringsUnmanaged C++ applications use string types composed of
ASCII/UNICODE characters ( In the MSDN documentation you will find that : "Regular C++ wide-character string literals (prefixed by L) and managed string literals (prefixed by S) can be used interchangeably where String types are expected. However, the reverse is not true. Managed string literals can not be used where C++ string types are expected." So, in functions where a For example, consider this piece of code (written in C++) : #pragma unmanaged #include "Windows.h" class CUnmanagedClass { public: void ShowMessageBox(char* szMessage) { ::MessageBox(NULL, szMessage , "CUnmanagedClass", MB_OK); } }; #pragma managed #using <mscorlib.dll> using namespace System; using namespace System::Runtime::InteropServices; __gc class CManagedClass { public: void ShowMessage(System::String* strMessage) { System::Console::WriteLine(strMessage); } }; int main(void) { String* strMessage = S"Hello world"; CManagedClass* pCManagedClass = new CManagedClass(); pCManagedClass->ShowMessage(strMessage); char* szMessage = (char*)Marshal::StringToHGlobalAnsi(strMessage); CUnmanagedClass cUnmanagedClass; cUnmanagedClass.ShowMessageBox(szMessage); Marshal::FreeHGlobal((int)szMessage); return 0; } The unmanaged class char* szMessage = (char*)Marshal::StringToHGlobalAnsi(strMessage); And freeing the memory again with FreeHGlobal: Marshal::FreeHGlobal((int)szMessage);
In the sample, I used Data marshaling when making calls between managed and unmanaged code when using P/Invoke in C# In C#, unmanaged methods are called by using the Runtime's Platform Invocation Service (P/Invoke). Your data also needs to be marshaled then : the marshalling attributes can be specified in the dllimport statement. Consider the following lines of code (written in C#): [DllImport("user32.dll")] public static extern int MessageBoxA(int h, [MarshalAs(UnmanagedType.LPStr)]string m, [MarshalAs(UnmanagedType.LPStr)]string c, int type); public static int Main(string args []) { MessageBoxA(0, "Hello World!", "My Message Box", 0); return 0; } The function ConclusionMixing managed and unmanaged code can be very powerful, and it gives us – programmers - a lot more freedom to decide on how to code. However, we should be aware that mixing these technologies introduces some extra difficulties and should be taken care off from the beginning, when starting to design your .NET applications.
|
||||||||||||||||||||||