Mix Managed and Unmanaged Code
There are a plethora of articles on how to mix managed and unmanaged code. The problem I found is that none of them really discuss how to pass anything more than simple values from managed to unmanaged code. Or they explain how to marshal managed text strings to an unmanaged char * pointer. Here are a few related links:
What I want to discuss is how to directly pass pointer to a class and be able to call that classes functions from unmanaged code. You can find my example in the SVN repository under the name ‘MixedTest’
First things first, start a new project:
1.) Open Visual studio 2005
2.) Go to File->New-> Project
3.) In the ‘Project Types’ box click ‘Visual C++’
4.) In the ‘Templates Box’ select ‘Windows Forms Application’
5.) Done. Alternatively you can simply snag my example.
Next make up a quick and gritty gui. I’m not going to go over those steps. For this example we are going to pass the MouseEventArgs from our managed form class to our unmanaged Foo class. My gui contains a ‘Panel’ with the ‘MouseOver’ event.
Unmanaged Code (Foo.h)
#pragma once #include <vcclr.h> #include "DbgConsole.h" class Foo { public: Foo(void); ~Foo(void); void MouseMove(gcroot<System::Windows::Forms::MouseEventArgs^> e); };
Unmanaged Code (Foo.cpp)
#include "StdAfx.h" #include "Foo.h" Foo::Foo(void) { } Foo::~Foo(void) { } void Foo::MouseMove(gcroot<System::Windows::Forms::MouseEventArgs^> e){ gcroot<System::Windows::Forms::MessageBox^> *msg = new gcroot<System::Windows::Forms::MessageBox^>; if(e->Button == System::Windows::Forms::MouseButtons::Left) { (*msg)->Show("Mouse Move["+e->Location.X.ToString() +"," + e->Location.Y.ToString() + "]: Left Button Down"); } }
and from our managed code(Form1.h)”
#include "Foo.h" public ref class Form1 : public System::Windows::Forms::Form { public: Form1(void) { InitializeComponent(); _foo = new Foo; } private: Foo *_foo; //.... other class specific stuff private: System::Void panel1_MouseMove(System::Object^ sender, System::Windows::Forms::MouseEventArgs^ e) { _foo->MouseMove(e); } };
gcroot is a life saver. Otherwise you have to take the time to manually cast variables back and forth. gcroot handles it all, automatically. The only problem is that the
Notice how we pass the MouseEventArgs directly to Foo, an unmanaged class? This saves us from having to pass each and every call to specific foo function although you could do that too.
If you create your own project from this post I recommend you at least take a look at my example in the repository. Every mouse movement will be recorded when the left mouse button is down and it is over our panel. Please note, each one of these will generate a text box. In my example code I also include a very simplistic Console debugger that actually uses a Windows Form and Textbox to create a fake shell. It only takes output but whatever.
