c# - 我可以使用以与我的程序不同的语言编写的库吗?
问题描述
我正在学习 .NET 框架,基本上我正在尝试制作一个将 YouTube URL 转换为 mp3 格式的桌面应用程序。我做了一些研究,发现我最好的选择是使用FFmpeg库。但它不是一个 .NET 库(不是用任何 .NET 语言编写的)。
所以,我的问题是我可以使用用不同语言编写的库吗?
我正在通过 GitHub 浏览潜在的解决方案,其中很多似乎都在使用该FFmpeg
库,我想知道这怎么可能(如果)这些库是用不同的语言编写的。谢谢。
解决方案
TL;DR:是或否,这取决于库的类型。我建议您访问nuget.org并查看已经为您完成所有工作的可用软件包。
一个完整的答案可能是关于一本书的价值,所以让我归结为更易于管理的东西,至少是我知道的东西。另外,强调我知道的事情。
让我们避免关注 C#,而是关注 .NET,因为这个答案,也不是我将要写的方式,以任何方式特定于 C#,而是特定于 .NET。
通常,您可以从 .NET 程序集中引用两种类型的外部库:
- 其他 .NET 程序集
- Windows DLL(稍后会详细介绍 Linux)
引用其他 .NET 程序集将在最终程序集中使用相同的技术,对它的引用,但要到达那里,您有几个选择:
- 您可以在同一个解决方案文件中创建同级 .NET 项目,并进行项目引用
- 您可以添加对 Nuget 包的依赖项
- 您可以添加对磁盘上的程序集文件的直接引用
这 3 个选项最终都会嵌入对相关程序集的引用。这将只是您引用的普通 .NET 代码,因此这里不会发生任何神奇的事情。你几乎肯定已经这样做了。
现在,对于 Windows DLL,即不是 .NET 程序集的 .dll 文件,您需要执行其他操作。
您需要使用P/Invoke,它基本上是如何引用此类 DLL 及其函数的名称。
要使用它,您需要声明一个extern
带有[DllImport(...)]
属性的方法,以及仔细使用正确的参数类型等等。这是来自PInvoke.net的示例:
[DllImport("gdi32.dll")]
static extern bool ArcTo(IntPtr hdc, int nLeftRect, int nTopRect,
int nRightRect, int nBottomRect, int nXRadial1, int nYRadial1,
int nXRadial2, int nYRadial2);
正确编写外部方法需要仔细注意所涉及的数据类型。除非这是您唯一的选择,否则我建议您尝试使用 nuget 路径。
现在,ffmpeg 既不是 .NET 程序集也不是 Windows DLL(据我所知),因此这两个选项都不可用。如果该库在适合链接到 C++ 程序的库中可用,那么您要做的就是编写一个 Interop 程序集,基本上在 C++ 中创建 .NET 类,以弥合您想要使用的 ffmpeg 库的差距。由于 C++.NET 项目既可以链接到此类库,也可以生成 .NET 程序集,因此可以这样做,但需要再次注意涉及的类型。
我会假设有人已经完成了这项工作,并且搜索 nuget.org发现了这些 nuget 包:
- FFmpeg.Native
- FFmpeg.Win10
- 以及大约 160 个其他名称中包含 ffmpeg 的软件包
我的建议是去看看这些 nuget 包。由于 ffmpeg 包含几个具有不同用途的不同库,因此您需要找到一个可以访问您感兴趣的库的库。
最后,如果您使用的是 .NET Core,并且需要在 Linux 上执行此操作,则您需要执行与上述 Windows DLL 相同的操作,除了 Linux 上的 .NET Core 可以添加类似类型的.so
文件引用。但是,如果您要链接的库不是独立库但适合链接,则上面编写的有关互操作程序集的所有内容仍然有效。
另请注意,创建一个可在 Windows 和 Linux 上运行的程序集也是一项艰巨的任务。
最后一个选项是您可以使用 ffmpeg 命令行应用程序。您必须将要处理的数据作为文件存储在磁盘上,然后小心地将所有参数构造到命令行程序,以这样一种方式调用它,即您既可以捕获程序的输出又可以隐藏它,以便用户看不到控制台窗口,最后从最终文件中读回处理后的输出。
如果您找不到正确的 nuget 包并且不想花时间研究如何正确获取 p/invoke 或互操作程序集,这是一种简单的方法,但在您真正开始一个单独的程序并等待它完成,您可能必须解析文本输出以找出执行期间发生的情况,例如它是成功还是失败。
您可以在 Stack Overflow, Execute ffmpeg command with C#上阅读有关此攻击线的更多信息。
推荐阅读
- typescript - 从不同文件导入时,默认导出不会被多次调用
- angular - 如何将输入类型应用于 ng2-smart-table
- git - 首次构建时的 Jenkins Git 变更日志
- android - 如何通过 ADB Android 检查移动网络连接?
- android - 新构建类型失败并出现错误:CrashlyticsOrgIdException:无法获取 Crashlytics 组织 ID
- javascript - 如何将图像放在 Brick Breaker HTML 游戏的球上(使用 JavaScript/HTML)
- java - 匹配多个通配符表达式的最短字符串
- shell - 按日期将日志文件移动到存档文件夹,但不是每个进程的最后一个日志文件
- python - 在类方法中模拟第三方函数
- powershell - Powershell在下一行执行之前没有等待