Skip to content

Commit a26b707

Browse files
committed
Update main to output generated at 37f525e
1 parent 8913fe0 commit a26b707

87 files changed

Lines changed: 480 additions & 179 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

foundation/framework/activity-start/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2478,7 +2478,7 @@ <h1 id="activity">Activity 启动流程分析</h1>
24782478
<small>
24792479

24802480
最后更新:
2481-
<span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date">August 3, 2025</span>
2481+
<span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date">August 10, 2025</span>
24822482

24832483

24842484
</small>

foundation/kotlin-compiler-learn/kotlin-c-interop/index.html

Lines changed: 312 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -939,9 +939,83 @@
939939

940940
<li class="md-nav__item">
941941
<a href="#_1" class="md-nav__link">
942-
实现跨语言调用的一般流程
942+
接口定义
943943
</a>
944944

945+
</li>
946+
947+
<li class="md-nav__item">
948+
<a href="#_2" class="md-nav__link">
949+
绑定生成
950+
</a>
951+
952+
<nav class="md-nav" aria-label="绑定生成">
953+
<ul class="md-nav__list">
954+
955+
<li class="md-nav__item">
956+
<a href="#_3" class="md-nav__link">
957+
参数解析
958+
</a>
959+
960+
</li>
961+
962+
<li class="md-nav__item">
963+
<a href="#_4" class="md-nav__link">
964+
调用核心生成器
965+
</a>
966+
967+
<nav class="md-nav" aria-label="调用核心生成器">
968+
<ul class="md-nav__list">
969+
970+
<li class="md-nav__item">
971+
<a href="#c" class="md-nav__link">
972+
获取 C 库定义
973+
</a>
974+
975+
</li>
976+
977+
<li class="md-nav__item">
978+
<a href="#kotlin-ir" class="md-nav__link">
979+
构建 Kotlin IR 存根
980+
</a>
981+
982+
</li>
983+
984+
<li class="md-nav__item">
985+
<a href="#_5" class="md-nav__link">
986+
构建桥接代码
987+
</a>
988+
989+
</li>
990+
991+
</ul>
992+
</nav>
993+
994+
</li>
995+
996+
<li class="md-nav__item">
997+
<a href="#_6" class="md-nav__link">
998+
原生代码编译
999+
</a>
1000+
1001+
<nav class="md-nav" aria-label="原生代码编译">
1002+
<ul class="md-nav__list">
1003+
1004+
<li class="md-nav__item">
1005+
<a href="#klib" class="md-nav__link">
1006+
生成 KLIB
1007+
</a>
1008+
1009+
</li>
1010+
1011+
</ul>
1012+
</nav>
1013+
1014+
</li>
1015+
1016+
</ul>
1017+
</nav>
1018+
9451019
</li>
9461020

9471021
<li class="md-nav__item">
@@ -2499,9 +2573,83 @@
24992573

25002574
<li class="md-nav__item">
25012575
<a href="#_1" class="md-nav__link">
2502-
实现跨语言调用的一般流程
2576+
接口定义
2577+
</a>
2578+
2579+
</li>
2580+
2581+
<li class="md-nav__item">
2582+
<a href="#_2" class="md-nav__link">
2583+
绑定生成
2584+
</a>
2585+
2586+
<nav class="md-nav" aria-label="绑定生成">
2587+
<ul class="md-nav__list">
2588+
2589+
<li class="md-nav__item">
2590+
<a href="#_3" class="md-nav__link">
2591+
参数解析
2592+
</a>
2593+
2594+
</li>
2595+
2596+
<li class="md-nav__item">
2597+
<a href="#_4" class="md-nav__link">
2598+
调用核心生成器
2599+
</a>
2600+
2601+
<nav class="md-nav" aria-label="调用核心生成器">
2602+
<ul class="md-nav__list">
2603+
2604+
<li class="md-nav__item">
2605+
<a href="#c" class="md-nav__link">
2606+
获取 C 库定义
25032607
</a>
25042608

2609+
</li>
2610+
2611+
<li class="md-nav__item">
2612+
<a href="#kotlin-ir" class="md-nav__link">
2613+
构建 Kotlin IR 存根
2614+
</a>
2615+
2616+
</li>
2617+
2618+
<li class="md-nav__item">
2619+
<a href="#_5" class="md-nav__link">
2620+
构建桥接代码
2621+
</a>
2622+
2623+
</li>
2624+
2625+
</ul>
2626+
</nav>
2627+
2628+
</li>
2629+
2630+
<li class="md-nav__item">
2631+
<a href="#_6" class="md-nav__link">
2632+
原生代码编译
2633+
</a>
2634+
2635+
<nav class="md-nav" aria-label="原生代码编译">
2636+
<ul class="md-nav__list">
2637+
2638+
<li class="md-nav__item">
2639+
<a href="#klib" class="md-nav__link">
2640+
生成 KLIB
2641+
</a>
2642+
2643+
</li>
2644+
2645+
</ul>
2646+
</nav>
2647+
2648+
</li>
2649+
2650+
</ul>
2651+
</nav>
2652+
25052653
</li>
25062654

25072655
<li class="md-nav__item">
@@ -2530,23 +2678,176 @@
25302678

25312679

25322680
<h1 id="kotlin-c">Kotlin 调用 C 语言是如何实现的?</h1>
2533-
<h2 id="_1">实现跨语言调用的一般流程</h2>
2534-
<ul>
2535-
<li>接口定义与绑定生成: 定义目标语言的接口描述,生成调用方语言的绑定代码,建立数据类型映射关系</li>
2536-
<li>数据类型转换:实现基础类型与复杂类型的映射转换</li>
2537-
<li>代码生成阶段: 生成跨语言调用的胶水代码</li>
2538-
<li>运行时支持阶段: 内存管理与错误处理等</li>
2539-
</ul>
2681+
<p>Kotlin 通过 C-interop 实现与 C 语言的互操作性,允许 Kotlin 代码调用 C 函数和使用 C 数据结构。C-interop 是 Kotlin/Native 的一部分,提供了一种机制来生成 Kotlin 代码,以便与 C 库进行交互。</p>
2682+
<p>C-interop 的工作原理是通过解析 C 头文件,生成相应的 Kotlin 代码和 KLIB(Kotlin Library)文件。这个过程包括以下几个步骤:</p>
2683+
<ol>
2684+
<li><strong>接口定义</strong>:使用 <code>.def</code> 文件定义 C 接口,包括头文件、编译选项、链接选项等信息。</li>
2685+
<li><strong>绑定生成</strong>:C-interop 工具解析 <code>.def</code> 文件,生成 Kotlin 代码和 KLIB 文件。这些 KLIB 文件包含了 C 函数的声明和数据结构的定义,使得 Kotlin 可以调用 C 函数。</li>
2686+
<li><strong>数据类型转换</strong>:C-interop 处理基础类型(如整数、浮点数等)和复杂类型(如结构体、枚举等)的映射转换。它会生成相应的 Kotlin 类型,以便在 Kotlin 代码中使用 C 数据结构。</li>
2687+
<li><strong>代码生成</strong>:C-interop 工具生成胶水代码,这些代码在 Kotlin 和 C 之间进行调用和数据传递。它会生成必要的函数调用包装器和属性访问器,以便 Kotlin 可以调用 C 函数。</li>
2688+
<li><strong>运行时支持</strong>:C-interop 提供了运行时支持,包括内存管理和错误处理等。它确保 Kotlin 代码可以正确地与 C 代码交互,并处理跨语言调用中的内存分配和释放。 </li>
2689+
</ol>
2690+
<h2 id="_1">接口定义</h2>
2691+
<pre><code>headers = hello.h
2692+
2693+
# (For cinterop tool) Path to search for static libraries.
2694+
# Must be relative to the project root.
2695+
libraryPaths = src/nativeInterop/cinterop
2696+
2697+
# (For final linker) Options to be embedded in the klib.
2698+
# Must be relative to the project root.
2699+
linkerOpts = -Lsrc/nativeInterop/cinterop
2700+
2701+
# The static library file to be included.
2702+
staticLibraries = libhello.a
2703+
2704+
# (For cinterop tool) Path to search for header files.
2705+
# Must be relative to the project root.
2706+
compilerOpts = -Isrc/nativeInterop/cinterop
2707+
</code></pre>
2708+
<p>如上所示,<code>.def</code> 文件定义了 C 接口,包括头文件、编译选项、链接选项等信息。C-interop 工具将解析这个文件,并生成相应的 Kotlin 代码和 KLIB 文件。</p>
2709+
<h2 id="_2">绑定生成</h2>
2710+
<pre><code>./kotlin-native/dist/bin/run_konan cinterop -def ./compilerTestData/cinterop/hello.def -o compilerTestData/cinterop/Hello -J&quot;-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:50015&quot;
2711+
</code></pre>
2712+
<p>当我们执行 C-interop 命令时,实际上是调用了以上命令,这个命令会执行以下操作:</p>
2713+
<h3 id="_3">参数解析</h3>
2714+
<p>执行以上命令行时,会执行到 mainImpl 函数,该函数负责解析命令行参数,并根据参数调用相应的 C-interop 工具。</p>
2715+
<pre><code>private fun mainImpl(args: Array&lt;String&gt;, runFromDaemon: Boolean, konancMain: (Array&lt;String&gt;) -&gt; Unit) {
2716+
val utilityName = args[0]
2717+
val utilityArgs = args.drop(1).toTypedArray()
2718+
when (utilityName) {
2719+
&quot;cinterop&quot; -&gt; {
2720+
val konancArgs = invokeInterop(&quot;native&quot;, utilityArgs, runFromDaemon)
2721+
konancArgs?.let { konancMain(it) }
2722+
}
2723+
// ...
2724+
}
2725+
}
2726+
</code></pre>
2727+
<h3 id="_4">调用核心生成器</h3>
2728+
<p>在解析完参数后,C-interop 工具会调用核心生成器来处理 C 库的绑定生成。这个过程主要由 <code>processCLib</code> 函数完成。</p>
2729+
<p><code>processCLib</code> 的主要职责是:获取 C 库的完整定义,调用 LLVM 解析其头文件,生成所有必要的 Kotlin 和 C 的“胶水代码”(stubs),并将其编译打包,为最终生成 KLIB 做好准备。</p>
2730+
<h4 id="c">获取 C 库定义</h4>
2731+
<p><code>processCLib</code> 函数中,首先会获取 C 库的定义, 这一步通过调用 LLVM 解析 <code>.def</code> 中指定的头文件来完成的。</p>
2732+
<pre><code>// nativeIndex 是一个抽象类,它描述了来自C头文件的定义的IR
2733+
val (nativeIndex, compilation) = buildNativeIndexImpl(library, verbose, allowPrecompiledHeaders = nativeLibsDir != null)
2734+
</code></pre>
2735+
<h4 id="kotlin-ir">构建 Kotlin IR 存根</h4>
2736+
<p>这一步的主要任务是从 C AST 中提取所有声明信息,并将 C 声明转换为 Kotlin IR 存根。</p>
2737+
<pre><code class="language-kotlin">class StubIrBuilder(private val context: StubIrContext) {
2738+
fun build(): StubIrBuilderResult {
2739+
// ...
2740+
nativeIndex.functions.filter { it.name !in excludedFunctions }.forEach { generateStubsForFunction(it) }
2741+
// ...
2742+
return StubIrBuilderResult(
2743+
stubs,
2744+
buildingContext.declarationMapper,
2745+
buildingContext.bridgeComponentsBuilder.build(),
2746+
buildingContext.wrapperComponentsBuilder.build()
2747+
)
2748+
}
2749+
}
2750+
2751+
// 生成类型映射和函数签名
2752+
fun mirror(declarationMapper: DeclarationMapper, type: Type): TypeMirror = when (type) {
2753+
is PrimitiveType -&gt; mirrorPrimitiveType(type, declarationMapper)
2754+
is RecordType -&gt; byRefTypeMirror(declarationMapper.getKotlinClassForPointed(type.decl).type)
2755+
is EnumType -&gt; // ...
2756+
is PointerType -&gt; // ...
2757+
is ArrayType -&gt; // ...
2758+
is FunctionType -&gt; byRefTypeMirror(KotlinTypes.cFunction.typeWith(getKotlinFunctionType(declarationMapper, type)))
2759+
is Typedef -&gt; // ...
2760+
is ObjCPointer -&gt; objCPointerMirror(declarationMapper, type)
2761+
else -&gt; TODO(type.toString())
2762+
}
2763+
</code></pre>
2764+
<p>这一步会处理基础类型(如整数、浮点数等)和复杂类型(如结构体、枚举等)的映射转换。它会生成相应的 Kotlin 类型,以便在 Kotlin 代码中使用 C 数据结构</p>
2765+
<p>这一步生成的内容实现上就是 CInterop 生成的 knm(kotlin native metadata) 文件,生成的内容就是函数声明,如下所示:</p>
2766+
<pre><code>package hello
2767+
2768+
@kotlinx.cinterop.internal.CCall
2769+
@kotlinx.cinterop.ExperimentalForeignApi
2770+
public external fun hello_from_c(timestamp: kotlin.Long): kotlin.Unit { /* compiled code */ }
2771+
</code></pre>
2772+
<h4 id="_5">构建桥接代码</h4>
2773+
<pre><code>class StubIrDriver(
2774+
private val context: StubIrContext,
2775+
private val options: DriverOptions
2776+
) {
2777+
fun run(): Result {
2778+
// 生成 Kotlin IR 存根
2779+
val builderResult = StubIrBuilder(context).build()
2780+
// 构建桥接代码
2781+
val bridgeBuilderResult = StubIrBridgeBuilder(context, builderResult).build()
2782+
// 生成 C 存根文件
2783+
outCFile.bufferedWriter().use {
2784+
emitCFile(context, it, entryPoint, bridgeBuilderResult.nativeBridges)
2785+
}
2786+
// ...
2787+
}
2788+
}
2789+
</code></pre>
2790+
<p>这一步的主要作用是生成 Kotlin 和 C 之间的桥接代码并写入 C 存根文件。它会创建函数调用包装器,生成属性访问器,并处理类型转换。</p>
2791+
<p>生成的内容如下所示,可以看到生成了<code>hello_from_c</code> 函数的调用包装器,后续 Kotlin 代码调用这个函数时,会通过这个包装器来调用 C 函数。</p>
2792+
<pre><code class="language-c">// __attribute__((always_inline)): 强制内联优化,减少函数调用开销
2793+
__attribute__((always_inline))
2794+
// 函数名 hello_hello_from_c_wrapper0 由 Kotlin/Native 自动生成
2795+
// 参数 long long p0 对应 Kotlin 的 Long 类型
2796+
void hello_hello_from_c_wrapper0(long long p0) {
2797+
hello_from_c(p0);
2798+
}
2799+
2800+
// 声明函数指针变量,用于存储包装器函数的地址
2801+
// __asm(&quot;knifunptr_hello0_hello_from_c&quot;) 指定汇编符号名,避免命名冲突
2802+
const void* knifunptr_hello0_hello_from_c __asm(&quot;knifunptr_hello0_hello_from_c&quot;);
2803+
// 将包装器函数的地址赋值给函数指针变量
2804+
// 这样 Kotlin 代码就可以通过这个函数指针安全地调用 C 函数
2805+
const void* knifunptr_hello0_hello_from_c = (const void*)&amp;hello_hello_from_c_wrapper0;
2806+
</code></pre>
2807+
<h3 id="_6">原生代码编译</h3>
2808+
<p>上面生成的 C 桥接代码,需要通过 LLVM 编译为 bc 文件。</p>
2809+
<pre><code>when (flavor) {
2810+
KotlinPlatform.NATIVE -&gt; {
2811+
// 编译为 LLVM 位码 (.bc) 文件
2812+
val outLib = File(nativeLibsDir, &quot;$libName.bc&quot;)
2813+
val compilerCmd = arrayOf(compiler, *compilerArgs,
2814+
&quot;-emit-llvm&quot;, &quot;-x&quot;, library.language.clangLanguageName,
2815+
&quot;-c&quot;, &quot;-&quot;, &quot;-o&quot;, outLib.absolutePath)
2816+
runCmd(compilerCmd, verbose, redirectInputFile = File(outCFile.absolutePath))
2817+
}
2818+
}
2819+
</code></pre>
2820+
<h4 id="klib">生成 KLIB</h4>
2821+
<p>最后一步是将生成的 Kotlin IR 存根和桥接代码序列化并写入 KLIB 文件。这一步会将库的元数据、IR Stub、manifest 文件等所有内容,按照 .klib 文件格式的标准目录结构,写入到由 -o 参数指定的输出目录中。</p>
2822+
<pre><code class="language-kotlin">when (stubIrOutput) {
2823+
is StubIrDriver.Result.Metadata -&gt; {
2824+
createInteropLibrary(
2825+
metadata = stubIrOutput.metadata, // Kotlin 元数据
2826+
nativeBitcodeFiles = compiledFiles + nativeOutputPath, // 原生位码
2827+
target = tool.target, // 目标平台
2828+
moduleName = moduleName, // 模块名
2829+
outputPath = outputPath, // 输出路径
2830+
manifest = def.manifestAddendProperties, // 清单属性
2831+
dependencies = stdlibDependency + imports.requiredLibraries,
2832+
nopack = nopack, // 是否打包
2833+
shortName = cinteropArguments.shortModuleName,
2834+
staticLibraries = resolveLibraries(staticLibraries, libraryPaths)
2835+
)
2836+
}
2837+
}
2838+
</code></pre>
25402839
<h2 id="cinterop">调试 CInterop 过程</h2>
2541-
<pre><code>./kotlin-native/dist/bin/run_konan cinterop -def ./compilerTestData/cinterop/hello.def -o compilerTestData/cinterop/output -J&quot;-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:50015&quot;
2840+
<pre><code>./kotlin-native/dist/bin/run_konan cinterop -def ./compilerTestData/cinterop/hello.def -o compilerTestData/cinterop/Hello -J&quot;-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:50015&quot;
2841+
2842+
./kotlin-native/dist/bin/run_konan konanc ./compilerTestData/cinterop/Main.kt -library ./compilerTestData/cinterop/Hello.klib -o ./compilerTestData/cinterop/Hello -J&quot;-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:50015&quot;
25422843
</code></pre>
25432844

25442845
<hr>
25452846
<div class="md-source-file">
25462847
<small>
25472848

25482849
最后更新:
2549-
<span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date">August 3, 2025</span>
2850+
<span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date">August 10, 2025</span>
25502851

25512852

25522853
</small>

foundation/kotlin-compiler-learn/kotlin-compiler-source/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3086,7 +3086,7 @@ <h2 id="_6">总结</h2>
30863086
<small>
30873087

30883088
最后更新:
3089-
<span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date">August 3, 2025</span>
3089+
<span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date">August 10, 2025</span>
30903090

30913091

30923092
</small>

foundation/kotlin-compiler-learn/kotlin-compiler-start/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2632,7 +2632,7 @@ <h2 id="kotlinjs">Kotlin/JS 编译器调试</h2>
26322632
<small>
26332633

26342634
最后更新:
2635-
<span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date">August 3, 2025</span>
2635+
<span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date">August 10, 2025</span>
26362636

26372637

26382638
</small>

foundation/kotlin-compiler-learn/kotlin-jack-backend/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2901,7 +2901,7 @@ <h2 id="_2">总结</h2>
29012901
<small>
29022902

29032903
最后更新:
2904-
<span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date">August 3, 2025</span>
2904+
<span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date">August 10, 2025</span>
29052905

29062906

29072907
</small>

0 commit comments

Comments
 (0)