{"id":487309,"date":"2026-07-14T18:26:44","date_gmt":"2026-07-14T18:26:44","guid":{"rendered":"https:\/\/savepearlharbor.com\/?p=487309"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=487309","title":{"rendered":"\u0410\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u0447\u0435\u0440\u0435\u0437 \u0431\u0438\u043e\u043c\u0435\u0442\u0440\u0438\u044e \u0432 Kotlin Multiplatform \u0438\u043b\u0438 Koncierge"},"content":{"rendered":"<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<h2>\u0412\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u0435<\/h2>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/701\/3bb\/5a9\/7013bb5a97e579f4104b16402e7c2bd7.png\" width=\"1672\" height=\"941\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/701\/3bb\/5a9\/7013bb5a97e579f4104b16402e7c2bd7.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/701\/3bb\/5a9\/7013bb5a97e579f4104b16402e7c2bd7.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u041d\u0430\u043a\u043e\u043d\u0435\u0446-\u0442\u043e \u043d\u0435\u043f\u043b\u043e\u0445\u043e \u043f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0432\u0448\u0438\u0441\u044c \u0432 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0438 \u0441\u0432\u043e\u0435\u0433\u043e \u043c\u0443\u043b\u044c\u0442\u0438\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f <a href=\"https:\/\/github.com\/UCASoft\/ModernMoney\" rel=\"noopener noreferrer nofollow\">Modern Money<\/a> \u043c\u043d\u0435 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u043b\u0430\u0441\u044c \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u0434\u043b\u044f Kotlin Multiplatform.<\/p>\n<p>\u0425\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0438\u043c\u0435\u0442\u044c \u043e\u0434\u0438\u043d API \u0434\u043b\u044f PIN-\u043a\u043e\u0434\u0430 \u0438 \u0431\u0438\u043e\u043c\u0435\u0442\u0440\u0438\u0438, \u0430 \u043f\u043e\u0434 \u043a\u0430\u043f\u043e\u0442\u043e\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Android Biometric Prompt, Windows Hello, Touch ID.<\/p>\n<p>\u0422\u0430\u043a \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f <a href=\"https:\/\/github.com\/Scogun\/koncierge\" rel=\"noopener noreferrer nofollow\">Koncierge<\/a> \u2014 \u043d\u0430\u0431\u043e\u0440 KMP-\u043c\u043e\u0434\u0443\u043b\u0435\u0439 <code>biometric<\/code>, <code>auth<\/code> \u0438 <code>auth-compose<\/code><\/p>\n<p>\u041a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0431\u044b, \u0437\u0430\u0434\u0430\u0447\u0430 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0430\u044f: \u043e\u0431\u044a\u044f\u0432\u0438\u0442\u044c <code>expect<\/code>-\u043a\u043b\u0430\u0441\u0441 \u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e <code>actual<\/code>-\u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0439.\u041d\u0430 Android \u044d\u0442\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c. \u0410 \u0432\u043e\u0442 Windows Hello, JVM-\u043c\u043e\u0434\u0443\u043b\u044c \u0438 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u0432\u0441\u0435\u0445 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u043e\u0432 \u0437\u0430\u0441\u0442\u0430\u0432\u0438\u043b\u0438 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0432 \u0442\u043e\u043c, \u043a\u0430\u043a Kotlin Multiplatform \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c.<\/p>\n<h3>\u0427\u0442\u043e \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c<\/h3>\n<p>\u041d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u043e\u0431\u0449\u0435\u0433\u043e \u043a\u043e\u0434\u0430 API \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u043b \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e:<\/p>\n<pre><code class=\"kotlin\">expect class Koncierge {    fun isBiometricAvailable(): Boolean    suspend fun authenticate(        message: String,        timeout: Duration = Duration.INFINITE,    ): BiometricResults}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:87px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0414\u0430\u043b\u044c\u0448\u0435 \u043a\u0430\u0436\u0434\u0430\u044f \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 \u0441\u0430\u043c\u0430 \u0440\u0435\u0448\u0430\u0435\u0442, \u043a\u0430\u043a\u0438\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u043c \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e.<\/p>\n<pre><code class=\"kotlin\">when (val result = Koncierge().authenticate(\"\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0435 \u043b\u0438\u0447\u043d\u043e\u0441\u0442\u044c\")) {    BiometricResults.AuthenticationSuccessful -&gt; {        \/\/ \u041c\u043e\u0436\u043d\u043e \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0437\u0430\u0449\u0438\u0449\u0435\u043d\u043d\u044b\u0439 \u044d\u043a\u0440\u0430\u043d.    }    BiometricResults.AuthenticationCancelled -&gt; {        \/\/ \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043e\u0442\u043c\u0435\u043d\u0438\u043b \u0437\u0430\u043f\u0440\u043e\u0441.    }    else -&gt; {        \/\/ \u041d\u0435\u0442 \u043e\u0431\u043e\u0440\u0443\u0434\u043e\u0432\u0430\u043d\u0438\u044f, \u043d\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u0430 \u0431\u0438\u043e\u043c\u0435\u0442\u0440\u0438\u044f \u0438\u043b\u0438 \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430.    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0421\u0430\u043c\u044b\u043c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u043c \u043c\u0435\u0441\u0442\u043e\u043c \u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f Windows.<\/p>\n<h3>Windows Hello<\/h3>\n<p>\u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u044f \u043f\u044b\u0442\u0430\u043b\u0441\u044f \u043d\u0430\u0439\u0442\u0438 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0432\u044b\u0437\u0432\u0430\u0442\u044c Windows Hello \u043f\u0440\u044f\u043c\u043e \u0438\u0437 Kotlin\/Native.\u00a0\u041d\u043e API Windows \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d \u0432\u043e\u043a\u0440\u0443\u0433 WinRT,\u00a0COM-\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u0432,\u00a0\u0444\u0430\u0431\u0440\u0438\u043a \u0430\u043a\u0442\u0438\u0432\u0430\u0446\u0438\u0438 \u0438 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439.\u00a0\u0414\u0430\u0436\u0435 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0432\u044b\u0437\u043e\u0432 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u0438 \u0431\u044b\u0441\u0442\u0440\u043e \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u044b\u043c.<\/p>\n<h4>CMake, \u043f\u043e\u0442\u043e\u043c Gradle<\/h4>\n<p>\u041f\u0435\u0440\u0432\u0443\u044e \u0440\u0430\u0431\u043e\u0447\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e C-\u043c\u043e\u0441\u0442\u0430 \u044f \u0441\u043e\u0431\u0438\u0440\u0430\u043b \u0447\u0435\u0440\u0435\u0437 CMake.\u00a0\u042d\u0442\u043e \u0431\u044b\u043b\u043e \u043b\u043e\u0433\u0438\u0447\u043d\u043e:\u00a0\u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439\u00a0<code>CMakeLists.txt<\/code>,\u00a0<code>add_library<\/code>,\u00a0\u0441\u043f\u0438\u0441\u043e\u043a \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0445 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u00a0\u2014\u00a0\u0438 \u0447\u0435\u0440\u0435\u0437 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u043c\u0430\u043d\u0434 \u043f\u043e\u043b\u0443\u0447\u0430\u043b\u0441\u044f\u00a0<code>libwindows_hello.a<\/code>.<\/p>\n<pre><code class=\"cmake\">add_library(windows_hello STATIC    src\/windows_hello.c)target_include_directories(windows_hello PUBLIC include)target_link_libraries(windows_hello PRIVATE    runtimeobject    user32)<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u0432\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e,\u00a0\u043d\u043e \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u043f\u043e\u044f\u0432\u0438\u043b\u0438\u0441\u044c \u0434\u0432\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0441\u0431\u043e\u0440\u043a\u0438.\u00a0Kotlin\/Native \u043e\u0436\u0438\u0434\u0430\u043b \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0439 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438,\u00a0\u0430 CMake \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u043b \u0441\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442,\u00a0\u0432\u044b\u0431\u0440\u0430\u0442\u044c \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 \u0438 \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u043d\u0443\u0436\u043d\u0443\u044e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e.<\/p>\n<p>\u0414\u043b\u044f \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0430 \u044d\u0442\u043e \u0442\u0435\u0440\u043f\u0438\u043c\u043e.\u00a0\u0414\u043b\u044f Gradle-\u0437\u0430\u0434\u0430\u0447,\u00a0CI \u0438 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0443\u0436\u0435 \u043d\u0430\u0447\u0438\u043d\u0430\u043b\u0430 \u0436\u0438\u0442\u044c \u0441\u0432\u043e\u0435\u0439 \u0436\u0438\u0437\u043d\u044c\u044e.\u00a0\u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u0440\u0435\u0448\u0438\u043b \u043e\u0442\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u043e\u0442 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e CMake-\u0448\u0430\u0433\u0430 \u0438 \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0442\u0438 \u0441\u0431\u043e\u0440\u043a\u0443 C-\u043a\u043e\u0434\u0430 \u0432 Gradle.<\/p>\n<p>\u041d\u0430 Windows Kotlin\/Native \u0432\u0441\u0435 \u0440\u0430\u0432\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 MinGW \u0432 \u0441\u0432\u043e\u0439 toolchain.\u00a0\u041e\u0441\u0442\u0430\u0432\u0430\u043b\u043e\u0441\u044c \u043d\u0430\u0439\u0442\u0438 \u0435\u0433\u043e\u00a0<code>gcc<\/code>\u00a0\u0438 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u044b\u0447\u043d\u044b\u0435\u00a0<code>Exec<\/code>-\u0437\u0430\u0434\u0430\u0447\u0438:<\/p>\n<pre><code class=\"kotlin\">val compileWindowsHelloNative = tasks.register&lt;Exec&gt;(\"compileWindowsHelloNative\") {    inputs.dir(windowsHelloNativeDir)    outputs.file(windowsHelloNativeObjectFile)    doFirst {        commandLine(            gcc.absolutePath,            \"-std=c11\",            \"-DWIN32_LEAN_AND_MEAN\",            \"-DNOMINMAX\",            \"-DWINDOWS_HELLO_STATIC\",            \"-I${windowsHelloNativeDir.dir(\"include\").asFile}\",            \"-c\",            windowsHelloNativeDir.file(\"src\/windows_hello.c\").asFile,            \"-o\",            windowsHelloNativeObjectFile.get().asFile,        )    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430 \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0432 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443:<\/p>\n<pre><code class=\"kotlin\">val buildWindowsHelloNative = tasks.register&lt;Exec&gt;(\"buildWindowsHelloNative\") {    dependsOn(compileWindowsHelloNative)    inputs.file(windowsHelloNativeObjectFile)    outputs.file(windowsHelloNativeArchiveFile)    doFirst {        commandLine(            ar.absolutePath,            \"rcs\",            windowsHelloNativeArchiveFile.get().asFile,            windowsHelloNativeObjectFile.get().asFile,        )    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u0432\u0430\u0436\u043d\u044b \u043d\u0435 \u0441\u0430\u043c\u0438 \u0432\u044b\u0437\u043e\u0432\u044b\u00a0<code>gcc<\/code>\u00a0\u0438\u00a0<code>ar<\/code>,\u00a0\u0430 \u0441\u0432\u044f\u0437\u0438 \u043c\u0435\u0436\u0434\u0443 \u0437\u0430\u0434\u0430\u0447\u0430\u043c\u0438.\u00a0<code>cinteropWindowsHelloMingwX64<\/code>\u00a0\u0438 \u043b\u0438\u043d\u043a\u043e\u0432\u043a\u0430 Windows-\u0431\u0438\u043d\u0430\u0440\u043d\u0438\u043a\u043e\u0432 \u0437\u0430\u0432\u0438\u0441\u044f\u0442 \u043e\u0442\u00a0<code>buildWindowsHelloNative<\/code>.\u00a0Gradle \u043f\u043e\u043d\u0438\u043c\u0430\u0435\u0442,\u00a0\u043a\u0430\u043a\u043e\u0439 \u0444\u0430\u0439\u043b \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432\u0445\u043e\u0434\u043e\u043c,\u00a0\u043a\u0430\u043a\u043e\u0439\u00a0\u2014\u00a0\u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u043c,\u00a0\u0438 \u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0432\u0441\u0435 \u0432 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435.<\/p>\n<p>\u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 CMake \u043e\u0441\u0442\u0430\u043b\u0441\u044f \u0443\u0434\u043e\u0431\u043d\u044b\u043c \u0432\u043e\u0441\u043f\u043e\u043c\u0438\u043d\u0430\u043d\u0438\u0435\u043c \u043e \u043f\u0435\u0440\u0432\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438,\u00a0\u0430 \u043f\u0440\u043e\u0435\u043a\u0442 \u043f\u0435\u0440\u0435\u0448\u0435\u043b \u043d\u0430 \u0447\u0438\u0441\u0442\u044b\u0439 Gradle.\u00a0\u0422\u043e\u0447\u043d\u0435\u0435,\u00a0\u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u043f\u043e-\u043f\u0440\u0435\u0436\u043d\u0435\u043c\u0443 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439,\u00a0\u043d\u043e \u0442\u043e\u0447\u043a\u0430 \u0432\u0445\u043e\u0434\u0430 \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u0442\u0435\u043f\u0435\u0440\u044c \u043e\u0434\u043d\u0430\u00a0\u2014\u00a0Gradle.<\/p>\n<h4>\u041d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 C-\u043c\u043e\u0441\u0442<\/h4>\n<p>\u0412 \u0438\u0442\u043e\u0433\u0435 \u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043b \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0443\u044e \u043e\u0431\u0435\u0440\u0442\u043a\u0443 \u043d\u0430 C.\u00a0\u041e\u043d\u0430 \u0441\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u0434\u0435\u0442\u0430\u043b\u0438 Windows API \u0438 \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 Kotlin \u0432\u0441\u0435\u0433\u043e \u0434\u0432\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438:<\/p>\n<pre><code class=\"cpp\">typedef struct WindowsHelloResult {    int32_t code;    int32_t hresult;} WindowsHelloResult;WINDOWS_HELLO_API int32_t windows_hello_check_availability(    WindowsHelloResult* out_result);WINDOWS_HELLO_API int32_t windows_hello_request_verification(    uint64_t owner_window_handle,    const wchar_t* prompt,    WindowsHelloResult* out_result);<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0417\u0430 \u044d\u0442\u043e\u0439 \u0433\u0440\u0430\u043d\u0438\u0446\u0435\u0439 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432\u0441\u044f \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 WinRT:<\/p>\n<ul>\n<li>\n<p>\u0447\u0435\u0440\u0435\u0437\u00a0<code>RoGetActivationFactory<\/code>\u00a0\u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u0444\u0430\u0431\u0440\u0438\u043a\u0430\u00a0<code>UserConsentVerifier<\/code>;<\/p>\n<\/li>\n<li>\n<p>\u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f\u00a0<code>CheckAvailabilityAsync<\/code>\u00a0\u0438\u043b\u0438\u00a0<code>RequestVerificationForWindowAsync<\/code>;<\/p>\n<\/li>\n<li>\n<p>\u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u0430\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u043e\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0434\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f;<\/p>\n<\/li>\n<li>\n<p>\u043a\u043e\u0434 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 \u0438\u00a0<code>HRESULT<\/code>\u00a0\u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0432 \u043f\u0440\u043e\u0441\u0442\u0443\u044e C-\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443.<\/p>\n<\/li>\n<\/ul>\n<p>\u041e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u043b\u0441\u044f \u0438\u043c\u0435\u043d\u043d\u043e C API.\u00a0Kotlin\/Native \u0443\u043c\u0435\u0435\u0442 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0445\u043e\u0440\u043e\u0448\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 C-\u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430\u043c\u0438 \u0447\u0435\u0440\u0435\u0437\u00a0<code>cinterop<\/code>,\u00a0\u0430 C++-ABI \u0438 WinRT-\u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u044f\u043b\u0438 \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u0441\u043b\u043e\u0439,\u00a0\u0438 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043b\u0438 \u0445\u043e\u0442\u044f \u0431\u044b CMake.\u00a0\u041d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 Kotlin\/Native \u0432\u044b\u0437\u043e\u0432 \u0442\u0435\u043f\u0435\u0440\u044c \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043f\u043e\u0447\u0442\u0438 \u043a\u0430\u043a \u043e\u0431\u044b\u0447\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f:<\/p>\n<pre><code class=\"kotlin\">fun requestVerification(    prompt: String,    ownerWindowHandle: Long = 0,): WindowsHelloVerification = memScoped {    val out = alloc&lt;WindowsHelloResult&gt;()    windows_hello_request_verification(        ownerWindowHandle.toULong(),        prompt.wcstr.ptr,        out.ptr,    )    WindowsHelloVerification(        result = verificationFromCode(out.code),        hresult = out.hresult,    )}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h3>JVM \u0438\u043b\u0438 \u043f\u043e\u0447\u0435\u043c\u0443 \u043c\u044b \u043d\u0435 \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Kotlin\/Native-\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443<\/h3>\n<p>\u041f\u043e\u0447\u0442\u0438 \u0441\u0440\u0430\u0437\u0443 \u043f\u043e\u0441\u043b\u0435 Windows-\u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u0432\u043e\u043f\u0440\u043e\u0441:\u00a0\u0430 \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u0441 JVM?<\/p>\n<p>Kotlin\/Native \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 C-\u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0447\u0435\u0440\u0435\u0437\u00a0<code>cinterop<\/code>\u00a0\u0438 \u043b\u0438\u043d\u043a\u0443\u0435\u0442 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443:<\/p>\n<pre><code class=\"elixir\">headers = windows_hello.hpackage = windowshellocompilerOpts = -DWINDOWS_HELLO_STATIC -Isrc\/nativeInterop\/windows-hello\/includestaticLibraries = libwindows_hello.alibraryPaths = build\/windows-hello-native\/bin\/Release build\/windows-hello-native\/binlinkerOpts = -lruntimeobject -luser32<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041d\u043e JVM \u043d\u0435 \u0443\u043c\u0435\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043f\u0430\u043a\u0435\u0442\u00a0<code>windowshello<\/code>\u00a0\u0438 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439\u00a0<code>.a<\/code>-\u0430\u0440\u0445\u0438\u0432.\u00a0\u0414\u043b\u044f \u043d\u0435\u0435 \u043d\u0443\u0436\u0435\u043d \u0434\u0440\u0443\u0433\u043e\u0439 \u043f\u0443\u0442\u044c:\u00a0\u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0438 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438.\u00a0\u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 C-\u0444\u0430\u0439\u043b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u0432 \u0434\u0432\u0430 \u0440\u0430\u0437\u043d\u044b\u0445 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430:<\/p>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<td>\n<p align=\"left\">\u041f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u044c<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041a\u0430\u043a \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">Kotlin\/Native\u00a0<code>mingwX64<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">libwindows_hello.a<\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>cinterop<\/code>\u00a0\u0438 \u043b\u0438\u043d\u043a\u043e\u0432\u043a\u0430 native-\u0431\u0438\u043d\u0430\u0440\u043d\u0438\u043a\u0430<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">JVM<\/p>\n<\/td>\n<td>\n<p align=\"left\">windows_hello.dll<\/p>\n<\/td>\n<td>\n<p align=\"left\">JNA \u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0438\u0437 JVM-\u0440\u0435\u0441\u0443\u0440\u0441\u0430<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>\u041d\u0430 JVM \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u00a0<a href=\"https:\/\/github.com\/java-native-access\/jna\" rel=\"noopener noreferrer nofollow\">JNA<\/a>.\u00a0\u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u043e\u0431\u044a\u044f\u0432\u0438\u043b \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430:<\/p>\n<pre><code class=\"kotlin\">private interface WindowsHelloLibrary : Library {    fun windows_hello_check_availability(        outResult: WindowsHelloResult,    ): Int    fun windows_hello_request_verification(        ownerWindowHandle: Long,        prompt: WString,        outResult: WindowsHelloResult,    ): Int}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>JVM-\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u044f \u043d\u0435 \u0441\u0442\u0430\u043b \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0432 \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438 \u0432\u0440\u0443\u0447\u043d\u0443\u044e.\u00a0Gradle \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442 DLL \u0432\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e build-\u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e,\u00a0\u0430 \u0437\u0430\u0442\u0435\u043c \u0437\u0430\u0434\u0430\u0447\u0430\u00a0<code>syncWindowsHelloJvmNativeResource<\/code>\u00a0\u043a\u043b\u0430\u0434\u0435\u0442 \u0435\u0435 \u0432 \u0440\u0435\u0441\u0443\u0440\u0441 <code>native\/windows\/x86-64\/windows_hello.dll<\/code><\/p>\n<p>\u0412\u043e \u0432\u0440\u0435\u043c\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0438\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u0442\u0441\u044f \u0438\u0437 JAR \u0432\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0438 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 JNA:<\/p>\n<pre><code class=\"kotlin\">val resource = javaClass.getResourceAsStream(resourcePath)val libraryFile = Files.createTempFile(\"koncierge-windows-hello\", \".dll\")resource.use { input -&gt;    libraryFile.outputStream().use { output -&gt;        input.copyTo(output)    }}Native.load(libraryFile.absolutePathString(), WindowsHelloLibrary::class.java)<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u0440\u044f\u043c\u043e \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c DLL \u0438\u0437\u043d\u0443\u0442\u0440\u0438 JAR \u043d\u0435\u043b\u044c\u0437\u044f, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0437\u0434\u0435\u0441\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c.<\/p>\n<p>\u0418\u043c\u0435\u043d\u043d\u043e \u043d\u0430 \u044d\u0442\u043e\u043c \u043c\u0435\u0441\u0442\u0435 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u044f\u0432\u043d\u043e \u0441\u0432\u044f\u0437\u0430\u0442\u044c JVM-\u043c\u043e\u0434\u0443\u043b\u044c \u0441 native-\u0446\u0435\u043b\u044f\u043c\u0438 \u0438 \u0437\u0430\u0434\u0430\u0447\u0430\u043c\u0438 \u0441\u0431\u043e\u0440\u043a\u0438.\u00a0\u042d\u0442\u043e \u043d\u0435 \u043e\u0431\u044b\u0447\u043d\u0430\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c \u0432\u0438\u0434\u0430\u00a0<code>implementation(project(...))<\/code>.\u00a0JVM-\u0447\u0430\u0441\u0442\u0438 \u043d\u0443\u0436\u043d\u0430 \u043d\u0430\u0442\u0438\u0432\u043d\u0430\u044f DLL,\u00a0\u0430\u00a0<code>mingwX64<\/code>-\u0447\u0430\u0441\u0442\u0438\u00a0\u2014\u00a0\u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430.\u00a0\u0417\u043d\u0430\u0447\u0438\u0442,\u00a0Gradle-\u0433\u0440\u0430\u0444 \u0434\u043e\u043b\u0436\u0435\u043d \u0437\u043d\u0430\u0442\u044c \u043f\u0440\u043e \u043e\u0431\u0435 \u0432\u0435\u0442\u043a\u0438:<\/p>\n<pre><code>jvmProcessResources    \u2514\u2500\u2500 syncWindowsHelloJvmNativeResource            \u2514\u2500\u2500 buildWindowsHelloJvmNative                    \u2514\u2500\u2500 compileWindowsHelloJvmNativecinteropWindowsHelloMingwX64    \u2514\u2500\u2500 buildWindowsHelloNative            \u2514\u2500\u2500 compileWindowsHelloNative<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041d\u0430 Windows \u044d\u0442\u043e \u0441\u0432\u044f\u0437\u044b\u0432\u0430\u043d\u0438\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e.\u00a0\u041d\u0430 macOS \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u0448\u0430\u0433:\u00a0\u043f\u0440\u0438 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0435 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0432\u043a\u043b\u044e\u0447\u0430\u0442\u044c\u00a0<code>mingwX64<\/code>\u00a0\u0432 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435,\u00a0\u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u0441\u0430\u043c Windows-\u0431\u0438\u043d\u0430\u0440\u043d\u0438\u043a \u043d\u0430 \u044d\u0442\u043e\u043c \u0430\u0433\u0435\u043d\u0442\u0435 \u043d\u0435 \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f.\u00a0\u0418\u043d\u0430\u0447\u0435 macOS-\u0430\u0433\u0435\u043d\u0442 \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0435 \u0437\u043d\u0430\u0435\u0442,\u00a0\u0447\u0442\u043e \u0432 \u0438\u0442\u043e\u0433\u043e\u0432\u043e\u0439 KMP-\u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0434\u043e\u043b\u0436\u0435\u043d \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c Windows target.<\/p>\n<h3>\u041f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f: \u043f\u043e\u0447\u0435\u043c\u0443 \u043e\u0434\u043d\u043e\u0433\u043e build-\u0430\u0433\u0435\u043d\u0442\u0430 \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e<\/h3>\n<p>\u041b\u043e\u043a\u0430\u043b\u044c\u043d\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u043d\u0443\u0436\u043d\u044b\u0439 target \u043d\u0430 \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0435\u0439 \u043c\u0430\u0448\u0438\u043d\u0435.\u00a0\u0412 CI \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f \u043c\u0435\u043d\u0435\u0435 \u0440\u043e\u043c\u0430\u043d\u0442\u0438\u0447\u043d\u0430\u044f:\u00a0\u0440\u0430\u0437\u043d\u044b\u0435 native targets \u0442\u0440\u0435\u0431\u0443\u044e\u0442 \u0440\u0430\u0437\u043d\u044b\u0435 host-\u0441\u0438\u0441\u0442\u0435\u043c\u044b.<\/p>\n<p>\u0412 \u043c\u043e\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 Windows-\u0430\u0433\u0435\u043d\u0442 \u0434\u043e\u043b\u0436\u0435\u043d \u0441\u043e\u0431\u0440\u0430\u0442\u044c:<\/p>\n<ul>\n<li>\n<p><code>mingwX64<\/code>-\u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044e;<\/p>\n<\/li>\n<li>\n<p>Windows Hello DLL \u0434\u043b\u044f JVM.<\/p>\n<\/li>\n<\/ul>\n<p>\u0410 macOS-\u0430\u0433\u0435\u043d\u0442 \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442:<\/p>\n<ul>\n<li>\n<p>macOS ARM64-\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u0434\u043b\u044f Touch ID;<\/p>\n<\/li>\n<li>\n<p>JVM- \u0438 Android-\u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438;<\/p>\n<\/li>\n<li>\n<p>\u043e\u0431\u0449\u0438\u0435 KMP-\u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435;<\/p>\n<\/li>\n<li>\n<p>\u0444\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u043d\u0430\u0431\u043e\u0440 \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0432 Maven Central.<\/p>\n<\/li>\n<\/ul>\n<p>\u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u044f \u043f\u044b\u0442\u0430\u043b\u0441\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044c,\u00a0\u0447\u0442\u043e \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043e\u0434\u043d\u0438\u043c \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u043c Gradle-\u0432\u044b\u0437\u043e\u0432\u043e\u043c \u043d\u0430 \u043b\u044e\u0431\u043e\u043c \u0430\u0433\u0435\u043d\u0442\u0435.\u00a0\u041d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0432\u0441\u0435 libraries \u043d\u0430 \u043e\u0434\u043d\u043e\u043c build-\u0430\u0433\u0435\u043d\u0442\u0435:\u00a0Windows-\u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b \u0442\u0440\u0435\u0431\u0443\u044e\u0442 Windows,\u00a0\u0430 macOS-\u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b\u00a0\u2014\u00a0macOS.<\/p>\n<p>\u041f\u043e\u044d\u0442\u043e\u043c\u0443 workflow \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d \u043d\u0430 \u0434\u0432\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u0447\u0430\u0441\u0442\u0438.<\/p>\n<h4>Windows job<\/h4>\n<p>\u041d\u0430 Windows \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u0437\u0430\u0434\u0430\u0447\u0438:<\/p>\n<pre><code class=\"lisp\">:biometric:publishMingwX64PublicationToWindowsStagingRepository:biometric:syncWindowsHelloJvmNativeResource<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e workflow \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442 \u0434\u0432\u0430 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u0430:<\/p>\n<ul>\n<li>\n<p>\u043f\u043e\u0434\u043f\u0438\u0441\u0430\u043d\u043d\u0443\u044e <code>mingwX64<\/code>-\u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044e;<\/p>\n<\/li>\n<li>\n<p><code>windows_hello.dll<\/code> \u0434\u043b\u044f JVM.<\/p>\n<\/li>\n<\/ul>\n<p>\u0412\u0430\u0436\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442:\u00a0Windows job \u043d\u0435 \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0430\u0441\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u043f\u0440\u044f\u043c\u043e \u0432 Maven Central.\u00a0\u041e\u043d\u0430 \u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432 staging-\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442 \u0435\u0433\u043e \u0434\u0430\u043b\u044c\u0448\u0435.<\/p>\n<h4>macOS job<\/h4>\n<p>macOS-\u0430\u0433\u0435\u043d\u0442 \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u0435\u0442 \u043e\u0431\u0430 Windows-\u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u0430 \u0432 \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0435 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438:<\/p>\n<pre><code class=\"lisp\">biometric\/build\/windows-maven-repositorybiometric\/build\/generated\/windows-hello-jvm\/resources\/native\/windows\/x86-64<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0417\u0430\u0442\u0435\u043c \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 targets \u0438 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0435\u0442 Windows-\u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044e \u0441 \u043e\u0431\u0449\u0438\u043c \u043d\u0430\u0431\u043e\u0440\u043e\u043c:<\/p>\n<pre><code class=\"kotlin\">    tasks.register&lt;Sync&gt;(\"assembleMavenCentralStagingRepository\") {        group = \"publishing\"        description = \"Combines the biometric publications built on macOS and Windows for Maven Central.\"        dependsOn(            \"prepareMavenCentralPublishing\",            \"publishAndroidPublicationToMacosStagingRepository\",            \"publishJvmPublicationToMacosStagingRepository\",            \"publishKotlinMultiplatformPublicationToMacosStagingRepository\",            \"publishMacosArm64PublicationToMacosStagingRepository\",        )        from(macosStaging)        from(layout.buildDirectory.dir(\"windows-maven-repository\"))        into(mavenCentralStaging)        doLast {            val version = project.version.toString()            val groupPath = project.group.toString().replace('.', '\/')            val repositoryRoot = mavenCentralStaging.get().asFile            val expectedArtifactIds = listOf(                \"biometric\",                \"biometric-android\",                \"biometric-jvm\",                \"biometric-macosarm64\",                \"biometric-mingwx64\",            )            expectedArtifactIds.forEach { artifactId -&gt;                val pom = repositoryRoot.resolve(\"$groupPath\/$artifactId\/$version\/$artifactId-$version.pom\")                if (!pom.isFile) {                    throw GradleException(\"Maven Central staging is missing $artifactId:$version (${pom.absolutePath}).\")                }            }        }    }<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0412 \u0438\u0442\u043e\u0433\u0435 \u0435\u0434\u0438\u043d\u044b\u0439 Maven Central bundle \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u043d\u0430 macOS,\u00a0\u043d\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0438 \u0443\u0436\u0435 \u0441\u043e\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u043d\u0430 Windows\u00a0<code>mingwX64<\/code>-\u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442.<\/p>\n<h3>\u0427\u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c \u0432 \u0438\u0442\u043e\u0433\u0435<\/h3>\n<p>\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0432\u0438\u0434\u0438\u0442 \u043e\u0434\u0438\u043d API:<\/p>\n<pre><code class=\"kotlin\">val koncierge = Koncierge()if (koncierge.isBiometricAvailable()) {    val result = koncierge.authenticate(\"\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0435 \u0432\u0445\u043e\u0434\")}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0410 \u0432\u043d\u0443\u0442\u0440\u0438 \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u043e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043c\u043d\u043e\u0433\u043e \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435\u043d\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b:<\/p>\n<ul>\n<li>\n<p><em> <\/em>Windows Hello \u0441\u043f\u0440\u044f\u0442\u0430\u043d \u0437\u0430 C-\u043c\u043e\u0441\u0442\u043e\u043c;<\/p>\n<\/li>\n<li>\n<p>Kotlin\/Native \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 <code>cinterop<\/code> \u0438 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443;<\/p>\n<\/li>\n<li>\n<p>JVM \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 JNA \u0438 DLL, \u0443\u043f\u0430\u043a\u043e\u0432\u0430\u043d\u043d\u0443\u044e \u0432 \u0440\u0435\u0441\u0443\u0440\u0441;<\/p>\n<\/li>\n<li>\n<p>Gradle \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0438 C-\u0441\u0431\u043e\u0440\u043a\u043e\u0439, \u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u043c\u0438 \u0437\u0430\u0434\u0430\u0447;<\/p>\n<\/li>\n<li>\n<p>Windows \u0438 macOS \u0441\u043e\u0431\u0438\u0440\u0430\u044e\u0442 \u0440\u0430\u0437\u043d\u044b\u0435 \u0447\u0430\u0441\u0442\u0438 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438;<\/p>\n<\/li>\n<li>\n<p>Maven Central \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0435\u0434\u0438\u043d\u044b\u0439 \u043d\u0430\u0431\u043e\u0440 \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0445 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u043e\u0432.<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c,\u00a0\u043a\u0430\u043a \u043c\u043d\u0435 \u043a\u0430\u0436\u0435\u0442\u0441\u044f,\u00a0\u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u0443\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443,\u00a0\u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0437\u0434\u043e\u0440\u043e\u0432\u043e \u043e\u0431\u043b\u0435\u0433\u0447\u0438\u0442 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0437 biometric \u0432 KMP \u0440\u0435\u0448\u0435\u043d\u0438\u044f.<\/p>\n<p>\u041f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0441 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0435\u0439 \u043d\u0430\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u0432 Kotlin,\u00a0\u0443\u0433\u043b\u0443\u0431\u0438\u0442\u044c \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u0435 Gradle \u0441\u0431\u043e\u0440\u043e\u043a,\u00a0\u0432\u0441\u043f\u043e\u043c\u043d\u0438\u0442\u044c \u043f\u0435\u0440\u0432\u044b\u0439 \u043a\u0443\u0440\u0441 \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0438\u0442\u0435\u0442\u0430 \u0438 C,\u00a0\u043d\u0430\u043a\u043e\u043d\u0435\u0446!<\/p>\n<h3>\u0427\u0442\u043e \u0434\u0430\u043b\u044c\u0448\u0435?<\/h3>\n<p>\u0421\u0435\u0439\u0447\u0430\u0441 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0443\u043b\u0443\u0447\u0448\u0438\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u0435\u0449\u0435\u0439:\u00a0\u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u0435 \u0442\u0435\u0441\u0442\u044b \u0434\u043b\u044f \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0445 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0439,\u00a0\u0430\u043a\u043a\u0443\u0440\u0430\u0442\u043d\u0435\u0435 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u043a\u043e\u0434\u044b Windows Hello \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044e \u043d\u0430 \u0431\u043e\u043b\u044c\u0448\u0435\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0435 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440.<\/p>\n<p>\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e,\u00a0\u0441\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f \u043e\u0442\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u0438 \u043e\u0442 \u0447\u0430\u0441\u0442\u0438 \u0440\u0443\u0447\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u0432\u043e\u043a\u0440\u0443\u0433 WinRT.\u00a0\u041d\u043e \u043f\u043e\u043a\u0430 C-\u043c\u043e\u0441\u0442 \u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f \u0432\u043f\u043e\u043b\u043d\u0435 \u0440\u0430\u0437\u0443\u043c\u043d\u043e\u0439 \u0433\u0440\u0430\u043d\u0438\u0446\u0435\u0439:\u00a0Windows API \u043e\u0441\u0442\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0441\u0432\u043e\u0435\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u0435,\u00a0\u0430 Kotlin \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0438 \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0443\u0435\u043c\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441.<\/p>\n<p>\u0422\u0430\u043a \u0436\u0435 \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u043c\u043e\u0433 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c WinBio,\u00a0\u043d\u043e \u043f\u043e\u043a\u0430 \u044d\u0442\u043e\u0442 \u043a\u043e\u0434 \u043e\u0447\u0435\u043d\u044c \u0441\u044b\u0440\u043e\u0439.<\/p>\n<p>\u0421\u043f\u0430\u0441\u0438\u0431\u043e,\u00a0\u0447\u0442\u043e \u0434\u043e\u0447\u0438\u0442\u0430\u043b\u0438!\u00a0\u0411\u0443\u0434\u0443 \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u0435\u043d \u0437\u0430 \u043b\u044e\u0431\u044b\u0435 \u0438\u0434\u0435\u0438 \u043f\u043e \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0438\u043b\u0438 contributing&#8217;\u0430.<\/p>\n<\/div>\n<p>\u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/1059174\/\">https:\/\/habr.com\/ru\/articles\/1059174\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u0412\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u0435\u041d\u0430\u043a\u043e\u043d\u0435\u0446-\u0442\u043e \u043d\u0435\u043f\u043b\u043e\u0445\u043e \u043f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0432\u0448\u0438\u0441\u044c \u0432 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0438 \u0441\u0432\u043e\u0435\u0433\u043e \u043c\u0443\u043b\u044c\u0442\u0438\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f Modern Money \u043c\u043d\u0435 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u043b\u0430\u0441\u044c \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u0434\u043b\u044f Kotlin Multiplatform.\u0425\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0438\u043c\u0435\u0442\u044c \u043e\u0434\u0438\u043d API \u0434\u043b\u044f PIN-\u043a\u043e\u0434\u0430 \u0438 \u0431\u0438\u043e\u043c\u0435\u0442\u0440\u0438\u0438, \u0430 \u043f\u043e\u0434 \u043a\u0430\u043f\u043e\u0442\u043e\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Android Biometric Prompt, Windows Hello, Touch ID.\u0422\u0430\u043a \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f Koncierge \u2014 \u043d\u0430\u0431\u043e\u0440 KMP-\u043c\u043e\u0434\u0443\u043b\u0435\u0439 biometric, auth \u0438 auth-compose\u041a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0431\u044b, \u0437\u0430\u0434\u0430\u0447\u0430 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0430\u044f: \u043e\u0431\u044a\u044f\u0432\u0438\u0442\u044c expect-\u043a\u043b\u0430\u0441\u0441 \u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e actual-\u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0439.\u041d\u0430 Android \u044d\u0442\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c. \u0410 \u0432\u043e\u0442 Windows Hello, JVM-\u043c\u043e\u0434\u0443\u043b\u044c \u0438 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u0432\u0441\u0435\u0445 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u043e\u0432 \u0437\u0430\u0441\u0442\u0430\u0432\u0438\u043b\u0438 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0432 \u0442\u043e\u043c, \u043a\u0430\u043a Kotlin Multiplatform \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c.\u0427\u0442\u043e \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c\u041d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u043e\u0431\u0449\u0435\u0433\u043e \u043a\u043e\u0434\u0430 API \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u043b \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e:expect class Koncierge {    fun isBiometricAvailable(): Boolean    suspend fun authenticate(        message: String,        timeout: Duration = Duration.INFINITE,    ): BiometricResults}\u0414\u0430\u043b\u044c\u0448\u0435 \u043a\u0430\u0436\u0434\u0430\u044f \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 \u0441\u0430\u043c\u0430 \u0440\u0435\u0448\u0430\u0435\u0442, \u043a\u0430\u043a\u0438\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u043c \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e.when (val result = Koncierge().authenticate(&#171;\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0435 \u043b\u0438\u0447\u043d\u043e\u0441\u0442\u044c&#187;)) {    BiometricResults.AuthenticationSuccessful -&gt; {        \/\/ \u041c\u043e\u0436\u043d\u043e \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0437\u0430\u0449\u0438\u0449\u0435\u043d\u043d\u044b\u0439 \u044d\u043a\u0440\u0430\u043d.    }    BiometricResults.AuthenticationCancelled -&gt; {        \/\/ \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043e\u0442\u043c\u0435\u043d\u0438\u043b \u0437\u0430\u043f\u0440\u043e\u0441.    }    else -&gt; {        \/\/ \u041d\u0435\u0442 \u043e\u0431\u043e\u0440\u0443\u0434\u043e\u0432\u0430\u043d\u0438\u044f, \u043d\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u0430 \u0431\u0438\u043e\u043c\u0435\u0442\u0440\u0438\u044f \u0438\u043b\u0438 \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430.    }}\u0421\u0430\u043c\u044b\u043c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u043c \u043c\u0435\u0441\u0442\u043e\u043c \u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f Windows.Windows Hello\u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u044f \u043f\u044b\u0442\u0430\u043b\u0441\u044f \u043d\u0430\u0439\u0442\u0438 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0432\u044b\u0437\u0432\u0430\u0442\u044c Windows Hello \u043f\u0440\u044f\u043c\u043e \u0438\u0437 Kotlin\/Native.\u00a0\u041d\u043e API Windows \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d \u0432\u043e\u043a\u0440\u0443\u0433 WinRT,\u00a0COM-\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u0432,\u00a0\u0444\u0430\u0431\u0440\u0438\u043a \u0430\u043a\u0442\u0438\u0432\u0430\u0446\u0438\u0438 \u0438 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439.\u00a0\u0414\u0430\u0436\u0435 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0432\u044b\u0437\u043e\u0432 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u0438 \u0431\u044b\u0441\u0442\u0440\u043e \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u044b\u043c.CMake, \u043f\u043e\u0442\u043e\u043c Gradle\u041f\u0435\u0440\u0432\u0443\u044e \u0440\u0430\u0431\u043e\u0447\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e C-\u043c\u043e\u0441\u0442\u0430 \u044f \u0441\u043e\u0431\u0438\u0440\u0430\u043b \u0447\u0435\u0440\u0435\u0437 CMake.\u00a0\u042d\u0442\u043e \u0431\u044b\u043b\u043e \u043b\u043e\u0433\u0438\u0447\u043d\u043e:\u00a0\u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439\u00a0CMakeLists.txt,\u00a0add_library,\u00a0\u0441\u043f\u0438\u0441\u043e\u043a \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0445 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u00a0\u2014\u00a0\u0438 \u0447\u0435\u0440\u0435\u0437 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u043c\u0430\u043d\u0434 \u043f\u043e\u043b\u0443\u0447\u0430\u043b\u0441\u044f\u00a0libwindows_hello.a.add_library(windows_hello STATIC    src\/windows_hello.c)target_include_directories(windows_hello PUBLIC include)target_link_libraries(windows_hello PRIVATE    runtimeobject    user32)\u041d\u0430 \u044d\u0442\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u0432\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e,\u00a0\u043d\u043e \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u043f\u043e\u044f\u0432\u0438\u043b\u0438\u0441\u044c \u0434\u0432\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0441\u0431\u043e\u0440\u043a\u0438.\u00a0Kotlin\/Native \u043e\u0436\u0438\u0434\u0430\u043b \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0439 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438,\u00a0\u0430 CMake \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u043b \u0441\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442,\u00a0\u0432\u044b\u0431\u0440\u0430\u0442\u044c \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 \u0438 \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u043d\u0443\u0436\u043d\u0443\u044e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e.\u0414\u043b\u044f \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0430 \u044d\u0442\u043e \u0442\u0435\u0440\u043f\u0438\u043c\u043e.\u00a0\u0414\u043b\u044f Gradle-\u0437\u0430\u0434\u0430\u0447,\u00a0CI \u0438 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0443\u0436\u0435 \u043d\u0430\u0447\u0438\u043d\u0430\u043b\u0430 \u0436\u0438\u0442\u044c \u0441\u0432\u043e\u0435\u0439 \u0436\u0438\u0437\u043d\u044c\u044e.\u00a0\u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u0440\u0435\u0448\u0438\u043b \u043e\u0442\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u043e\u0442 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e CMake-\u0448\u0430\u0433\u0430 \u0438 \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0442\u0438 \u0441\u0431\u043e\u0440\u043a\u0443 C-\u043a\u043e\u0434\u0430 \u0432 Gradle.\u041d\u0430 Windows Kotlin\/Native \u0432\u0441\u0435 \u0440\u0430\u0432\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 MinGW \u0432 \u0441\u0432\u043e\u0439 toolchain.\u00a0\u041e\u0441\u0442\u0430\u0432\u0430\u043b\u043e\u0441\u044c \u043d\u0430\u0439\u0442\u0438 \u0435\u0433\u043e\u00a0gcc\u00a0\u0438 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u044b\u0447\u043d\u044b\u0435\u00a0Exec-\u0437\u0430\u0434\u0430\u0447\u0438:val compileWindowsHelloNative = tasks.register&lt;Exec&gt;(&#171;compileWindowsHelloNative&#187;) {    inputs.dir(windowsHelloNativeDir)    outputs.file(windowsHelloNativeObjectFile)    doFirst {        commandLine(            gcc.absolutePath,            &#171;-std=c11&#187;,            &#171;-DWIN32_LEAN_AND_MEAN&#187;,            &#171;-DNOMINMAX&#187;,            &#171;-DWINDOWS_HELLO_STATIC&#187;,            &#171;-I${windowsHelloNativeDir.dir(&#171;include&#187;).asFile}&#187;,            &#171;-c&#187;,            windowsHelloNativeDir.file(&#171;src\/windows_hello.c&#187;).asFile,            &#171;-o&#187;,            windowsHelloNativeObjectFile.get().asFile,        )    }}\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430 \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0432 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443:val buildWindowsHelloNative = tasks.register&lt;Exec&gt;(&#171;buildWindowsHelloNative&#187;) {    dependsOn(compileWindowsHelloNative)    inputs.file(windowsHelloNativeObjectFile)    outputs.file(windowsHelloNativeArchiveFile)    doFirst {        commandLine(            ar.absolutePath,            &#171;rcs&#187;,            windowsHelloNativeArchiveFile.get().asFile,            windowsHelloNativeObjectFile.get().asFile,        )    }}\u0417\u0434\u0435\u0441\u044c \u0432\u0430\u0436\u043d\u044b \u043d\u0435 \u0441\u0430\u043c\u0438 \u0432\u044b\u0437\u043e\u0432\u044b\u00a0gcc\u00a0\u0438\u00a0ar,\u00a0\u0430 \u0441\u0432\u044f\u0437\u0438 \u043c\u0435\u0436\u0434\u0443 \u0437\u0430\u0434\u0430\u0447\u0430\u043c\u0438.\u00a0cinteropWindowsHelloMingwX64\u00a0\u0438 \u043b\u0438\u043d\u043a\u043e\u0432\u043a\u0430 Windows-\u0431\u0438\u043d\u0430\u0440\u043d\u0438\u043a\u043e\u0432 \u0437\u0430\u0432\u0438\u0441\u044f\u0442 \u043e\u0442\u00a0buildWindowsHelloNative.\u00a0Gradle \u043f\u043e\u043d\u0438\u043c\u0430\u0435\u0442,\u00a0\u043a\u0430\u043a\u043e\u0439 \u0444\u0430\u0439\u043b \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432\u0445\u043e\u0434\u043e\u043c,\u00a0\u043a\u0430\u043a\u043e\u0439\u00a0\u2014\u00a0\u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u043c,\u00a0\u0438 \u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0432\u0441\u0435 \u0432 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435.\u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 CMake \u043e\u0441\u0442\u0430\u043b\u0441\u044f \u0443\u0434\u043e\u0431\u043d\u044b\u043c \u0432\u043e\u0441\u043f\u043e\u043c\u0438\u043d\u0430\u043d\u0438\u0435\u043c \u043e \u043f\u0435\u0440\u0432\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438,\u00a0\u0430 \u043f\u0440\u043e\u0435\u043a\u0442 \u043f\u0435\u0440\u0435\u0448\u0435\u043b \u043d\u0430 \u0447\u0438\u0441\u0442\u044b\u0439 Gradle.\u00a0\u0422\u043e\u0447\u043d\u0435\u0435,\u00a0\u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u043f\u043e-\u043f\u0440\u0435\u0436\u043d\u0435\u043c\u0443 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439,\u00a0\u043d\u043e \u0442\u043e\u0447\u043a\u0430 \u0432\u0445\u043e\u0434\u0430 \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u0442\u0435\u043f\u0435\u0440\u044c \u043e\u0434\u043d\u0430\u00a0\u2014\u00a0Gradle.\u041d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 C-\u043c\u043e\u0441\u0442\u0412 \u0438\u0442\u043e\u0433\u0435 \u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043b \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0443\u044e \u043e\u0431\u0435\u0440\u0442\u043a\u0443 \u043d\u0430 C.\u00a0\u041e\u043d\u0430 \u0441\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u0434\u0435\u0442\u0430\u043b\u0438 Windows API \u0438 \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 Kotlin \u0432\u0441\u0435\u0433\u043e \u0434\u0432\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438:typedef struct WindowsHelloResult {    int32_t code;    int32_t hresult;} WindowsHelloResult;WINDOWS_HELLO_API int32_t windows_hello_check_availability(    WindowsHelloResult* out_result);WINDOWS_HELLO_API int32_t windows_hello_request_verification(    uint64_t owner_window_handle,    const wchar_t* prompt,    WindowsHelloResult* out_result);\u0417\u0430 \u044d\u0442\u043e\u0439 \u0433\u0440\u0430\u043d\u0438\u0446\u0435\u0439 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432\u0441\u044f \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 WinRT:\u0447\u0435\u0440\u0435\u0437\u00a0RoGetActivationFactory\u00a0\u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u0444\u0430\u0431\u0440\u0438\u043a\u0430\u00a0UserConsentVerifier;\u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f\u00a0CheckAvailabilityAsync\u00a0\u0438\u043b\u0438\u00a0RequestVerificationForWindowAsync;\u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u0430\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u043e\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0434\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f;\u043a\u043e\u0434 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 \u0438\u00a0HRESULT\u00a0\u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0432 \u043f\u0440\u043e\u0441\u0442\u0443\u044e C-\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443.\u041e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u043b\u0441\u044f \u0438\u043c\u0435\u043d\u043d\u043e C API.\u00a0Kotlin\/Native \u0443\u043c\u0435\u0435\u0442 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0445\u043e\u0440\u043e\u0448\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 C-\u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430\u043c\u0438 \u0447\u0435\u0440\u0435\u0437\u00a0cinterop,\u00a0\u0430 C++-ABI \u0438 WinRT-\u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u044f\u043b\u0438 \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u0441\u043b\u043e\u0439,\u00a0\u0438 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043b\u0438 \u0445\u043e\u0442\u044f \u0431\u044b CMake.\u00a0\u041d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 Kotlin\/Native \u0432\u044b\u0437\u043e\u0432 \u0442\u0435\u043f\u0435\u0440\u044c \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043f\u043e\u0447\u0442\u0438 \u043a\u0430\u043a \u043e\u0431\u044b\u0447\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f:fun requestVerification(    prompt: String,    ownerWindowHandle: Long = 0,): WindowsHelloVerification = memScoped {    val out = alloc&lt;WindowsHelloResult&gt;()    windows_hello_request_verification(        ownerWindowHandle.toULong(),        prompt.wcstr.ptr,        out.ptr,    )    WindowsHelloVerification(        result = verificationFromCode(out.code),        hresult = out.hresult,    )}JVM \u0438\u043b\u0438 \u043f\u043e\u0447\u0435\u043c\u0443 \u043c\u044b \u043d\u0435 \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Kotlin\/Native-\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443\u041f\u043e\u0447\u0442\u0438 \u0441\u0440\u0430\u0437\u0443 \u043f\u043e\u0441\u043b\u0435 Windows-\u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u0432\u043e\u043f\u0440\u043e\u0441:\u00a0\u0430 \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u0441 JVM?Kotlin\/Native \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 C-\u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0447\u0435\u0440\u0435\u0437\u00a0cinterop\u00a0\u0438 \u043b\u0438\u043d\u043a\u0443\u0435\u0442 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443:headers = windows_hello.hpackage = windowshellocompilerOpts = -DWINDOWS_HELLO_STATIC -Isrc\/nativeInterop\/windows-hello\/includestaticLibraries = libwindows_hello.alibraryPaths = build\/windows-hello-native\/bin\/Release build\/windows-hello-native\/binlinkerOpts = -lruntimeobject -luser32\u041d\u043e JVM \u043d\u0435 \u0443\u043c\u0435\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043f\u0430\u043a\u0435\u0442\u00a0windowshello\u00a0\u0438 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439\u00a0.a-\u0430\u0440\u0445\u0438\u0432.\u00a0\u0414\u043b\u044f \u043d\u0435\u0435 \u043d\u0443\u0436\u0435\u043d \u0434\u0440\u0443\u0433\u043e\u0439 \u043f\u0443\u0442\u044c:\u00a0\u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0438 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438.\u00a0\u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 C-\u0444\u0430\u0439\u043b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u0432 \u0434\u0432\u0430 \u0440\u0430\u0437\u043d\u044b\u0445 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430:\u041f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u044c\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u041a\u0430\u043a \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044fKotlin\/Native\u00a0mingwX64libwindows_hello.acinterop\u00a0\u0438 \u043b\u0438\u043d\u043a\u043e\u0432\u043a\u0430 native-\u0431\u0438\u043d\u0430\u0440\u043d\u0438\u043a\u0430JVMwindows_hello.dllJNA \u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0438\u0437 JVM-\u0440\u0435\u0441\u0443\u0440\u0441\u0430\u041d\u0430 JVM \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u00a0JNA.\u00a0\u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u043e\u0431\u044a\u044f\u0432\u0438\u043b \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430:private interface WindowsHelloLibrary : Library {    fun windows_hello_check_availability(        outResult: WindowsHelloResult,    ): Int    fun windows_hello_request_verification(        ownerWindowHandle: Long,        prompt: WString,        outResult: WindowsHelloResult,    ): Int}JVM-\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u044f \u043d\u0435 \u0441\u0442\u0430\u043b \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0432 \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438 \u0432\u0440\u0443\u0447\u043d\u0443\u044e.\u00a0Gradle \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442 DLL \u0432\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e build-\u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e,\u00a0\u0430 \u0437\u0430\u0442\u0435\u043c \u0437\u0430\u0434\u0430\u0447\u0430\u00a0syncWindowsHelloJvmNativeResource\u00a0\u043a\u043b\u0430\u0434\u0435\u0442 \u0435\u0435 \u0432 \u0440\u0435\u0441\u0443\u0440\u0441 native\/windows\/x86-64\/windows_hello.dll\u0412\u043e \u0432\u0440\u0435\u043c\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0438\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u0442\u0441\u044f \u0438\u0437 JAR \u0432\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0438 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 JNA:val resource = javaClass.getResourceAsStream(resourcePath)val libraryFile = Files.createTempFile(&#171;koncierge-windows-hello&#187;, &#171;.dll&#187;)resource.use { input -&gt;    libraryFile.outputStream().use { output -&gt;        input.copyTo(output)    }}Native.load(libraryFile.absolutePathString(), WindowsHelloLibrary::class.java)\u041f\u0440\u044f\u043c\u043e \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c DLL \u0438\u0437\u043d\u0443\u0442\u0440\u0438 JAR \u043d\u0435\u043b\u044c\u0437\u044f, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0437\u0434\u0435\u0441\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c.\u0418\u043c\u0435\u043d\u043d\u043e \u043d\u0430 \u044d\u0442\u043e\u043c \u043c\u0435\u0441\u0442\u0435 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u044f\u0432\u043d\u043e \u0441\u0432\u044f\u0437\u0430\u0442\u044c JVM-\u043c\u043e\u0434\u0443\u043b\u044c \u0441 native-\u0446\u0435\u043b\u044f\u043c\u0438 \u0438 \u0437\u0430\u0434\u0430\u0447\u0430\u043c\u0438 \u0441\u0431\u043e\u0440\u043a\u0438.\u00a0\u042d\u0442\u043e \u043d\u0435 \u043e\u0431\u044b\u0447\u043d\u0430\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c \u0432\u0438\u0434\u0430\u00a0implementation(project(&#8230;)).\u00a0JVM-\u0447\u0430\u0441\u0442\u0438 \u043d\u0443\u0436\u043d\u0430 \u043d\u0430\u0442\u0438\u0432\u043d\u0430\u044f DLL,\u00a0\u0430\u00a0mingwX64-\u0447\u0430\u0441\u0442\u0438\u00a0\u2014\u00a0\u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430.\u00a0\u0417\u043d\u0430\u0447\u0438\u0442,\u00a0Gradle-\u0433\u0440\u0430\u0444 \u0434\u043e\u043b\u0436\u0435\u043d \u0437\u043d\u0430\u0442\u044c \u043f\u0440\u043e \u043e\u0431\u0435 \u0432\u0435\u0442\u043a\u0438:jvmProcessResources    \u2514\u2500\u2500 syncWindowsHelloJvmNativeResource            \u2514\u2500\u2500 buildWindowsHelloJvmNative                    \u2514\u2500\u2500 compileWindowsHelloJvmNativecinteropWindowsHelloMingwX64    \u2514\u2500\u2500 buildWindowsHelloNative            \u2514\u2500\u2500 compileWindowsHelloNative\u041d\u0430 Windows \u044d\u0442\u043e \u0441\u0432\u044f\u0437\u044b\u0432\u0430\u043d\u0438\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e.\u00a0\u041d\u0430 macOS \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u0448\u0430\u0433:\u00a0\u043f\u0440\u0438 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0435 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0432\u043a\u043b\u044e\u0447\u0430\u0442\u044c\u00a0mingwX64\u00a0\u0432 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435,\u00a0\u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u0441\u0430\u043c Windows-\u0431\u0438\u043d\u0430\u0440\u043d\u0438\u043a \u043d\u0430 \u044d\u0442\u043e\u043c \u0430\u0433\u0435\u043d\u0442\u0435 \u043d\u0435 \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f.\u00a0\u0418\u043d\u0430\u0447\u0435 macOS-\u0430\u0433\u0435\u043d\u0442 \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0435 \u0437\u043d\u0430\u0435\u0442,\u00a0\u0447\u0442\u043e \u0432 \u0438\u0442\u043e\u0433\u043e\u0432\u043e\u0439 KMP-\u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0434\u043e\u043b\u0436\u0435\u043d \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c Windows target.\u041f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f: \u043f\u043e\u0447\u0435\u043c\u0443 \u043e\u0434\u043d\u043e\u0433\u043e build-\u0430\u0433\u0435\u043d\u0442\u0430 \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e\u041b\u043e\u043a\u0430\u043b\u044c\u043d\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u043d\u0443\u0436\u043d\u044b\u0439 target \u043d\u0430 \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0435\u0439 \u043c\u0430\u0448\u0438\u043d\u0435.\u00a0\u0412 CI \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f \u043c\u0435\u043d\u0435\u0435 \u0440\u043e\u043c\u0430\u043d\u0442\u0438\u0447\u043d\u0430\u044f:\u00a0\u0440\u0430\u0437\u043d\u044b\u0435 native targets \u0442\u0440\u0435\u0431\u0443\u044e\u0442 \u0440\u0430\u0437\u043d\u044b\u0435 host-\u0441\u0438\u0441\u0442\u0435\u043c\u044b.\u0412 \u043c\u043e\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 Windows-\u0430\u0433\u0435\u043d\u0442 \u0434\u043e\u043b\u0436\u0435\u043d \u0441\u043e\u0431\u0440\u0430\u0442\u044c:mingwX64-\u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044e;Windows Hello DLL \u0434\u043b\u044f JVM.\u0410 macOS-\u0430\u0433\u0435\u043d\u0442 \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442:macOS ARM64-\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u0434\u043b\u044f Touch ID;JVM- \u0438 Android-\u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438;\u043e\u0431\u0449\u0438\u0435 KMP-\u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435;\u0444\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u043d\u0430\u0431\u043e\u0440 \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0432 Maven Central.\u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u044f \u043f\u044b\u0442\u0430\u043b\u0441\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044c,\u00a0\u0447\u0442\u043e \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043e\u0434\u043d\u0438\u043c \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u043c Gradle-\u0432\u044b\u0437\u043e\u0432\u043e\u043c \u043d\u0430 \u043b\u044e\u0431\u043e\u043c \u0430\u0433\u0435\u043d\u0442\u0435.\u00a0\u041d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0432\u0441\u0435 libraries \u043d\u0430 \u043e\u0434\u043d\u043e\u043c build-\u0430\u0433\u0435\u043d\u0442\u0435:\u00a0Windows-\u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b \u0442\u0440\u0435\u0431\u0443\u044e\u0442 Windows,\u00a0\u0430 macOS-\u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b\u00a0\u2014\u00a0macOS.\u041f\u043e\u044d\u0442\u043e\u043c\u0443 workflow \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d \u043d\u0430 \u0434\u0432\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u0447\u0430\u0441\u0442\u0438.Windows job\u041d\u0430 Windows \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u0437\u0430\u0434\u0430\u0447\u0438::biometric:publishMingwX64PublicationToWindowsStagingRepository:biometric:syncWindowsHelloJvmNativeResource\u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e workflow \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442 \u0434\u0432\u0430 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u0430:\u043f\u043e\u0434\u043f\u0438\u0441\u0430\u043d\u043d\u0443\u044e mingwX64-\u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044e;windows_hello.dll \u0434\u043b\u044f JVM.\u0412\u0430\u0436\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442:\u00a0Windows job \u043d\u0435 \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0430\u0441\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u043f\u0440\u044f\u043c\u043e \u0432 Maven Central.\u00a0\u041e\u043d\u0430 \u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432 staging-\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442 \u0435\u0433\u043e \u0434\u0430\u043b\u044c\u0448\u0435.macOS jobmacOS-\u0430\u0433\u0435\u043d\u0442 \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u0435\u0442 \u043e\u0431\u0430 Windows-\u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u0430 \u0432 \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0435 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438:biometric\/build\/windows-maven-repositorybiometric\/build\/generated\/windows-hello-jvm\/resources\/native\/windows\/x86-64\u0417\u0430\u0442\u0435\u043c \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 targets \u0438 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0435\u0442 Windows-\u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044e \u0441 \u043e\u0431\u0449\u0438\u043c \u043d\u0430\u0431\u043e\u0440\u043e\u043c:    tasks.register&lt;Sync&gt;(&#171;assembleMavenCentralStagingRepository&#187;) {        group = &#171;publishing&#187;        description =&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-487309","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/487309","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=487309"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/487309\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=487309"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=487309"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=487309"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}