C# 是否可以运行非托管C++;通常从托管C++/CLI项目?

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++

我正在用C++/CLI包装一个纯非托管VC++9项目,以便从.NET应用程序中简单地使用它。我知道如何编写,以及那些非托管代码,但我不能完全理解的是:

>P>非托管LIB是一个非常复杂的C++库,使用了很多内联和其他特性,所以我不能将它编译成<代码> /CLR < /代码>标记的托管DLL。我需要使用普通的VC++编译器将其编译成一个单独的DLL

  • 如何从非托管代码中导出符号,以便可以从C++/CLI项目中使用?我是否将我需要的每个类都标记为可见的
    extern
    ?是这么简单还是有更多的复杂性

  • 如何从C++/CLI项目访问导出的符号?我是否简单地包含了非托管源代码的头文件,C++链接器会从非托管DLL中获取实际代码吗?或者我必须在指向DLL中的类的新头文件中手工编写一组单独的“extern”类吗

  • 当我的C++/CLI项目创建非托管类时,非托管代码会在正常的VC9运行时正常运行,还是被迫在.NET中运行?导致更多的兼容性问题

  • C++项目创建了很多实例,并有自己的自定义垃圾回收器,全部用普通C++编写,它是DirectX声音渲染器,管理大量DirectX对象。所有这些是否正常工作,或者Win32功能是否会受到任何影响


    您可以使用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
      -您需要禁用最小重建
    • 代码> /ESCC < /C> > C++异常,用SEH异常(EHa)将其改为是。
    • /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在函数的持续时间内简单地调用它,然后关闭它。