可以使用C ++ / CLI从本机C ++应用程序调用.NET代码吗?

时间:2021-12-26 05:26:11

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

我已经用C ++ / CLI完成了另一种方式(从.NET调用纯C ++代码),并且它(大多数情况下)都有效。

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

如何完成本机到C ++ / CLI的指导?

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

我真的不想使用COM互操作...

5 个解决方案

#1


You can always host the CLR in your native app.

您始终可以在本机应用中托管CLR。

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

如果您有一个现有的本机C ++应用程序并且想要避免使用过多的CLR来“污染”它,那么您可以只为一个特定文件打开/ clr标志,并使用标准C ++标头为其提供接口。我用一些旧的代码完成了这个。在标题中我有:

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.

因此,程序的其余部分有一个简单的API,它可以传递HICON和目标文件路径。

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

然后我有一个单独的源文件,这是唯一一个/ clr打开的文件:

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.

这样我就可以从我毛茸茸的旧C ++程序中将HICON转换为PNG文件,但是我已经从其余的代码中分离出了.NET框架的使用 - 所以如果我以后需要移植,我可以轻松地交换一个不同的实施。

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.

您可以进一步将这一点放在一个单独的DLL中,并将CLR相关的代码放在一个单独的DLL中,尽管除非您希望能够单独修补它,否则几乎没有附加价值。

#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.

“C ++ / CLI in Action”一书有一章名为“混合管理和本机代码”,在本章的“使用互操作机制”标题下,它讨论了从本机代码访问托管库和从托管代码访问本机库。当我每次阅读它时,它确实帮助我获得了概念。

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

您应该查看Unmanaged Exports,您可以将其作为NuGet包获取。这是根据作者的描述:

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.

一组编译时库(无需部署)和构建任务,使您可以将函数从托管代码导出到本机应用程序。这意味着,您可以使用C#或F#等托管语言为仅具有C-Api(如Notepad ++)的本机应用程序创建插件。 nuget包就是您所需要的。只需使用[DllExport]标记您的方法并为x86,x64或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:

从C ++ / CLI调用.NET代码非常简单。它与常规C ++非常相似。确保您的项目设置为C ++ / CLI项目,通过转到“公共属性”下的项目属性添加对.NET程序集的引用,然后将.NET对象与以下代码一起使用:

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

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

  // ...
}

#1


You can always host the CLR in your native app.

您始终可以在本机应用中托管CLR。

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

如果您有一个现有的本机C ++应用程序并且想要避免使用过多的CLR来“污染”它,那么您可以只为一个特定文件打开/ clr标志,并使用标准C ++标头为其提供接口。我用一些旧的代码完成了这个。在标题中我有:

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.

因此,程序的其余部分有一个简单的API,它可以传递HICON和目标文件路径。

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

然后我有一个单独的源文件,这是唯一一个/ clr打开的文件:

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.

这样我就可以从我毛茸茸的旧C ++程序中将HICON转换为PNG文件,但是我已经从其余的代码中分离出了.NET框架的使用 - 所以如果我以后需要移植,我可以轻松地交换一个不同的实施。

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.

您可以进一步将这一点放在一个单独的DLL中,并将CLR相关的代码放在一个单独的DLL中,尽管除非您希望能够单独修补它,否则几乎没有附加价值。

#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.

“C ++ / CLI in Action”一书有一章名为“混合管理和本机代码”,在本章的“使用互操作机制”标题下,它讨论了从本机代码访问托管库和从托管代码访问本机库。当我每次阅读它时,它确实帮助我获得了概念。

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

您应该查看Unmanaged Exports,您可以将其作为NuGet包获取。这是根据作者的描述:

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.

一组编译时库(无需部署)和构建任务,使您可以将函数从托管代码导出到本机应用程序。这意味着,您可以使用C#或F#等托管语言为仅具有C-Api(如Notepad ++)的本机应用程序创建插件。 nuget包就是您所需要的。只需使用[DllExport]标记您的方法并为x86,x64或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:

从C ++ / CLI调用.NET代码非常简单。它与常规C ++非常相似。确保您的项目设置为C ++ / CLI项目,通过转到“公共属性”下的项目属性添加对.NET程序集的引用,然后将.NET对象与以下代码一起使用:

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

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

  // ...
}