C# 是否可以运行非托管C++;通常从托管C++/CLI项目?
我正在用C++/CLI包装一个纯非托管VC++9项目,以便从.NET应用程序中简单地使用它。我知道如何编写,以及那些非托管代码,但我不能完全理解的是:C# 是否可以运行非托管C++;通常从托管C++/CLI项目?,c#,c++,.net,visual-c++,c++-cli,C#,C++,.net,Visual C++,C++ Cli,我正在用C++/CLI包装一个纯非托管VC++9项目,以便从.NET应用程序中简单地使用它。我知道如何编写,以及那些非托管代码,但我不能完全理解的是: >P>非托管LIB是一个非常复杂的C++库,使用了很多内联和其他特性,所以我不能将它编译成 /CLR < /代码>标记的托管DLL。我需要使用普通的VC++编译器将其编译成一个单独的DLL 如何从非托管代码中导出符号,以便可以从C++/CLI项目中使用?我是否将我需要的每个类都标记为可见的extern?是这么简单还是有更多的复杂性 如何从C++
extern
?是这么简单还是有更多的复杂性您可以使用PInvoke从非托管DLL调用导出的函数。这就是从.Net访问非托管Windows API的方式。但是,如果导出函数使用C++对象,而不只是纯C数据结构,则可能会遇到问题。
还有一个C++的互操作技术,可以使用:
你可以从一个普通的本地C++项目开始(从10年前的Visual Studio 6导入),当你今天构建它时,它将链接到当前运行的VC运行时版本。 然后,您可以向其中添加一个新的foo.cpp
文件,但要配置该文件,使其启用/CLR标志。这将导致编译器从该文件生成IL,并链接一些额外的支持,使.NET framework在启动时加载到进程中,以便它可以JIT编译并执行IL
应用程序的其余部分仍然像以前一样以本机方式编译,并且完全不受影响
事实是,即使是“纯”CLR应用程序也确实是一种混合,因为CLR本身(显然)是本机代码。混合C++/CLI应用程序只是通过允许添加更多与某些CLR托管代码共享进程的本机代码来扩展这一点。它们在整个过程中共存
如果使用声明创建标题foo.h
:
void bar(int a, int b);
您可以在本机代码或foo.cpp
CLR代码中自由地实现或调用它。编译器/链接器组合处理所有事情。从CLR代码中调用本机代码应该不需要做任何特殊的事情
您可能会收到有关不兼容交换机的编译错误:
-要编辑并继续程序数据库,请将其更改为仅程序数据库/ZI
-您需要禁用最小重建/Gm
-运行时检查,将其更改为默认值/RTC
- 预编译头-将其更改为不使用预编译头
-运行时类型信息-将其更改为打开(/GR)/GR-
所有这些更改只需对特定的/CLR启用文件进行 如Daniel所述,您可以在文件级微调设置。您也可以在文件中使用“#pragma managed”,但我不会无缘无故地这样做 请记住,您可以创建完整的混合模式部件。这意味着,您可以将本机代码原封不动地编译到这个文件中,再加上一些围绕这个代码的C++/CLI包装器。最后,您将拥有与本机Dll相同的文件,其中包含所有导出的本机符号,并同时具有完整的.NET程序集(公开C++/CLI对象) 这也意味着,只要考虑文件外部的本机客户机代码,就只需关心导出。混合dll/程序集中的C++/CLI代码可以使用常用的访问规则访问本机数据结构(只需包含标头即可提供)
因为您提到过,我为一些非平凡的本地C++类层次结构做了这个工作,包括大量的DirectX代码。所以,这里没有主要问题
我建议不要在.NET驱动的环境中使用pInvoke。是的,它起作用了。但是对于任何非平凡的(比如说超过10个函数)来说,使用C++/CLI提供的OO方法肯定会更好。您的C#client开发人员将非常感激。在C++/CLI中,您可以使用所有.NET功能,如委托/属性、托管线程等。从VS 2012开始,您还可以使用一些有用的Intellisense。是的,您可以使用混合模式。只需将要编译的文件标记为本机文件,而不使用
/clr
选项。有一些#pragma指令可以在功能级别上控制它。我认为我做不到这一点。我在#5中提到,这个库非常复杂,它管理自己的对象,它维护活动的DirectX对象指针和所有东西。它甚至有自己的GC,定期运行。我试图包装它,而不破坏任何东西。如果我创建静态函数(i can),并且使用p/javek,实际的C++项目会运行在一个普通的VC++环境中吗?或者.WE.NET在函数的持续时间内简单地调用它,然后关闭它。