我有一个非托管的 C++ exe,我可以直接从我的 C# 代码内部调用(具有我可以创建一个库的 C++ 代码)或通过生成一个进程并从 OutputStream 中获取数据。选项的优点/缺点是什么?
5 回答
由于您有 C++ 库的源代码,您可以使用 C++/CLI 将其编译为混合模式 dll,以便 C# 应用程序使用。
这样做的好处是在数据流(该 C++ 模块的输入或输出)上最为灵活。
在进程外运行 C++ 代码有一个好处。如果您的 C++ 代码不是很健壮,这可以使您的主要 C# 进程稳定,以免被 C++ 代码崩溃。
正在进行的主要缺点是确保您正确处理托管/本机交互。
1)
c++ 代码可能取决于清理/资源释放等的确定性破坏。我说这可能是因为这在 c++ 中是常见且良好的做法。
在托管代码中,这意味着您必须小心正确地处理您的 c++ cli 包装器代码。如果您的代码使用过一次,c# 中的 using 子句将为您执行此操作。如果对象需要作为成员存在一段时间,您会发现 dispose 需要在整个应用程序中链接起来。
2)
另一个问题取决于您的应用程序的内存消耗程度。托管垃圾收集器可以是惰性的。如果托管分配需要比可用空间更多的空间,则可以保证启动。然而,非托管分配器无论如何都没有连接。因此,您需要手动通知托管分配器您将进行非托管分配,并且它应该保持该空间可用。这是使用 AddMemoryPressure 方法完成的。
流程外的主要缺点是:
1) 速度。
2) 管理通信的代码开销。
3) 监视一个或其他进程在不期望时死亡的代码开销。
抓取 OutputStream 的最大缺点是缺少数据类型。我宁愿做导出一些函数和重用现有库的工作;但是,这实际上只是一种偏好。
生成进程的另一个缺点是在 Windows 上生成进程是一项非常昂贵(缓慢)的操作。如果您打算经常调用 c++ 代码,这值得考虑。一个优点可能是您自动更加孤立于 c++ 程序中的崩溃。替换 c++ 可执行文件也可能是一个优势。此外,在 c# 中编写互操作代码可能会很麻烦。如果它是一个复杂的交互并且您决定进行互操作,请查看互操作层的 c++/cli。
最好将 C++ 可执行文件的函数子集构建到库中。您将保持类型安全,并且您将能够更好地利用异常处理(更不用说对如何管理对库中函数的调用的更精细控制)。
如果您从可执行文件的 OutputStream 中获取数据,您将看不到可执行文件的进程,没有真正的异常处理,并且您将丢失您可能拥有的任何类型信息。