为类似 iOS 的平台创建和使用自定义框架
从 .NET 9 开始,本机 AOT 支持发布不依赖于适用于 iOS 的平台的 iOS 工作负载的 .NET 类库。 借助此支持,可以创建可从 iOS、Mac Catalyst 和 tvOS 应用程序使用的自包含本机库。
重要
此方法不附带内置的 Objective-C 互操作性支持,并且可能需要进行其他代码适应(例如封送引用类型参数),以实现互操作性。
生成共享库
本部分介绍使用 NativeAOT 支持创建简单的 .NET 类库项目的步骤,并从中为类似 iOS 的平台生成本机库。
下载 .NET 9 SDK
创建类库项目
dotnet new classlib -n "MyNativeAOTLibrary"
将以下属性添加到项目文件中
MyNativeAOTLibrary.csproj
<PublishAot>true</PublishAot> <PublishAotUsingRuntimePack>true</PublishAotUsingRuntimePack>
编辑
MyNativeAOTLibrary/Class1.cs
源代码以公开托管方法,以便可以从本机代码aotsample_add
中引用它。 例如:using System.Runtime.InteropServices; namespace NaotLib; public class Class1 { [UnmanagedCallersOnly(EntryPoint = "aotsample_add")] public static int Add(int a, int b) { return a + b; } }
通过指定适当的运行时标识符(如下
<rid>
所述)发布类库并面向所需的 iOS 类平台:dotnet publish -r <rid> MyNativeAOTLibrary/MyNativeAOTLibrary.csproj
成功完成上一步将生成一对文件:共享库MyNativeAOTLibrary.dylib
及其调试符号MyNativeAOTLibrary.dylib.dSYM
,位于: MyNativeAOTLibrary/bin/Release/net9.0/<rid>/publish/
注意
若要创建通用框架,需要发布给定平台的 Arm64
类库和 x64
体系结构。
这意味着需要使用不同的运行时标识符重复步骤 5。
例如,将包含两个maccatalyst-arm64
和maccatalyst-x64
运行时标识符的类库发布为将共享库打包到自定义 MacCatalyst 通用框架的先决条件。
创建和使用自定义框架
Apple 要求将共享库 (.dylibs) 打包到框架中才能从应用程序使用。
本部分介绍实现此目的所需的所有步骤,以及使用共享 NativeAOT 库/框架的 iOS/MacCatalyst 应用程序的简单方案。
注意
所述的步骤仅用于演示目的。 实际要求可能因确切用例而异。
将共享库打包到自定义 iOS 框架中
创建框架文件夹:
mkdir MyNativeAOTLibrary.framework
调整加载命令:
LC_RPATH
load 命令install_name_tool -rpath @executable_path @executable_path/Frameworks MyNativeAOTLibrary/bin/Release/net9.0/ios-arm64/publish/MyNativeAOTLibrary.dylib
LC_ID_DYLIB
load 命令install_name_tool -id @rpath/MyNativeAOTLibrary.framework/MyNativeAOTLibrary MyNativeAOTLibrary/bin/Release/net9.0/ios-arm64/publish/MyNativeAOTLibrary.dylib
将二进制文件手动打包到通用文件中:
lipo -create MyNativeAOTLibrary/bin/Release/net9.0/ios-arm64/publish/MyNativeAOTLibrary.dylib -output MyNativeAOTLibrary.framework/MyNativeAOTLibrary
将属性列表文件添加到框架:
- 创建
Info.plist
文件
touch MyNativeAOTLibrary.framework/Info.plist
- 将附录中的内容添加到创建的
Info.plist
文件中
- 创建
最后一步之后,框架结构应如下所示:
MyNativeAOTLibrary.framework
|_ MyNativeAOTLibrary
|_ Info.plist
将共享库打包到自定义 MacCatalyst 通用框架中
通用框架需要二Arm64
x64
进制文件和体系结构。
因此,必须事先发布面向以下两个 RID 的本机库: maccatalyst-arm64
和 maccatalyst-x64
。
创建框架文件夹结构:
mkdir -p MyNativeAOTLibrary.framework/Versions/A/Resources ln -sfh Versions/Current/MyNativeAOTLibrary MyNativeAOTLibrary.framework/MyNativeAOTLibrary ln -sfh Versions/Current/Resources MyNativeAOTLibrary.framework/Resources ln -sfh A MyNativeAOTLibrary.framework/Versions/Current
调整加载命令:
LC_RPATH
load 命令install_name_tool -rpath @executable_path @executable_path/../Frameworks MyNativeAOTLibrary/bin/Release/net9.0/maccatalyst-arm64/publish/MyNativeAOTLibrary.dylib install_name_tool -rpath @executable_path @executable_path/../Frameworks MyNativeAOTLibrary/bin/Release/net9.0/maccatalyst-x64/publish/MyNativeAOTLibrary.dylib
LC_ID_DYLIB
load 命令install_name_tool -id @rpath/MyNativeAOTLibrary.framework/Versions/A/MyNativeAOTLibrary MyNativeAOTLibrary/bin/Release/net9.0/maccatalyst-arm64/publish/MyNativeAOTLibrary.dylib install_name_tool -id @rpath/MyNativeAOTLibrary.framework/Versions/A/MyNativeAOTLibrary MyNativeAOTLibrary/bin/Release/net9.0/maccatalyst-x64/publish/MyNativeAOTLibrary.dylib
将二进制文件手动打包到通用文件中:
lipo -create MyNativeAOTLibrary/bin/Release/net9.0/maccatalyst-arm64/publish/MyNativeAOTLibrary.dylib MyNativeAOTLibrary/bin/Release/net9.0/maccatalyst-x64/publish/MyNativeAOTLibrary.dylib -output MyNativeAOTLibrary.framework/Versions/A/MyNativeAOTLibrary
将属性列表文件添加到框架:
- 创建
Info.plist
文件
touch MyNativeAOTLibrary.framework/Versions/A/Resources/Info.plist
- 将附录中的内容添加到创建的
Info.plist
文件中
- 创建
最后一步之后,框架结构应如下所示:
MyNativeAOTLibrary.framework
|_ MyNativeAOTLibrary -> Versions/Current/MyNativeAOTLibrary
|_ Resources -> Versions/Current/Resources
|_ Versions
|_ A
| |_ Resources
| | |_ Info.plist
| |_ MyNativeAOTLibrary
|_ Current -> A
使用自定义框架
打开
Xcode
(在本示例中Xcode 16.0
使用)创建新的
App
项目选择应用的名称(例如
MyiOSApp
),然后选择 Objective-C 作为源语言添加对框架的
MyNativeAOTLibrary
引用- 在
MyiOSApp
“常规”选项卡的“框架”、“库”和“嵌入内容”下,选择+添加MyNativeAOTLibrary
为引用的框架 - 在对话框中,选择“ 添加其他 ->添加文件 ”,然后浏览到其位置
MyNativeAOTLibrary.framework
并选择它 - 选择后,为
MyNativeAOTLibrary
框架设置Embed and Sign
选项
- 在
在“生成设置”选项卡中将位置添加到
MyNativeAOTLibrary.framework
框架搜索路径列表通过调用公开的托管方法
aotsample_add
并打印结果进行编辑main.m
extern int aotsample_add(int a, int b); int main(int argc, char * argv[]) { ... NSLog(@"2 + 5 = %d", aotsample_add(2, 5)); ... }
选择物理 iOS 设备并生成/运行应用
成功启动应用后检查日志。 应用应打印出来:
2 + 5 = 7
注意
对于 MacCatalyst,除了步骤 7 之外,请使用相同的步骤,其中需要将运行目标设置为: Mac (Mac Catalyst)
。
使用适用于 iOS 等平台的 NativeAOT 生成静态库
如生成本机库概述中所述,最好基于静态库生成共享库,因为存在一些限制。
但是,如果需要,可以按照生成共享库的步骤生成静态库,并在项目文件中包括附加属性:
<NativeLib>Static</NativeLib>
发布项目后,可以在以下位置找到静态库MyNativeAOTLibrary.a
。 MyNativeAOTLibrary/bin/Release/net9.0/<rid>/publish
本文不介绍如何使用静态库和配置使用者项目。
附录 Info.plist 内容
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleName</key>
<string>MyNativeAOTLibrary</string>
<key>CFBundleIdentifier</key>
<string>com.companyname.MyNativeAOTLibrary</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>CFBundleExecutable</key>
<string>MyNativeAOTLibrary</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
</dict>
</plist>