头文件与定义文件
定义文件(.def)是 cinterop 工具的配置文件,告诉编译器如何生成 C 库的 Kotlin 绑定。掌握定义文件的编写是 C 互操作的关键技能。
定义文件基础
###文件格式
.def 文件采用类似 properties 的格式:
properties
# 基本结构
headers = header1.h header2.h
package = com.example.mylib
compilerOpts = -I/usr/local/include
linkerOpts = -L/usr/local/lib -lmylib必需属性
headers
指定需要生成绑定的 C 头文件:
properties
# 单个头文件
headers = sqlite3.h
# 多个头文件(空格分隔)
headers = stdio.h stdlib.h unistd.h
# 系统头文件和自定义头文件
headers = sys/socket.h mylib.hpackage
生成的 Kotlin 代码的包名:
properties
package = com.example.nativelib
# 或使用简短名称
package = mylib可选属性
headerFilter
指定哪些声明应该被导出(支持 glob 模式):
properties
# 只导出 mylib.h 中的声明
headers = mylib.h other.h
headerFilter = mylib.h
# 使用通配符
headerFilter = mylib/*.h
# 多个过滤器
headerFilter = mylib.h utils.hTIP
headerFilter 可以避免导出不需要的系统头文件声明,减小生成的 klib 大小。
compilerOpts
传递给 C 编译器的选项:
properties
# 指定头文件搜索路径
compilerOpts = -I/usr/local/include
# 多个选项
compilerOpts = -I/usr/local/include -I./include -DDEBUG
# 宏定义
compilerOpts = -DVERSION=2 -DENABLE_LOGGING常用编译选项:
| 选项 | 说明 | 示例 |
|---|---|---|
-I<path> | 添加头文件搜索路径 | -I/usr/local/include |
-D<macro> | 定义宏 | -DDEBUG |
-D<macro>=<value> | 定义带值的宏 | -DVERSION=2 |
-std=<standard> | 指定 C 标准 | -std=c99 |
linkerOpts
传递给链接器的选项:
properties
# 链接库
linkerOpts = -lsqlite3
# 指定库搜索路径
linkerOpts = -L/usr/local/lib -lmylib
# 多个库
linkerOpts = -lssl -lcrypto -lpthread常用链接选项:
| 选项 | 说明 | 示例 |
|---|---|---|
-l<name> | 链接库(自动添加 lib 前缀和后缀) | -lsqlite3 → libsqlite3.so |
-L<path> | 添加库搜索路径 | -L/usr/local/lib |
-framework <name> | macOS/iOS Framework | -framework UIKit |
平台特定配置
条件属性
根据不同平台使用不同配置:
properties
headers = mylib.h
package = mylib
# macOS 配置
compilerOpts.osx = -I/usr/local/include
linkerOpts.osx = -L/usr/local/lib -lmylib
# Linux 配置
compilerOpts.linux = -I/usr/include
linkerOpts.linux = -lmylib -lpthread -ldl
# Windows 配置
compilerOpts.mingw = -I/mingw64/include
linkerOpts.mingw = -lmylib -lws2_32支持的平台后缀:
| 后缀 | 平台 |
|---|---|
.osx .macos | macOS |
.linux | Linux |
.mingw | Windows (MinGW) |
.ios | iOS (所有架构) |
.iosArm64 | iOS ARM64 设备 |
.iosX64 | iOS x64 模拟器 |
.iosSimulatorArm64 | iOS ARM64 模拟器 |
.android | Android NDK |
平台检测示例
properties
# sqlite.def
headers = sqlite3.h
headerFilter = sqlite3.h
package = sqlite
# macOS
linkerOpts.osx = -lsqlite3
# Linux
linkerOpts.linux = -lsqlite3 -ldl -lpthread
# Windows
linkerOpts.mingw = -lsqlite3
# Android
linkerOpts.android = -lsqlite3properties
# openssl.def
headers = openssl/ssl.h openssl/crypto.h
headerFilter = openssl/*.h
package = openssl
compilerOpts.osx = -I/usr/local/opt/openssl/include
linkerOpts.osx = -L/usr/local/opt/openssl/lib -lssl -lcrypto
compilerOpts.linux = -I/usr/include/openssl
linkerOpts.linux = -lssl -lcrypto高级特性
excludeDependendentModules
排除依赖模块的传递导入:
properties
headers = mylib.h
package = mylib
excludeDependentModules = truestaticLibraries
直接链接静态库:
properties
headers = mylib.h
package = mylib
staticLibraries = libmylib.a
# 或指定路径
staticLibraries = /usr/local/lib/libmylib.alibraryPaths
指定库文件搜索路径(替代 -L):
properties
headers = mylib.h
package = mylib
libraryPaths = /usr/local/lib /opt/libmodules
模块化导入(Clang modules):
properties
# 使用模块而非头文件
modules = UIKit Foundation
package = platform.uikitWARNING
modules 选项仅在支持 Clang modules 的平台可用(如 macOS、iOS)。
实战示例
libcurl 定义文件
properties
# libcurl.def
headers = curl/curl.h
headerFilter = curl/*.h
package = libcurl
# 编译选项
compilerOpts = -I/usr/include/curl
compilerOpts.osx = -I/usr/local/opt/curl/include
# 链接选项
linkerOpts = -lcurl
linkerOpts.osx = -L/usr/local/opt/curl/lib -lcurl
linkerOpts.linux = -lcurl
linkerOpts.mingw = -lcurl -lws2_32zlib 压缩库
properties
# zlib.def
headers = zlib.h
package = zlib
# 所有平台都使用系统 zlib
linkerOpts = -lzOpenGL 定义文件
properties
# opengl.def
# macOS 使用 OpenGL Framework
headers.osx = OpenGL/gl.h
modules.osx = OpenGL
package.osx = platform.opengl
# Linux 使用 GL 库
headers.linux = GL/gl.h
linkerOpts.linux = -lGL
package.linux = opengl自定义 C 库
properties
# mylib.def
headers = mylib.h internal.h
headerFilter = mylib.h # 只导出 public API
package = com.example.mylib
# 开发环境配置
compilerOpts = -I./include -DDEBUG
linkerOpts = -L./build/lib -lmylib
# Release 配置(通过 Gradle 覆盖)
compilerOpts.release = -I./include -DNDEBUGGradle 集成
基础配置
kotlin
// build.gradle.kts
kotlin {
linuxX64 {
compilations.getByName("main") {
cinterops {
val libcurl by creating {
// 指定 def 文件
defFile(project.file("src/nativeInterop/cinterop/libcurl.def"))
}
}
}
}
}覆盖 def 文件配置
kotlin
kotlin {
linuxX64 {
compilations.getByName("main") {
cinterops {
val mylib by creating {
defFile(project.file("src/nativeInterop/cinterop/mylib.def"))
// 覆盖包名
packageName("com.example.custom")
// 添加额外的编译选项
compilerOpts("-I/custom/path", "-DEXTRA_FLAG")
// 添加额外的链接选项
linkerOpts("-L/custom/lib", "-lextra")
// 设置头文件目录
includeDirs.allHeaders("/usr/local/include")
}
}
}
}
}多目标配置
kotlin
kotlin {
listOf(
iosX64(),
iosArm64(),
iosSimulatorArm64()
).forEach { target ->
target.compilations.getByName("main") {
cinterops {
val mylib by creating {
defFile(project.file("src/nativeInterop/cinterop/mylib.def"))
// iOS 特定配置
when (target.name) {
"iosArm64" -> {
// 真机配置
compilerOpts("-arch", "arm64")
}
else -> {
// 模拟器配置
}
}
}
}
}
}
}调试技巧
查看生成的代码
编译后查看生成的 Kotlin 绑定:
bash
# 编译 interop
./gradlew :shared:cinteropMylibLinuxX64
# 查看生成的代码
cat build/classes/kotlin/linuxX64/main/cinterop/mylib-cinterop-mylib.klib启用详细日志
properties
# gradle.properties
kotlin.native.verbose=true验证头文件路径
bash
# 测试 C 编译器能否找到头文件
clang -I/usr/local/include -c test.c常见问题
找不到头文件
properties
# 错误信息
error: 'mylib.h' file not found
# 解决方案:添加头文件搜索路径
compilerOpts = -I/path/to/includes链接错误
properties
# 错误信息
undefined reference to `my_function'
# 解决方案:确保链接了正确的库
linkerOpts = -L/path/to/libs -lmylib符号冲突
properties
# 多个库有相同符号时
# 使用 headerFilter 只导出需要的声明
headers = lib1.h lib2.h
headerFilter = lib1.h # 只导出 lib1 的符号宏未定义
c
// C 头文件需要宏定义
#ifndef VERSION
#error "VERSION not defined"
#endifproperties
# def 文件中定义宏
compilerOpts = -DVERSION=2最佳实践
组织定义文件
project/
├── src/
│ └── nativeInterop/
│ └── cinterop/
│ ├── sqlite.def # 系统库
│ ├── curl.def
│ └── mylib.def # 自定义库使用 headerFilter
properties
# 总是使用 headerFilter 避免导出不必要的符号
headers = stdio.h mylib.h
headerFilter = mylib.h # 只导出 mylib.h平台特定最小化
properties
# 优先使用跨平台配置
headers = mylib.h
linkerOpts = -lmylib
# 仅在必要时添加平台特定配置
linkerOpts.mingw = -lmylib -lws2_32 # Windows 需要额外的库版本管理
properties
# 在 def 文件中记录库版本
# SQLite 3.40.0
headers = sqlite3.h
package = sqlite定义文件是 cinterop 的核心配置,掌握其各项属性和高级特性,能够帮助你高效地集成任何 C 库到 Kotlin/Native 项目中。