7

在我们的团队中,我们面临着选择:我们需要调用外部第三方代码并从我们的 C# 代码处理其输出。

第三方代码有两种形式:dlls 集和单个exe文件(可能dll自己调用​​这些 s)。可能的方法可能是:使用Process.Start语句运行可执行文件并捕获其输出。还有一种是dll直接调用。

我试图了解我们应该使用哪种方法。

一方面调用可执行文件很简单,但另一方面——它感觉并不健壮。

一方面调用看起来更正确的方式来完成这项工作,但另一方面 -为我们在本机代码中拥有的所有函数dll提供绑定可能是非常复杂的任务。C#C

但我需要对这个话题进行更深入的分析才能做出最终决定。以前有没有人遇到过同样的问题,也许你可以分享你的发现。

这将非常有用!

编辑:在这种特殊情况下,我正在谈论视频转换。我需要从用户那里获取视频流并将其转换为一种视频格式。可以打电话ffmpeg来做这项工作,一切都很好,直到出现问题,我需要重新启动编码或采取任何措施。我无法估计需要多长时间,如果我需要并行转换多个视频,ffmpeg不会像我计划的那样灵活......

至少在我现在看来。当我深入研究时,也许会出现更多问题。

4

6 回答 6

4

有几个考虑:

  1. 你有dll的来源吗?
  2. 你打算调用这些 dll 多少?
  3. dll的API有多复杂,你的用法是什么?

取决于答案。

在以下情况下创建绑定:

  • 你会经常调用 dll。直接调用要快得多。
  • 你有来源并检查它们有多好。否则,您可能会遇到内存泄漏、调用约定等方面的巨大问题。
  • dll 的 API 并不太复杂,因此您不需要向它们发送 C++ 对象等。或者实现很多已经在 exe 中完成的工作。

使用可执行文件:

  • 如果您只需要偶尔运行它们。创建另一个流程的开销对您来说并不重要。
  • 如果您不确定代码的质量。对于您的代码来说,它会更加安全和健壮,而不是加载一些实施不良的 dll。如果出现问题,您始终可以尝试多次运行 .exe。但它是一个 dll 使您的应用程序崩溃,您无能为力。
  • 如果 API 很复杂,而且 exe 有很多功能,那你就必须重新实现。
于 2013-01-24T11:37:21.153 回答
0

我想说这将取决于您的代码在库的 api 支持方面期望的粒度。

如果可执行文件对您来说足够好地封装了工作流,那么您可以从调用可执行文件的简单性中受益。

此外,由于您提到这是本机 C 代码,添加 DLL 引用将意味着必须处理非托管代码,除非我没有选择,否则我个人不会这样做。

于 2013-01-24T11:28:15.913 回答
0

如果 dll 编写得很好并且没有内存泄漏,那么最好使用 dll,因为它不需要新的进程创建开销。

于 2013-01-24T11:29:32.360 回答
0

我想说这完全取决于您的要求、时间范围、exe文件输出的稳定性以及解析的难易程度。两种方式都是可行的。

例如,Mercurial 将其控制台输出视为与其交互的主要方式——即使人们可以直接使用其 Python 代码。

另一方面,从 C# 调用 C 函数相当容易,因此这也可能是一种选择。但是,如果您需要映射数百个 C 函数,则必须问问自己是否有时间这样做。

于 2013-01-24T11:30:43.863 回答
0

EXE 只调用一个主入口,所以不能直接调用函数。当您调用 exe 时,将创建一个新进程,在该进程的主线程的上下文中调用入口线程。

DLL 通过直接调用函数为您提供更大的灵活性 每个函数系统都有一个入口点 将 DLL 加载到现有线程的上下文中

因此调用 DLL 对计算资源来说要好得多,并提供更多的灵活性。考虑到您可以从托管和非托管代码调用 DLL,并且可以从 C# 调用托管和非托管 dll

如果 DLL 有来接口,你可以直接添加引用,如果没有,你仍然可以像下面这样调用它

 [DllImport(@"TestLib.dll")]
    public static extern void InitParam([MarshalAs(UnmanagedType.LPWStr)] string inputFile,
        [MarshalAs(UnmanagedType.LPWStr)] string outputFile,
        [MarshalAs(UnmanagedType.LPWStr)] string templateFile,
        [MarshalAs(UnmanagedType.LPWStr)] string userName,
        [MarshalAs(UnmanagedType.LPWStr)] string manifestFilePath,
        [MarshalAs(UnmanagedType.LPWStr)] string usersRightList);

简单来说,您导入 DLL 并使用编组将参数映射到 .net 类型

于 2013-01-24T11:31:17.120 回答
0

答案取决于外部应用程序使用它的 dll 的方式。:

  • 调用 exe,如果它多次调用多个 dll 函数并且它的业务流程又大又复杂 - 你不想在 C# 代码中重新实现所有 exe 逻辑。
  • 直接调用dll,如果exe只调用dll中的一二函数,调用顺序和参数是众所周知的,或者根本不存在。

一般来说,我更喜欢直接调用 dll,因为这消除了很多开销以及产生新进程和处理其输出的可能问题。并且不要害怕本地代码,如果您的 dll 函数很简单,那么使用 PInvoke 您将能够轻松调用这些函数。

于 2013-01-24T11:33:22.363 回答