简体   繁体   English

是否可以通过托管C ++ / CLI项目正常运行非托管C ++?

[英]Is it possible to run unmanaged C++ normally from a managed C++/CLI project?

I'm in the process of wrapping a pure unmanaged VC++ 9 project in C++/CLI in order to use it plainly from a .NET app. 我正在使用C ++ / CLI包装一个纯粹的非托管VC ++ 9项目,以便从.NET应用程序中清楚地使用它。 I know how to write the wrappers , and that unmanaged code can be executed from .NET , but what I can't quite wrap my head around: 我知道如何编写包装器 ,并且可以从.NET执行非托管代码,但我无法完全理解:

  1. The unmanaged lib is a very complex C++ library and uses a lot of inlining and other features, so I cannot compile this into the /clr -marked managed DLL. 非托管lib是一个非常复杂的C ++库,它使用了很多内联和其他功能,因此我无法将其编译到/clr -marked托管DLL中。 I need to compile this into a seperate DLL using the normal VC++ compiler. 我需要使用普通的VC ++编译器将其编译为单独的DLL。

  2. How do I export symbols from this unmanaged code so that it can be used from the C++/CLI project? 如何从此非托管代码导出符号,以便可以从C ++ / CLI项目中使用它? Do I mark every class I need visible as extern ? 我是否将我需要的所有课程标记为extern Is it that simple or are there some more complexities? 是这么简单还是有一些更复杂的问题?

  3. How do I access the exported symbols from the C++/CLI project? 如何从C ++ / CLI项目访问导出的符号? Do I simply include the header files of the unmanaged source code and will the C++ linker take the actual code from the unmanaged DLL? 我是否只包含非托管源代码的头文件,C ++链接器是否会从非托管DLL中获取实际代码? Or do I have to hand write a seperate set of "extern" classes in a new header file that points to the classes in the DLL? 或者,我是否必须在指向DLL中的类的新头文件中手动编写一组单独的“extern”类?

  4. When my C++/CLI project creates the unmanaged classes, will the unmanaged code run perfectly fine in the normal VC9 runtime or will it be forced to run within .NET? 当我的C ++ / CLI项目创建非托管类时,非托管代码是否会在正常的VC9运行时运行得很好,还是会被迫在.NET中运行? causing more compatibility issues? 导致更多兼容性问题?

  5. The C++ project creates lots of instances and has its own custom-implemented garbage collector, all written in plain C++, it is a DirectX sound renderer and manages lots of DirectX objects. C ++项目创建了大量实例,并且有自己的自定义垃圾收集器,全部用纯C ++编写,它是一个DirectX声音渲染器并管理大量的DirectX对象。 Will all this work normally or would such Win32 functionality be affected in any way? 所有这些都能正常工作还是会以任何方式影响Win32功能?

You can start with an ordinary native C++ project (imported from, say, Visual Studio 6.0 from well over a decade ago) and when you build it today, it will link to the current version of the VC runtime. 您可以从普通的本机C ++项目(从十多年前从Visual Studio 6.0导入)开始,当您今天构建它时,它将链接到VC运行时的当前版本。

Then you can add a single new foo.cpp file to it, but configure that file so it has the /CLR flag enabled. 然后,您可以向其添加一个新的foo.cpp文件,但配置该文件以使其启用了/ CLR标志。 This will cause the compiler to generate IL from that one file, and also link in some extra support that causes the .NET framework to be loaded into the process as it starts up, so it can JIT compile and then execute the IL. 这将导致编译器从该文件生成IL,并且还链接一些额外的支持,导致.NET框架在启动时加载到进程中,因此它可以JIT编译然后执行IL。

The remainder of the application is still compiled natively as before, and is totally unaffected. 应用程序的其余部分仍然像以前一样本地编译,并且完全不受影响。

The truth is that even a "pure" CLR application is really a hybrid, because the CLR itself is (obviously) native code. 事实是,即使是“纯粹的”CLR应用程序也是混合应用程序,因为CLR本身(显然)是本机代码。 A mixed C++/CLI application just extends this by allowing you to add more native code that shares the process with some CLR-hosted code. 混合C ++ / CLI应用程序只是通过允许您添加更多本机代码来扩展这一点,该代码与一些CLR托管代码共享该过程。 They co-exist for the lifetime of the process. 它们在整个过程中共存。

If you make a header foo.h with a declaration: 如果你用一个声明创建一个标题foo.h

void bar(int a, int b);

You can freely implement or call this either in your native code or in the foo.cpp CLR code. 您可以在本机代码或foo.cpp CLR代码中自由地实现或调用它。 The compiler/linker combination takes care of everything. 编译器/链接器组合负责所有事情。 There should be no need to do anything special to call into native code from within your CLR code. 从CLR代码中调用本机代码不需要做任何特殊操作。

You may get compile errors about incompatible switches: 您可能会遇到有关不兼容的开关的编译错误:

  • /ZI - Program database for edit and continue , change it to just Program database /ZI - 用于编辑和继续的程序数据库 ,将其更改为程序数据库
  • /Gm - you need to disable Minimal rebuild /Gm - 您需要禁用最小重建
  • /EHsc - C++ exceptions, change it to Yes with SEH Exceptions (/EHa) /EHsc - C ++异常, 使用SEH异常(/ EHa)将其更改为
  • /RTC - Runtime checks, change it to Default /RTC - 运行时检查,将其更改为默认值
  • Precompiled headers - change it to Not Using Precompiled Headers 预编译头 - 将其更改为“ 不使用预编译头”
  • /GR- - Runtime Type Information - change it to On (/GR) /GR- - 运行时类型信息 - 将其更改为开(/ GR)

All these changes only need to be made on your specific /CLR enabled files. 所有这些更改只需要在特定的/ CLR启用的文件上进行。

As mentioned from Daniel, you can fine-tune your settings on file level. 如Daniel所述,您可以在文件级别上微调您的设置。 You can also play with '#pragma managed' inside files, but I wouldn't do that without reason. 您也可以在文件中使用“#pragma managed”,但我不会毫无理由地这样做。

Have in mind, that you can create a complete mixed mode assembly. 请记住,您可以创建一个完整的混合模式程序集。 That means, you can compile your native code unchanged into this file PLUS some C++/CLI wrapper around this code. 这意味着,您可以将您的本机代码不加改变地编译到此文件中,并在此代码周围添加一些C ++ / CLI包装器。 Finally, you will have the same file as native Dll with all your exported native symbols AND as full-fledged .NET assembly (exposing C++/CLI objects) at the same time! 最后,您将拥有与本机Dll相同的文件,其中包含所有导出的本机符号,并且同时具有完整的.NET程序集(公开C ++ / CLI对象)!

That also means, you have only to care about exports as far as native client code outside your file is considered. 这也意味着,只考虑文件外部的本机客户端代码,您只需关心导出。 Your C++/CLI code inside the mixed dll/assembly can access the native data structures using the usual access rules (provided simply by including the header) 混合dll /程序集中的C ++ / CLI代码可以使用通常的访问规则访问本机数据结构(仅通过包含标头提供)

Because you mentioned it, I did this for some non-trivial native C++ class hierarchy including a fair amount of DirectX code. 因为你提到过它,我为一些非平凡的原生C ++类层次结构做了这个,包括相当数量的DirectX代码。 So, no principal problem here. 所以,这里没有主要问题。

I would advise against usage of pInvoke in a .NET-driven environment. 我建议不要在.NET驱动的环境中使用pInvoke。 True, it works. 没错,它有效。 But for anything non-trivial (say more than 10 functions) you are certainly better with an OO approach as provided by C++/CLI. 但是对于任何非平凡的事情(例如超过10个函数),使用C ++ / CLI提供的OO方法肯定会更好。 Your C# client developers will be thankful. 您的C#客户端开发人员将非常感激。 You have all the .NET stuff like delegates/properties, managed threading and much more at your finger tips in C++/CLI. 您可以在C ++ / CLI中获得所有.NET内容,例如委托/属性,托管线程等等。 Starting with VS 2012 with a somewhat usable Intellisense too. 从VS 2012开始,还有一些可用的Intellisense。

You can use PInvoke to call exported functions from unmanaged DLLs. 您可以使用PInvoke从非托管DLL调用导出的函数。 This is how unmanaged Windows API is accessed from .Net. 这是从.Net访问非托管Windows API的方式。 However, you may run into problems if your exported functions use C++ objects, and not just plain C data structures. 但是,如果导出的函数使用C ++对象而不仅仅是纯C数据结构,则可能会遇到问题。

There also seems to be C++ interop technology that can be of use to you: http://msdn.microsoft.com/en-us/library/2x8kf7zx(v=vs.80).aspx 似乎还有C ++互操作技术可以对你有用: http//msdn.microsoft.com/en-us/library/2x8kf7zx(v = vs。80).aspx

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM