从非特定 .NET 应用程序引用特定于平台的库

Posted

技术标签:

【中文标题】从非特定 .NET 应用程序引用特定于平台的库【英文标题】:Referencing a platform-specific library from a non-specific .NET app 【发布时间】:2009-02-27 23:57:39 【问题描述】:

我经常需要在我的 C# 应用程序中包含少量本机代码,我倾向于通过 C++/CLI 来完成。通常我只需要使用一个 C++ 库,它没有 .NET 的好替代品;但有时性能也是一个因素。

这是有问题的;这样做意味着添加对特定 x86 或 x64 库的引用。大多数库都支持 64 位和 32 位编译,或者只需要稍作修改即可在 64 位下工作。但是,我只能引用来自特定 C# 项目构建目标的 一个 版本。这意味着我需要为解决方案中的每个项目手动添加多个构建目标。

VS.NET 在这种情况下非常无用:如果您将 C++ 库和 C# 库添加到同一个解决方案中,并且 C# 和 C++ 库同时具有 32 位和 64 位目标,您的解决方案将包含“任何 CPU”目标、“混合平台”目标、x64 目标、x86 目标(C# 称之为 32 位)、win32 目标(C++ 称之为 32 位),也许还有更多;至少有两个版本(发布和调试,除非您添加了更多版本)。

这很快就变得一团糟,而且没有充分的理由。显而易见的行为不应该那么棘手:如果我有一个 C# 项目引用一个 C++ 项目,那么 64 位版本应该引用 64 位版本应该有点明显,32 位也是如此。

最糟糕的是,所有这一切都会导致两个独立但相同的可执行文件:A Any CPU .NET 项目可以在 32 位和 64 位模式下不加修改地工作,但我还没有找到加载适当的方法平台特定的支持库,具体取决于应用启动的模式。

总结这段漫长的漫谈:

是否可以让在跨平台应用程序上使用 VS 变得不那么痛苦 - 让它无需手动操作即可将适当的引用添加到适当的构建目标? 是否有一种简单的方法可以使 .NET 可执行文件具有特定于平台的引用,可以在 32 位和 64 位模式下运行,并根据需要加载适当的程序集?

【问题讨论】:

如果您的 C# 应用程序也特定于平台而不是 AnyCPU,这是否可以正常工作? 它不能“正常”工作-因此是问题所在。但是,如果您的意思是如果所有项目都设置为在特定的、相同的位数下运行 - 那么是的,它确实有效(这是手动解决方案)。到目前为止,VS 2010 已经发布,这会将两种项目类型默认为吸引力较小但更兼容的 x86 模式,因此它可以开箱即用 - 但如果您想支持 x64 执行,您仍然需要手动更改每个项目的每个构建。 【参考方案1】:

您应该问自己的主要问题是,您需要 64 位版本吗?有关详细信息,请参阅 Scott Hanselman 和 myself 的博客文章。

如果你真的需要这两个版本,你也可以将 32 位和 64 位库都加载到 GAC 中,这样运行时就可以自动选择正确的一个。

如果您不想对您的库进行 GAC,您还可以查看 this *** post,其中描述了一种加载正确程序集的方法。不过我不太喜欢这个解决方案,因为它确实需要一个插件模型

【讨论】:

64 位版本有时由于性能(主要是在本机库中进行数学运算)或由于内存限制而具有吸引力。我经常遇到这两个。无论如何感谢您的链接,虽然我也真的不喜欢插件模型。【参考方案2】:

我的答案是肯定的。一种可能的方法是使用插件架构,使其像这样工作,

    当您的 C# 应用程序在 x86 上运行时,它会加载 x86 版本的插件。 在 x64 上运行时,它会加载 x64 版本。

然后为插件版本准备两个项目。一个配置为针对 x86 进行编译,而另一个配置为针对 x64 进行编译。反过来,x86 插件封装了 C++ 库的 x86 构建,以及 C++ 库的 x64 over x64 构建。

这有点复杂,因为你必须维护两个插件项目文件,而源文件可以共享。

使用插件架构,插件库在运行时加载,因此您有足够的时间来检测现在是在 x86 还是 x64 上,然后决定加载哪个插件。

希望对您有所帮助。

【讨论】:

以上是关于从非特定 .NET 应用程序引用特定于平台的库的主要内容,如果未能解决你的问题,请参考以下文章

在 SQL 语句中,如何选择所有非特定条件的元素?

从 Play 商店安装应用时缺少拆分 APK

在跨平台 xamarin 项目中编写特定于平台的代码

使用 GitHub Actions 在 .net 应用程序中填充特定于环境的变量

在 Flutter 中使用特定于平台的包

您可以在 PhoneGap 中添加特定于平台的代码吗?