随着 .net Core 以及最近的 .net 5 的推出,跨平台 .net/C# 变得相对容易。 考虑到这一点,我正在开发一个将使用 .net 5/C# 的应用程序,但我想将一些代码保留在 C++/本机域中。仅使用 C#,甚至可以从开发版本发布到其他平台。我愿意放弃。
现在,如何保持项目跨平台?
我一直在寻找任何地方似乎都没有一个很好的选择...
也许this solution from Xamarin?我不确定它会转换为桌面,或者它可以在 CI/CD 上自动化...
但除此之外,每个人似乎都以自己的笨拙方式逃脱。
有人对跨平台的 C(++)/C# 集成有什么建议吗?
编辑 1:
我的问题不是让互操作本身。我已经成功地使用了 SWIG,并且我知道 P/Invoke、C 兼容的 ABI 等等。
我的问题是构建系统/部署。到目前为止,我必须复制文件。但是如何才能拥有一个集成的构建系统呢?例如,我希望在为 C++ 库构建我的 dotnet 应用程序时进行编译。
答案 0 :(得分:2)
您可以毫无问题地使用 C++/C#。但是 C++ 端和 C# 端之间的“桥梁”方法必须接受/返回普通的 C 类型/结构。 你不能绕过std::xxxx
句号。您可以传递 char *str
、struct { int Foo, int Bar }
、int[]
等(但仍然有一些复杂性,这取决于它是如何完成的)。
我维护了一个 github 示例,这些示例关于在 .NET Framework/.NET Core 上从/到 C/C++ 到 C# 封送字符串和结构。该项目是为 Visual Studio 构建的,所以里面有一些“微软性”,但基本思想可以很容易地复制粘贴到其他 C 平台上。
当你想做一个完全多平台的项目时,还有一些额外的复杂性(我在写这些例子时没有考虑跨平台):
字符串的编码:在示例中我展示了您可以轻松使用 utf-8 字符串,但这仍然很痛苦,因为在 Windows 上,Windows API 不支持 utf-8 并且是为wchar_t
(您不能使用 utf-8 文件名 CreateFile
)。在 Linux 的另一边,每个人都使用 char*
而几乎没有人使用 wchar_t*
(举相同的例子,filesystems on Linux are agnostic about character sets,所以 open
原语和 {{1} } 方法可以接受可以是 utf-8 编码的 fopen
),因此决定如何以跨平台方式处理 char*
/char
是一件痛苦的事情。如果必须这样做,我可能会将 wchar_t
宏定义为 Linux 上的 TCHAR
,Windows 上的 char
,在任何地方使用它,并使用 wchar_t
编组选项对于字符串,以及 LPTStr
类的 Auto
方法(例如 Marshal
)。 .NET Core 认为 Marshal.PtrToStringAuto
/LPTStr
在 Linux 上为 xxxAuto
,在 Windows 上为 char*
。
虽然在 Windows 上有大量的内存分配器(.NET Core 在互操作中使用的主要分配器是用于内存的 wchar_t*
和用于字符串的 CoTaskMemAlloc
,但也有利基 (useles) 之类的东西 SysAllocString
),在 Linux .NET Core 上直接使用 GlobalHAlloc
。这对于释放“从另一端”分配的内存很重要,如果您希望能够让编组器自动释放内存,它会增加复杂性。但最终,从 C/C++ 端公开内存释放器总是一个好主意,因为之前或之后您必须释放在 C/C++ 端分配的内存。虽然可能,但我认为让编组器自动释放分配给 C/C++ 端的内存是一个坏主意(因为您无法控制操作,并且无法轻松调试它)。所以没有 malloc
在 C# 中用 char* Foo()
翻译:这是可能的,但 .NET 编组器将使用 string Foo()
来释放它。还有其他方法可以执行此操作,或者您可以手动执行此操作(CoTaskMemFree
然后您显式转换并释放 IntPtr Foo()
)。
Linux下使用IntPtr
和BSTR
有一些限制(主要问题是C端没有对等方法),所以如果要跨平台编程使用它们的坏主意(但没有人使用它们)
答案 1 :(得分:1)
三个方面:
显然,您需要为所有支持的平台维护本机组件的版本和构建。这本身就是一个挑战,但与从 .NET 使用它无关。关于 1),您需要为您的本机库提供一个与标准化 PInvoke 规范兼容的 API。这可能具有挑战性,具体取决于您的组件的功能,如果做得不好,可能会导致麻烦。如果可以,只选择纯托管代码,如果您已准备好迎接挑战,请继续!