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):

  1. shared_object - C# Class project (.Net 4.5.1)
  2. mixedAdapter - C++ CLR project
  3. 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