Когда я пытался создать контекст OpenGL с помощью Windows API и Kotlin, произошла ошибка при выполнении задачи связывания. Я разместил вывод этой задачи на pastebin (срок действия истекает через месяц), и эти две строки вывода выделяются:
... undefined ссылка на __imp_wglCreateContext '
... неопределенная ссылка на '__imp_wglMakeCurrent'
Для каждой функции wgl , которую я использую, clang (фронтенд компилятора LLVM) печатает такие строки. Компиляция работает нормально, но когда дело доходит до компоновки, задача либо не выполняется (Kotlin 1.3.71), либо никогда не заканчивается ни с чем (Kotlin 1.4-M1).
Обратите внимание, что это не проблема времени выполнения и любая другая функция API Windows работает правильно, а также то, что 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 для работы. Но любая другая функция OpenGL из пакета platform.opengl32
работает, и поскольку Kotlin проверяет при компиляции, какие библиотеки используются и включает их автоматически, все должно работать нормально. Однако clang все равно это не понравилось, и он не смог найти реализации функций wgl.
Затем я искал в inte rnet какие-либо решения, и несколько человек получили такой же вывод, но их случаи не были полностью похожи на мои, и я не нашел никого, кто бы вообще пытался создать контекст OpenGL с Kotlin (я знаю, что это может быть не лучший выбор для использования языка высокого уровня для чего-то подобного, и что я мог бы использовать другую библиотеку для того, что я пытаюсь выполнить sh, но я хочу посмотреть, на что способен Kotlin).
Далее я проверил, имеет ли средство отслеживания проблем Kotlin что-то об этом уже (нет) и версия LLVM Kotlin использует и журналы изменений LLVM, если они что-то говорят об этом (нет, и я знаю, что это не имеет особого смысла, но вы никогда не знаете), поэтому я решил, что проблема должна быть на моей стороне.
Я нашел следующие возможные причины:
- Я использую неправильную версию OpenGL (должна быть последней для моей графики s карта, я обновил свой графический драйвер)
- Мне нужно сделать что-то дополнительно с зависимостями
- Я использую устаревший API
- Я слишком тупой
- Мне не повезло, и это просто не работает на моем P C
Это все, что я еще не проверял, потому что я не мог, поэтому, конечно, я не не знаю, правда ли это. Я пытался заставить это работать в течение пары дней, так что теперь я обращаюсь за помощью или советом. Может быть, кто-то может попытаться скомпилировать это тоже. Следующий скрипт является необходимым скриптом сборки для 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
и поместите файл * .kt в папку kotlin с первым показанным кодом. Затем запустите задачу: runReleaseExecutableOpenGLErrorDemo и посмотрите, скомпилируется ли она и скомпонована ли она, затем попробуйте комментировать вызовы функции wgl и запустить ее снова. Это было построено с использованием последних версий IntelliJ и Gradle.
Конечно, если кто-то знает, в чем проблема, дайте мне знать или прокомментируйте, если вам нужна дополнительная информация. И, пожалуйста, также скажите мне, каков был результат компиляции вышеуказанного кода.
Заранее спасибо!