从Visual C ++调用C#代码 [英] Calling C# code from visual C++

查看:85
本文介绍了从Visual C ++调用C#代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基本上,我需要从Visual C ++代码中调用C#代码。
阅读了很多有关可能方法的文章后,我决定要使用C ++ / CLI机制。

Basically I need to call C# code from Visual C++ code. After reading lots of articles about possible ways, I decided I want to use C++/CLI mechanism.

最初,我决定我将使用C ++原生功能代码(dll库项目),他们将从CLR项目中调用某些功能,而CLR项目中将调用C#项目中的某些功能。

Initially I decided I will have some functions in C++ native code (dll library project), they will call some functions from a CLR project which will call some functions from a C# project.

之后,我想也许我可以摆脱了桥梁项目(CLR项目),因为它仅过渡到托管世界。我认为我可以创建本机项目,可以向其中添加一个c ++源文件,并且可以仅对该文件而不是整个项目启用CLR支持。
因此,这意味着我的本机项目将仅包含一个可以使用C ++ / CLI语法并表示网桥的文件。所有其他文件只是本机C ++源文件。
从设计角度来看这对吗?!

After that I thought that maybe I could get rid of the bridge project (the CLR project) since it only makes the transition to managed world. I think that I can just create my native project, and I can add a c++ source file to it and I can enable CLR support just for that file and not the entire project. So this would mean my native project will include just one file which can use C++/CLI syntax and represents the bridge . All other files are just native C++ source files. Is this right from a design perspective ?!

为了执行上述操作,我认为我必须将托管的C#dll文件添加到其他#using目录中C ++本机dll文件的属性。
问题是我不知道如何根据当前配置设置C#dll调试或发布版本的路径。

In order to do the above, I think I must add the managed C# dll file to Additional #using Directories properties of the C++ native dll File. The problem is I don't know how to set the path to C# dll debug or release versions based on current configuration.

我也知道我可以请勿将本地C ++ DLL添加到C#项目引用中。
但是看起来我可以在本地C ++项目中添加一个C#dll作为引用。怎么会 ?!这还行吗?!
如果可以将C#dll添加到本机C ++项目引用中,是否需要设置这些#using目录?!

Also I know that I can't add a native C++ DLL to a C# project references. But it looks like I can add a C# dll as a reference inside the native C++ project. How come ?! Does this even work ?! If I can add a C# dll to a native C++ project references, do I need to set those #using directories ?!

推荐答案


我可以仅对该文件而不是整个项目启用CLR支持

I can enable CLR support just for that file and not the entire project

在执行此操作与选择CLR项目模板开始之间没有有效的区别。无论哪种方式,结果都是混合模式的.NET程序集,其中包含MSIL和本机代码。在项目级别执行此操作仅会为项目中的.cpp文件设置/ clr的默认值。您也可以通过覆盖单个.cpp文件的设置(现在禁用/ clr),使用CLR项目模板来执行此操作。最终结果都是相同的。

There is no effective distinction between doing this and getting started by selecting a CLR project template. Either way the result is a mixed-mode .NET assembly, containing both MSIL and native code. Doing it at the project level merely sets the default value for /clr for the .cpp files in the project. You can also do this with a CLR project template by overriding the settings of an individual .cpp file, now disabling /clr. The end result is all the same.


我认为我必须将托管的C#dll文件添加到其他使用目录

I think I must add the managed C# dll file to Additional #using Directories

是的,这是一种方法。还可以解决您的查询,您可以在路径名中使用$(Configuration)宏。在编译时解析为调试或发布,具体取决于您构建的配置。我应该强调,这实际上不是必需的。编译器仅使用C#程序集中的元数据。只是声明。与.h文件完全相同,请注意您很少会根据配置使#include有所不同。唯一的例外情况是在C#源代码中使用 #if DEBUG 来包含/排除代码,这不是很常见。

Yes, that is one way to do it. Also solves your query, you can use the $(Configuration) macro in the path name. Resolves to "Debug" or "Release" at compile time, depending on the configuration you build. I should emphasize that this is not actually necessary. The compiler only uses the metadata in the C# assembly. Just the declarations. The exact equivalent of a .h file, note how you rarely make an #include different based on the configuration. The only corner-case is when you used #if DEBUG in your C# source code to include/exclude code, not very common.


但是看起来我可以在本地C ++项目中添加一个C#dll作为引用

But it looks like I can add a C# dll as a reference inside the native C++ project

在每个VS版本中都对此进行了修改,而不是100%确定您在做什么。实际上,添加引用时很少发生,它只是使编译器驱动程序添加 / FU编译选项。如果.cpp文件未使用/ clr编译,则它什么也不做,编译器将完全忽略它。当您在源代码中使用 #using 而不使用/ clr时,它确实会大声抱怨。否则,这两者之间没有真正的区别,只是更容易使用/ FU控制文件的路径。

This has been tinkered with in every VS version, not 100% sure what you are doing. Very little happens in practice when you add a reference, it merely gets the compiler driver to add the /FU compile option. If the .cpp file is not compiled with /clr then it does nothing, the compiler just completely ignores it. It does complain loudly when you use #using in source code and didn't use /clr. No real distinction between the two otherwise, just easier to control the path of the file with /FU.


因为它仅转换为受管理的世界

since it only makes the transition to managed world

在这里要小心一点,还有很多事情要做。您在此处执行的操作称为反向pinvoke,本机代码称为托管代码。 C ++ / CLI的主要目的是完全相反。更复杂的是,需要完成的一件很重要的事情是,CLR需要在第一次调用时被加载和初始化。这完全是自动的,由使用 __ declspec(dllexport)时自动生成的存根提供。罗伯特·吉塞克(Robert Giesecke)的非托管出口实用程序所依赖的魔术同样是您应该考虑的另一种选择。

A word of caution is appropriate here, there is a lot more going on. What you are doing here is called "reverse pinvoke", native code calling managed code. C++/CLI was primarily designed to do the exact opposite. It is more involved, the non-trivial thing that needs to happen is that the CLR needs to be loaded and initialized on the first call. That's all automagic, provided by a stub that's auto-generated when you use __declspec(dllexport). The same magic that the Robert Giesecke's "Unmanaged Exports" utility depends on, another option that you should look at.

但是它是有限的。您不能公开对象模型,而只能公开简单的函数。尽管相当适度,但函数调用中增加了开销。而且,大而又大的问题,您无法轻松诊断错误。 CLR和大多数C#代码都希望调用者知道如何处理异常。问题是您不是来自本地C ++代码。您在使用 __ try / __ except 的过程中还有一些余地,但是您无法获得有关该异常的任何详细信息。这会将非常简单的问题(例如FileNotFoundException)变成完全无法诊断的崩溃。您可以通过将调试器类型设置为混合来进行调试,但在交付后无法做任何有用的事情。支持电话非常丑陋。

But it is limited. You cannot expose an object model, just simple functions. There is added overhead in the function call, although it is pretty modest. And the big, big problem, you cannot easily diagnose errors. Both the CLR and most any C# code expects the caller to know how to handle exceptions. Problem is that you don't from native C++ code. You have some leeway in using __try/__except but you can't get any details about the exception. That turns very simple problems, like FileNotFoundException, into completely undiagnosable crashes. You can debug it by setting the Debugger Type to "Mixed", but you can't do anything useful after you shipped it. Very ugly support phone calls.

其他实现这些功能而不会出现这些问题的方法是使用C#库中的[ComVisible(true)],允许在本机中#import C ++代码。并通过其托管界面自己对CLR进行托管,这是支持以托管代码编写的插件的程序所使用的方法。像AutoCAD这样的CAD程序就是很好的例子。还有Visual Studio。

Other ways to accomplish the same without these problems is by using [ComVisible(true)] in your C# library, allowing #import in your native C++ code. And custom-hosting the CLR yourself through its hosting interface, the approach used by the kind of programs that support plugins written in managed code. CAD programs like AutoCAD are good examples of that. And Visual Studio.

这篇关于从Visual C ++调用C#代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆