Can C++/CLI be used to call .NET code from native

2019-01-17 02:03发布

问题:

I've done the other way around (calling pure C++ code from .NET) with C++/CLI, and it worked (for the most part).

How is the native-to-C++/CLI direction done?

I really don't want to use COM interop...

回答1:

You can always host the CLR in your native app.



回答2:

If you have an existing native C++ app and want to avoid "polluting" it with too much CLR stuff, you can switch on the /clr flag for just one specific file and use a standard C++ header to provide an interface to it. I've done this in an old bit of code. In the header I have:

void SaveIconAsPng(void *hIcon, const wchar_t *pstrFileName);

So the rest of the program has a simple API to which it can pass an HICON and a destination filepath.

Then I have a separate source file which is the only one that has /clr switched on:

using namespace System;
using namespace System::Drawing;
using namespace System::Drawing::Imaging;
using namespace System::Drawing::Drawing2D;

#include <vcclr.h> 
#include <wchar.h>

void SaveIconAsPng(void *hIcon, const wchar_t *pstrFileName)
{
    try
    {
        Bitmap bitmap(16, 16, PixelFormat::Format32bppArgb);

        Graphics ^graphics = Graphics::FromImage(%bitmap);
        graphics->SmoothingMode = SmoothingMode::None;

        Icon ^icon = Icon::FromHandle(IntPtr(hIcon));
        graphics->DrawIcon(icon, Rectangle(0, 0, 15, 15));
        graphics->Flush();

        bitmap.Save(gcnew String(pstrFileName), ImageFormat::Png);
    }
    catch (Exception ^x)
    {
        pin_ptr<const wchar_t> unmngStr = PtrToStringChars(x->Message);
        throw widestring_error(unmngStr); // custom exception type based on std::exception
    }
}

That way I can convert HICONs into PNG files from my hairy old C++ program, but I've isolated the use of the .NET framework from the rest of the code - so if I need to be portable later, I can easily swap in a different implementation.

You could take this a stage further and put the CLR-dependent code in a separate DLL, although there would be little added value in that unless you wanted to be able to patch it separately.



回答3:

The book C++/CLI in Action has a chapter named Mixing Managed and Native Code and inside the chapter, under Working With Interop Mechanisms heading, it talks about both accessing a managed library from native code and accessing a native library from managed code. It did help me get the concepts when I read it once upon a time.



回答4:

You should take a look at Unmanaged Exports, which you can get as a NuGet package. This is the description according to the author:

A set of compile-time libraries (nothing to deploy) and a build task that enable you to export functions from managed code to native applications. That means, you can create plugins in a managed language like C# or F# for native applications that only have a C-Api (like Notepad++). The nuget package is all you need. Just mark your methods with [DllExport] and build for x86, x64 or ia64.



回答5:

Calling .NET code from C++/CLI is very straightforward. Its very similar to regular C++. Make sure your project is setup as a C++/CLI project, add a reference to your .NET assembly by going to the project properties under "Common Properties", then use your .NET objects with some code like this:

using namespace System;
using namespace System::Collections::Generic;
using namespace MyNamespace;

void MyFunctionCall()
{
  MyObject ^obj = gcnew MyObject();
  obj->MyMethod();

  // ...
}