windows - 链接失败,未定义对 Kotlin 中用于 OpenGL 的 Windows API 的 wgl 函数的引用
问题描述
当我尝试使用 Windows API 和 Kotlin 创建 OpenGL 上下文时,执行链接任务时发生错误。我在 pastebin 上发布了该任务的输出(一个月后到期),输出的这两行很突出:
...未定义对“__imp_wglCreateContext”的引用
...未定义的对“__imp_wglMakeCurrent”的引用
对于我使用的每个wgl 函数,clang(LLVM 编译器前端)都会打印出这样的行。编译工作正常,但在链接方面,任务要么失败(Kotlin 1.3.71),要么永远不会以任何事情结束(Kotlin 1.4-M1)。
请注意,这不是运行时问题,任何其他 Windows API 函数都可以正常工作,而且 Kotlin 还为 wgl 函数提供了绑定。
如果所有 wgl 函数都被删除,我制作的以下代码可以正常编译和链接,并且会按预期生成一个空白窗口(注释掉 wgl 函数):
import kotlinx.cinterop.*
import platform.windows.*
@OptIn(ExperimentalUnsignedTypes::class)
fun main() {
memScoped {
val className = "OpenGLLinkErrorDemo"
// create an instance of the window class
val wc = cValue<WNDCLASS> {
lpfnWndProc = staticCFunction { hwnd, uMsg, wParam, lParam ->
when (uMsg) {
WM_DESTROY.toUInt() -> {
PostQuitMessage(0)
0
}
WM_PAINT.toUInt() -> {
memScoped {
val ps = alloc<PAINTSTRUCT>()
val hdc = BeginPaint(hwnd, ps.ptr)
val brush = alloc<HBRUSH__> {
unused = COLOR_WINDOW + 1
}
FillRect(hdc, ps.rcPaint.ptr, brush.ptr)
EndPaint(hwnd, ps.ptr)
}
0
}
else -> DefWindowProc!!(hwnd, uMsg, wParam, lParam)
}
}
hInstance = GetModuleHandle!!(null)
lpszClassName = className.wcstr.ptr
}
// register the window class instance
RegisterClass!!(wc.ptr)
val hwnd = CreateWindowEx!!(
0u, // optional window styles
className.wcstr.ptr, // window class
className.wcstr.ptr, // window text
CS_OWNDC.toUInt(), // window style (this one in particular is needed for OpenGL)
// size and position
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
null, // parent window
null, // menu
GetModuleHandle!!(null), // instance handle
null // additional application data
)
?: throw RuntimeException("Failed to create window")
// create a pixelformat descriptor with opengl compatible settings
val pfd = alloc<PIXELFORMATDESCRIPTOR> {
nSize = sizeOf<PIXELFORMATDESCRIPTOR>().toUShort()
nVersion = 1u
dwFlags = (PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER).toUInt()
iPixelType = PFD_TYPE_RGBA.toUByte()
cColorBits = 32u
cRedBits = 0u; cRedShift = 0u; cGreenBits = 0u; cGreenShift = 0u; cBlueBits = 0u; cBlueShift = 0u; cAlphaBits = 0u; cAlphaShift = 0u
cAccumBits = 0u
cAccumRedBits = 0u; cAccumGreenBits = 0u; cAccumBlueBits = 0u; cAccumAlphaBits = 0u
cDepthBits = 24u
cStencilBits = 8u
cAuxBuffers = 0u
iLayerType = PFD_MAIN_PLANE.toUByte()
bReserved = 0u
dwLayerMask = 0u; dwVisibleMask = 0u; dwDamageMask = 0u
}
SetPixelFormat(GetDC(hwnd), ChoosePixelFormat(GetDC(hwnd), pfd.ptr), pfd.ptr)
// the source of evil. using the function to create an opengl context, but the linker doesn't know the wgl functions
val openGLContext = wglCreateContext(GetDC(hwnd)) ?: throw RuntimeException("Failed to create OpenGL context")
wglMakeCurrent(GetDC(hwnd), openGLContext)
ShowWindow(hwnd, 1)
// run the message loop
val msg = alloc<MSG>()
while (GetMessage!!(msg.ptr, null, 0u, 0u) == 1) {
TranslateMessage(msg.ptr)
DispatchMessage!!(msg.ptr)
}
}
}
所以我检查了文档,当然这需要 OpenGL 库才能工作。但是platform.opengl32
包中的任何其他 OpenGL 函数都可以工作,并且因为 Kotlin 在编译时会检查使用了哪些库并自动包含它们,所以一切都应该正常工作。但是,clang 仍然不喜欢它,并且找不到 wgl 函数的实现。
然后我在互联网上搜索了任何解决方案,有几个人有相同的输出,但他们的情况与我的情况并不完全一样,我根本没有找到任何人尝试使用 Kotlin 创建 OpenGL 上下文(我知道可能不会是使用高级语言来完成这样的事情的最佳选择,我可以使用另一个库来完成我想要完成的事情,但我想看看 Kotlin 能做多少)。
接下来,我检查了 Kotlin 问题跟踪器是否已经有相关信息(不),以及 Kotlin 使用的 LLVM 版本和 LLVM 变更日志,如果他们对此有任何说明(不,我知道这没有多大意义,但你永远不知道),所以我认为问题一定在我这边。
我想出了以下可能的原因:
- 我使用了错误版本的 OpenGL(应该是我的显卡的最新版本,我更新了我的显卡驱动程序)
- 我需要对依赖项做一些额外的事情
- 我正在使用已弃用的 API
- 我太笨了
- 我运气不好,它在我的电脑上不起作用
这些都是我还没有检查的东西,因为我不能,所以我当然不知道它们是否属实。几天来我一直试图让它工作,所以现在我寻求帮助或建议。也许有人也可以尝试编译它。以下脚本是 gradle 的必要构建脚本:
@file:Suppress("UNUSED_VARIABLE")
plugins {
kotlin("multiplatform") version "1.3.71"
}
repositories {
mavenCentral()
}
kotlin {
mingwX64("openGLErrorDemo") {
binaries {
executable {
entryPoint = "main"
}
}
val main by compilations.getting {
kotlinOptions {
freeCompilerArgs = listOf("-Xopt-in=kotlin.RequiresOptIn")
}
}
}
sourceSets {
val commonMain by getting {
dependencies {
implementation(kotlin("stdlib-common"))
}
}
}
}
将该脚本放入名为 build.gradle.kts 的文件中,然后在其旁边创建以下文件夹结构:
src
\- openGLErrorDemoMain
\- kotlin
并在 kotlin 文件夹中放置一个 *.kt 文件,并显示第一个代码。然后运行 :runReleaseExecutableOpenGLErrorDemo 任务并查看它是否编译和链接,然后尝试注释 wgl 函数调用并再次运行它。这是使用最新版本的 IntelliJ 和 Gradle 构建的。
当然,如果有人知道问题出在哪里,请告诉我,或者如果您需要更多信息,请发表评论。还请告诉我编译上述代码的结果是什么。
提前致谢!
解决方案
推荐阅读
- python - IDLE 控制台中 Flask 应用程序的导入错误
- typescript - 扩大 TypeScript 中的 const 文字类型
- python - 删除出现在整个数据框中的特定值
- neo4j - 是否可以在 Cypher 中“重复”不止一跳的模式?
- android - 在 Android 中从 File Api 迁移到 Storage Access Framework (SAF)
- sql - 使用 SQL Alchemy 会话注册用户定义函数
- reactjs - 音频到 blob 和 POST 到 cloudinary 问题
- django - 如何在 django 中限制对媒体图像 URL 的访问
- jquery - 画布元素在 WordPress 中不起作用
- swift - 如何快速生成不重叠的随机按钮