Improve Windows interop (#2022)

This commit is contained in:
Nikolay Igotti
2018-09-07 18:55:20 +03:00
committed by GitHub
parent f5da2ae345
commit d42b717320
5 changed files with 32 additions and 9 deletions
@@ -375,16 +375,16 @@ fun List<String>.toCStringArray(autofreeScope: AutofreeScope): CPointer<CPointer
fun Array<String>.toCStringArray(autofreeScope: AutofreeScope): CPointer<CPointerVar<ByteVar>> =
autofreeScope.allocArrayOf(this.map { it.cstr.getPointer(autofreeScope) })
val String.wcstr: CValues<ShortVar>
val String.wcstr: CValues<UShortVar>
get() {
val chars = CharArray(this.length, { i -> this.get(i)})
return object : CValues<ShortVar>() {
return object : CValues<UShortVar>() {
override val size get() = 2 * (chars.size + 1)
override fun getPointer(scope: AutofreeScope): CPointer<ShortVar> {
val result = scope.allocArray<ShortVar>(chars.size + 1)
override fun getPointer(scope: AutofreeScope): CPointer<UShortVar> {
val result = scope.allocArray<UShortVar>(chars.size + 1)
nativeMemUtils.putCharArray(chars, result.pointed, chars.size)
result[chars.size] = 0.toShort()
result[chars.size] = 0u
return result
}
}
@@ -129,6 +129,21 @@ fun CPointer<ShortVar>.toKString(): String {
return String(bytes)
}
fun CPointer<UShortVar>.toKString(): String {
val nativeBytes = this
var length = 0
while (nativeBytes[length] != 0.toUShort()) {
++length
}
val bytes = CharArray(length)
var index = 0
while (index < length) {
bytes[index] = nativeBytes[index].toShort().toChar()
++index
}
return String(bytes)
}
@SymbolName("Kotlin_interop_malloc")
private external fun malloc(size: Long, align: Int): NativePtr
@@ -323,7 +323,8 @@ class StubGenerator(
}
// We take this approach as generic 'const short*' shall not be used as String.
fun representCFunctionParameterAsWString(type: Type)= type.isAliasOf(platformWStringTypes)
fun representCFunctionParameterAsWString(function: FunctionDecl, type: Type) = type.isAliasOf(platformWStringTypes)
&& !noStringConversion.contains(function.name)
private fun getArrayLength(type: ArrayType): Long {
val unwrappedElementType = type.elemType.unwrapTypedefs()
@@ -629,7 +630,7 @@ class StubGenerator(
kotlinParameters.add(parameterName to KotlinTypes.string.makeNullable())
bodyGenerator.pushMemScoped()
"$parameterName?.cstr?.getPointer(memScope)"
} else if (representCFunctionParameterAsWString(parameter.type)) {
} else if (representCFunctionParameterAsWString(func, parameter.type)) {
kotlinParameters.add(parameterName to KotlinTypes.string.makeNullable())
bodyGenerator.pushMemScoped()
"$parameterName?.wcstr?.getPointer(memScope)"
+1 -1
View File
@@ -4,5 +4,5 @@ headers = wtypes.h minwindef.h windows.h commctrl.h dwmapi.h shlobj.h shlwapi.h
compilerOpts = -DUNICODE -DWINVER=0x0601 -D_WIN32_WINNT=0x0601 -DWINAPI_FAMILY=3 -DOEMRESOURCE \
-Wno-incompatible-pointer-types -Wno-deprecated-declarations
linkerOpts = -lcomctl32 -lcrypt32 -lshlwapi -lshell32 -limm32 -lusp10 -lwininet -lgdi32 -luser32 -lkernel32
noStringConversion = LoadCursorA LoadBitmapA
noStringConversion = LoadCursorA LoadBitmapA LoadIconA LoadImageA LoadCursorW LoadBitmapW LoadIconW LoadImageW
depends = posix
+8 -1
View File
@@ -2,6 +2,13 @@ import kotlinx.cinterop.*
import platform.windows.*
fun main(args: Array<String>) {
MessageBoxW(null, "Konan говорит:\nЗДРАВСТВУЙ МИР!\n",
val message = StringBuilder()
memScoped {
val buffer = allocArray<UShortVar>(MAX_PATH)
GetModuleFileNameW(null, buffer, MAX_PATH)
val path = buffer.toKString().split("\\").dropLast(1).joinToString("\\")
message.append("Я нахожусь в $path\n")
}
MessageBoxW(null, "Konan говорит:\nЗДРАВСТВУЙ МИР!\n$message",
"Заголовок окна", (MB_YESNOCANCEL or MB_ICONQUESTION).convert())
}