Calling managed code from unmanaged
- Tutorial
- Recovery mode
![image](https://habrastorage.org/web/281/9f8/c1d/2819f8c1d1b74974b5027871e467d4ba.jpg)
Our example will consist of three projects:
- MixedLibrary - C ++ / CLI
- SimpleLibrary - C #
- Win32App - C ++
![image](https://habrastorage.org/web/2df/521/cdd/2df521cdd15a466cb1943c1f5bc061ae.png)
Let's start with the simplest - SimpleLibrary . This library contains one simple service that adds two numbers and prints the result to the console:
public class Service
{
public void Add(Int32 a, Int32 b)
{
Console.WriteLine("Hello from Managed Code!");
Console.WriteLine(String.Format("Result: {0}", a + b));
}
}
Now let's move on to the MixedLibrary library . This library contains a wrapper class over our SimpleService. The contents of the CppService.h file:
// Директивы препроцессора нужны, чтобы компилятор сгенерировал записи
// об экспорте класса из библиотеки
#ifdef INSIDE_MANAGED_CODE
# define DECLSPECIFIER __declspec(dllexport)
# define EXPIMP_TEMPLATE
#else
# define DECLSPECIFIER __declspec(dllimport)
# define EXPIMP_TEMPLATE extern
#endif
namespace MixedLibrary
{
class DECLSPECIFIER CppService
{
public:
CppService();
virtual ~CppService();
public:
void Add(int a, int b);
private:
void * m_impl;
};
}
And the contents of the CppService.cpp file:
#include "CppService.h"
using namespace System;
using namespace System::Runtime::InteropServices;
using namespace SimpleLibrary;
namespace MixedLibrary
{
CppService::CppService()
{
Service^ service = gcnew Service();
m_impl = GCHandle::ToIntPtr(GCHandle::Alloc(service)).ToPointer();
}
CppService::~CppService()
{
GCHandle handle = GCHandle::FromIntPtr(IntPtr(m_impl));
handle.Free();
}
void CppService::Add(int a, int b)
{
GCHandle handle = GCHandle::FromIntPtr(IntPtr(m_impl));
Service^ service = safe_cast(handle.Target);
service->Add(a, b);
}
}
Also, for compilation, you need to add the INSIDE_MANAGED_CODE preprocessor directive:
![image](https://habrastorage.org/web/3fb/aa8/3fd/3fbaa83fd72a4f0d810606fef0f2c45a.png)
And the final touch is our usual unmanaged application:
#include "stdafx.h"
#pragma comment(lib, "../Debug/MixedLibrary.lib")
#include
#include "../MixedLibrary/CppService.h"
using namespace std;
using namespace MixedLibrary;
int main()
{
CppService* service = new CppService();
service->Add(5, 6);
cout << "press any key..." << endl;
getchar();
}
And, of course, the result:
![image](https://habrastorage.org/web/e32/bfd/285/e32bfd2858574fe5a4155cc4491a1575.png)
Author: nikitam