基本上我需要从Visual C++代码调用C#代码.在阅读了很多关于可能方法的文章后,我决定使用C++/CLI机制.
最初我决定在C++本机代码(dll库项目)中有一些函数,它们将调用CLR项目中的一些函数,这些函数将调用C#项目中的一些函数.
在那之后,我想也许我可以摆脱桥梁项目(CLR项目),因为它只是向管理世界过渡.我认为我可以创建我的原生项目,我可以添加一个c ++源文件,我可以只为该文件而不是整个项目启用CLR支持.所以这意味着我的本机项目将只包含一个可以使用C++/CLI语法并代表桥接的文件.所有其他文件只是本机C++源文件.从设计的角度看这是对的吗?!
为了做到这一点,我想我必须将托管C#dll文件添加到C++本机dll文件的其他#using Directories属性中.问题是我不知道如何根据当前配置设置C#dll调试或发布版本的路径.
另外我知道我不能将本机C++ DLL添加到C#项目引用中.但看起来我可以在本机C++项目中添加一个C#dll作为引用.怎么会 ?!这甚至有用吗?如果我可以将C#dll添加到本机C++项目引用中,是否需要设置#using目录?
我只能为该文件启用CLR支持,而不是整个项目
通过选择CLR项目模板,在执行此操作和开始之间没有有效的区别.无论哪种方式,结果都是混合模式.NET程序集,包含MSIL和本机代码.在项目级别执行此操作仅为项目中的.cpp文件设置/ clr的默认值.您也可以通过覆盖单个.cpp文件的设置来使用CLR项目模板执行此操作,现在禁用/ clr.最终结果都是一样的.
我想我必须将托管的C#dll文件添加到其他#using目录
是的,这是一种方法.也解决了您的查询,您可以在路径名中使用$(Configuration)宏.根据您构建的配置,在编译时解析为"Debug"或"Release".我应该强调,这实际上并不是必要的.编译器仅使用C#程序集中的元数据.只是声明.完全相当于.h文件,请注意您很少根据配置使#include不同.唯一的一个例子就是当你#if DEBUG在C#源代码中使用包含/排除代码时,这种情况并不常见.
但看起来我可以在本机C++项目中添加一个C#dll作为引用
这在每个VS版本中都被修改过,而不是100%确定你在做什么.在添加引用时,实际上很少发生,它只是让编译器驱动程序添加/ FU编译选项.如果.cpp文件没有使用/ clr编译,那么它什么都不做,编译器就完全忽略了它.当你#using在源代码中使用并且没有使用/ clr 时,它会大声抱怨.两者之间没有真正的区别,只是更容易用/ FU来控制文件的路径.
因为它只是向管理世界过渡
这里需要注意的是,还有很多事情要做.你在这里做的是"反向pinvoke",本机代码调用托管代码.C++/CLI主要是为了完全相反而设计的.它涉及更多,需要发生的非平凡事情是需要在第一次调用时加载和初始化CLR.这都是自动的,由您使用时自动生成的存根提供__declspec(dllexport).与Robert Giesecke的"Unmanaged Exports"实用程序所依赖的魔法相同,这是您应该关注的另一种选择.
但它是有限的.您不能公开对象模型,只需简单的函数.函数调用中增加了开销,尽管它非常适中.而大的,大的问题,你不能轻易诊断错误.CLR和大多数C#代码都希望调用者知道如何处理异常.问题是你不是从本机C++代码.你有一些使用余地,__try/__except但你无法获得有关异常的任何细节.这将非常简单的问题(如FileNotFoundException)转变为完全不可诊断的崩溃.您可以通过将调试器类型设置为"混合"来调试它,但在发货后您无法执行任何有用的操作.非常难看的支持电话.
在没有这些问题的情况下实现相同的其他方法是在C#库中使用[ComVisible(true)],允许在本机C++代码中使用#import.并通过其托管接口自定义托管CLR,这种方法支持使用托管代码编写的插件.像AutoCAD这样的CAD程序就是很好的例子.和Visual Studio.