Kotlin C interop (LowLevelKeyboardProc callback function)


#1

An error occurred while calling the LowLevelKeyboardProc function.
Announced in the ‘.h’ file, created ‘.klib’ with the help of ‘cinterop’. But there is an error.

LRESULT CALLBACK LowLevelKeyboardProc(
In int nCode,
In WPARAM wParam,
In LPARAM lParam
);

main.kt:15:46: error: no value passed for parameter ‘nCode’
hhk = SetWindowsHookExA(WH_KEYBOARD_LL, (LowLevelKeyboardProc { nCode, wParam, info -> println(info.vkCode)}), hMod, 0)
^
main.kt:15:46: error: no value passed for parameter ‘wParam’
hhk = SetWindowsHookExA(WH_KEYBOARD_LL, (LowLevelKeyboardProc { nCode, wParam, info -> println(info.vkCode)}), hMod, 0)
^
main.kt:15:46: error: type mismatch: inferred type is LRESULT /* = Long / but HOOKPROC? / = CPointer<CFunction<(Int, WPARAM /* = ULong /, LPARAM / = Long /) -> LRESULT / = Long />>? / was expected
hhk = SetWindowsHookExA(WH_KEYBOARD_LL, (LowLevelKeyboardProc { nCode, wParam, info -> println(info.vkCode)}), hMod, 0)
^
main.kt:15:67: error: type mismatch: inferred type is (???, ???, ???) -> Unit but LPARAM /
= Long / was expected
hhk = SetWindowsHookExA(WH_KEYBOARD_LL, (LowLevelKeyboardProc { nCode, wParam, info -> println(info.vkCode)}), hMod, 0)
^
main.kt:15:69: error: cannot infer a type for this parameter. Please specify it explicitly.
hhk = SetWindowsHookExA(WH_KEYBOARD_LL, (LowLevelKeyboardProc { nCode, wParam, info -> println(info.vkCode)}), hMod, 0)
^
main.kt:15:76: error: cannot infer a type for this parameter. Please specify it explicitly.
hhk = SetWindowsHookExA(WH_KEYBOARD_LL, (LowLevelKeyboardProc { nCode, wParam, info -> println(info.vkCode)}), hMod, 0)
^
main.kt:15:84: error: cannot infer a type for this parameter. Please specify it explicitly.
hhk = SetWindowsHookExA(WH_KEYBOARD_LL, (LowLevelKeyboardProc { nCode, wParam, info -> println(info.vkCode)}), hMod, 0)
^
main.kt:15:116: error: type mismatch: inferred type is CPointer<CFunction<(LPCWSTR? /
= CPointer<WCHARVar /
= UShortVarOf<WCHAR /* = UShort */> */>? /) -> HMODULE? / = CPointer<HINSTANCE__>? />>? but HINSTANCE? / = CPointer<HINSTANCE__>? */ was expected
hhk = SetWindowsHookExA(WH_KEYBOARD_LL, (LowLevelKeyboardProc { nCode, wParam, info -> println(info.vkCode)}), hMod, 0)


#2

Use staticCFunction instead of LowLevelKeyboardProc


#3

SetWindowsHookExA(WH_KEYBOARD_LL, staticCFunction( { nCode, wParam, info -> println(info.vkCode) }), hMod, 0)
main.kt:16:87: error: type mismatch: inferred type is Unit but LRESULT /* = Long / was expected
hhk = SetWindowsHookExA(WH_KEYBOARD_LL, staticCFunction( { nCode, wParam, info -> println(info.vkCode) }), hMod, 0)
^
main.kt:16:100: error: unresolved reference: vkCode
hhk = SetWindowsHookExA(WH_KEYBOARD_LL, staticCFunction( { nCode, wParam, info -> println(info.vkCode) }), hMod, 0)
^
main.kt:16:112: error: type mismatch: inferred type is CPointer<CFunction<(LPCWSTR? /
= CPointer<WCHARVar /* = UShortVarOf<WCHAR /* = UShort */> */>? /) -> HMODULE? / = CPointer<HINSTANCE__>? />>? but HINSTANCE? / = CPointer<HINSTANCE__>? */ was expected
hhk = SetWindowsHookExA(WH_KEYBOARD_LL, staticCFunction( { nCode, wParam, info -> println(info.vkCode) }), hMod, 0)
^


#4

Well, let’s simplify first.
Does SetWindowsHookExA(WH_KEYBOARD_LL, staticCFunction { nCode, wParam, info -> 0 }, hMod, 0) work?


#5

Does not work.

main.kt:22:91: error: type mismatch: inferred type is CPointer<CFunction<(LPCWSTR? /* = CPointer<WCHARVar /* = UShortVarOf<WCHAR /* = UShort */> />? /) -> HMODULE? / = CPointer<HINSTANCE__>? />>? but HINSTANCE? / = CPointer<HINSTANCE__>? / was expected
hhk = SetWindowsHookExA(WH_KEYBOARD_LL, staticCFunction { nCode, wParam, info -> 0 }, hMod, 0, hMod, 0)
^
main.kt:22:100: error: too many arguments for public fun SetWindowsHookExA(idHook: Int, lpfn: HOOKPROC? /
= CPointer<CFunction<(Int, WPARAM /
= ULong /, LPARAM / = Long /) -> LRESULT / = Long />>? /, hmod: HINSTANCE? / = CPointer<HINSTANCE__>? /, dwThreadId: DWORD / = UInt /): HHOOK? / = CPointer<HHOOK__>? / defined in user32
hhk = SetWindowsHookExA(WH_KEYBOARD_LL, staticCFunction { nCode, wParam, info -> 0 }, hMod, 0, hMod, 0)
^
main.kt:22:106: error: too many arguments for public fun SetWindowsHookExA(idHook: Int, lpfn: HOOKPROC? /
= CPointer<CFunction<(Int, WPARAM /
= ULong /, LPARAM / = Long /) -> LRESULT / = Long */>>? /, hmod: HINSTANCE? / = CPointer<HINSTANCE__>? /, dwThreadId: DWORD / = UInt /): HHOOK? / = CPointer<HHOOK__>? */ defined in user32
hhk = SetWindowsHookExA(WH_KEYBOARD_LL, staticCFunction { nCode, wParam, info -> 0 }, hMod, 0, hMod, 0)

Here is the taco advertised “user32.h”:
#include <Windows.h>
#include <winuser.h>
#include <psapi.h>
#include <processthreadsapi.h>
LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);

In a zip file I try to connect a kernel32 (HERE, there is a question how to pass a pointer to a variable to the function “GetWindowThreadProcessId” to transfer “pid” to the function) and user32. If it is not clear, I will clean it for better readability.ShitMyCinterop.7z (907.1 KB)


#6

Так а зачем hMod, 0, hMod, 0 два раза то?


#7

Stupid mistake.
Yes, staticCFunction helped, now the error goes further
main.kt:22:91: error: type mismatch: inferred type is CPointer<CFunction<(LPCWSTR? /* = CPointer<WCHARVar /* = UShortVarOf<WCHAR /* = UShort */> */>? /) -> HMODULE? / = CPointer<HINSTANCE__>? />>? but HINSTANCE? / = CPointer<HINSTANCE__>? */ was expected
hhk = SetWindowsHookExA(WH_KEYBOARD_LL, staticCFunction { nCode, wParam, info -> 0 }, hMod, 0)


#8

On the Kotlin JVM I used:
import com.sun.jna.platform.win32.Kernel32
val hMod = Kernel32.INSTANCE.GetModuleHandle(null)
It’s equal?
import platform.windows.GetModuleHandle
val hMod = GetModuleHandle


#9

Guess it should be val hMod = GetModuleHandle(null)


#10

He will swear at the null value


#11

error: only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type CPointer<CFunction<(LPCWSTR? /* = CPointer<WCHARVar /* = UShortVarOf<WCHAR /* = UShort */> */>? /) -> HMODULE? / = CPointer<HINSTANCE__>? */>>?


#12

JNA type is specified hMod:WinDef.HMODULE! = GetModuleHandle(null)


#13

I tried this, but this is also not a solution: val hMod:HMODULE? = GetModuleHandle(null)

main.kt:26:26: error: only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type CPointer<CFunction<(LPCWSTR? /* = CPointer<WCHARVar /* = UShortVarOf<WCHAR /* = UShort */> */>? /) -> HMODULE? / = CPointer<HINSTANCE__>? */>>?


#14

Did you really read INTEROP.md?

import kotlinx.cinterop.*
import platform.windows.*

val hMod = GetModuleHandleA(null)
val hhk = SetWindowsHookExA(WH_KEYBOARD_LL, staticCFunction(::keyHandler), hMod, 0)

fun keyHandler(nCode: Int, wParam: WPARAM, lParam: LPARAM): LRESULT {
    val info = lParam.toCPointer<KBDLLHOOKSTRUCT>()!!.pointed
    println(info.vkCode)
    return CallNextHookEx(hhk, nCode, wParam, lParam)
}

#15

Yes, I actually read, but through google translate - it makes it very hard to understand.
Are you on the K / N development team?


#16

Are you on the K / N development team?

No, just “advanced user”.


#17

I correctly create a pointer?

DWORD GetWindowThreadProcessId(
HWND hWnd,
LPDWORD pid
);
var pid:LPDWORD
GetWindowThreadProcessId(“hWnd”, pid.toCPointer()!!.pointed){
}


#18
memScoped {
    val hwnd: HWND? = TODO()
    val buf = alloc<UIntVar>()
    val tid = GetWindowThreadProcessId(hwnd, buf.ptr)
    val pid = buf.value
}

#19

Allocates memory for a variable: alloc()

Нужно ли освобождать память или после
выхода из блока память сама освободится?

Получает указатель buf.ptr

“.value” это относится к ptr, какие ещё есть значения?


#20

Освободится по выходу из memScoped
buf.ptr когда нужно передать указатель
buf.value читает из сишного UIntVar в простой котлиновский UInt