首页 > 解决方案 > Kotlin/Native Windows cinterop 使用内置库 dll

问题描述

我正在使用 Windows 来遵循这里的 Kotlin-Native libcurl 示例https://kotlinlang.org/docs/tutorials/native/curl.html

不幸的是,这是一个比我想象的更大的挑战。我一直在学习如何使用 CMake 等工具从源代码编译 Windows 上的 C 二进制文件,并按照本教程在 Windows 上构建 libcurl:https ://jonnyzzz.com/blog/2018/10/29/kn-libcurl-windows /

在对 Windows 上的 cinterop 的 .def 文件进行了几天的试验和错误之后,并使用 compilerOpts 指向我构建的库中的 curl 头文件,我遇到了障碍。

我似乎无法让 Gradle 识别 dll 文件。任务 ':linkDebugExecutableMingw' 一直失败。我不知道我应该把dll文件放在哪里。我已经尝试将它放入 exe 旁边的构建输出文件夹中,但它仍然无法编译,出现以下错误:

C:\Users\yous\.konan\dependencies\msys2-mingw-w64-x86_64-clang-llvm-lld-compiler_rt-8.0.1\bin\ld: C:\Users\yous\AppData\Local\Temp\konan_temp6326583690522756621\result.o:out:(.rdata$.refptr.knifunptr_sample35_curl_easy_strerror[.refptr.knifunptr_sample35_curl_easy_strerror]+0x0): undefined reference to `knifunptr_sample35_curl_easy_strerror'

和一个类似的头文件错误列表,那么最后的消息是:

e: C:\Users\yabde\.konan\dependencies\msys2-mingw-w64-x86_64-clang-llvm-lld-compiler_rt-8.0.1/bin/clang++ invocation reported errors

这是在我成功找到头文件之后。我相信这是不包含 dll 文件的问题。

这是我相关的 Gradle 构建脚本:

mingwX64("mingw") {
        compilations.main {
            cinterops {
                libcurl {
                    // Def-file describing the native API.
                    // The default path is src/nativeInterop/cinterop/<interop-name>.def
                    defFile project.file("src/nativeInterop/cinterop/libcurl.def")

                    // Package to place the Kotlin API generated.
                    packageName 'libcurl'

                    // Options to be passed to compiler by cinterop tool.
                    compilerOpts '-Isrc\\nativeInterop\\cinterop\\libcurl-vc-x64-release-dll-ipv6-sspi-winssl\\include -o libcurl'
                    //linkerOpts '-Isrc\\nativeInterop\\cinterop\\libcurl-vc-x64-release-dll-ipv6-sspi-winssl\\bin'

                    // Directories for header search (an analogue of the -I<path> compiler option).
                    //includeDirs.allHeaders("path1", "path2")

                    // Additional directories to search headers listed in the 'headerFilter' def-file option.
                    // -headerFilterAdditionalSearchPrefix command line option analogue.
                    includeDirs.headerFilterOnly("src/nativeInterop/cinterop/libcurl-vc-x86-release-dll-ipv6-sspi-winssl/include")

                    // A shortcut for includeDirs.allHeaders.
                    //includeDirs("include/directory", "another/directory")
                }
            }
        }
        binaries {
            executable {
                // Change to specify fully qualified name of your application's entry point:
                entryPoint = 'sample.main'
                // Specify command-line arguments, if necessary:
                //runTask?.args('-Lsrc/nativeInterop/cinterop/libcurl-vc-x86-release-dll-ipv6-sspi-winssl/bin')
                runTask?.args('')
            }
        }
    }

我相信这个问题可能与定位 dll 的链接器选项有关,但取消注释 linkerOpts 行没有帮助。

我想我已经放弃了 Kotlin/Native 并将坚持使用 C 进行面向数据的原生编程......

编辑: 另外,请注意,任何被注释掉的文本都是我尝试过的 ,所以,这是我的 def 文件:

headers = curl/curl.h
headerFilter = curl/*

compilerOpts.linux = -I/usr/include -I/usr/include/x86_64-linux-gnu

linkerOpts.osx = -L/opt/local/lib -L/usr/local/opt/curl/lib -lcurl
linkerOpts.linux = -L/usr/lib/x86_64-linux-gnu -lcurl
linkerOpts.mingw = -Llibcurl-vc-x86-release-dll-ipv6-sspi-winssl/lib

好的,这是我的项目结构:

结构体

标签: cgradlekotlindllkotlin-native

解决方案


在寻找将 libcurl 与我的二进制文件静态链接的解决方案时,我多次经历了这个问题。

最后,我最终在 Windows 上使用 WinInet 进行 HTTP 通信。Linux 和 macOS 二进制文件仍然依赖于带有 libcurl 的 ktor 客户端。

请参阅我如何将 WinInet API 与 Kotlin MPP 一起使用的示例:https ://github.com/localazy/kotlin-mpp-wininet

对于简单的 HTTP 通信,WinInet API 已经足够好了,并且生成的二进制文件要小得多,在我的例子中,它没有额外的依赖项。


推荐阅读