Mixed Mode Adapter for Native C++
So our customer's goal was to update their native C++ application with support for calling a static instance of a C# class and share that instance with native and managed clients from within the same process space. This is a sample created to demonstrate one method to accomplish this task. (Many thanks to Rodney Viana for helping solve several critical problems I ran into making this sample work (if you have not downloaded Rodney's debugging extension - what are you waiting for? https://netext.codeplex.com/)
We chose a mixed C++/CLI adapter as a solution:
Visual C++ supports the use of the Standard C++ Library, the Common RunTime library (CRT), ATL, and MFC for applications compiled with /clr (Common Language Runtime Compilation). This allows existing applications that use these libraries to use .NET Framework features as well. From <https://msdn.microsoft.com/en-us/library/ms173268.aspx>
Solution contains three projects (Link to Visual Studio Solution: https://1drv.ms/1A45F7Q):
- shared_object - C# Class project (.Net 4.5.1)
- mixedAdapter - C++ CLR project
- client - C++ Win32
shared_object
This DLL exposes a simple singleton class with one method named Hello_World. It returns a string to the caller.
mixedAdapter
This is the C++ CLR project which acts as an adapter or wrapper. It can been called from C++ natively and it can add managed references. I have a project reference to shared_object. Make sure to add this to your class __declspec(dllexport) so your client project can import later:
1: #include <msclr\marshal_cppstd.h>
2:
3: #include <string>
4:
5: using namespace System;
6:
7: using namespace shared_object;
8:
9: #pragma native
10:
11: namespace mixedAdapter
12:
13: {
14:
15: class __declspec(dllexport) InTheMix
16:
17: {
18:
19: public:
20:
21: std::string SayHello()
22:
23: {
24:
25: SingletonObj^ instance = SingletonObj::GetInstance();
26:
27: std::string returnValue = msclr::interop::marshal_as<std::string>(instance->Hello_World());
28:
29: return returnValue;
30:
31: }
32:
33: };
34:
35: }
36:
client
Client has a header file with __declspec(dllimport) to import the definition from the lib file
1: #include <string>
2:
3: namespace mixedAdapter
4:
5: {
6:
7: class __declspec(dllimport) InTheMix
8:
9: {
10:
11: public:
12:
13: std::string SayHello();
14:
15: };
16:
17: }
18:
And the client.cpp file has #pragma comment (lib,"mixedAdapter") added which is a hint to the linker to find the correct lib file. To get this working, I opened to project properties of client, under Linker, I selected "Additional Library Directories" and put in the path of my mixedAdapter.lib file. Without this step you may get a complier error.
1: #include "stdafx.h"
2:
3: #include "mixedAdapter.h"
4:
5: using namespace mixedAdapter;
6:
7: #pragma comment (lib,"mixedAdapter")
8:
9: int _tmain(int argc, _TCHAR* argv[])
10:
11: {
12:
13: std::string str;
14:
15: InTheMix myClass;
16:
17: str = myClass.SayHello();
18:
19: printf("%s", str.c_str());
20:
21: return 0;
22:
23: }
24:
Test:
C:\Visual Studio 2013\Projects\mixedAdapter\Debug>client.exe
Hello World
Comments
Anonymous
March 09, 2015
Yes, this test was successful. Thanks for the post.Anonymous
March 09, 2015
Thanks