Support for wchar, minor opts in interop runtime (#641)

This commit is contained in:
Nikolay Igotti
2017-06-07 14:23:35 +03:00
committed by GitHub
parent 242e1da191
commit 2d6d4b15e6
7 changed files with 107 additions and 10 deletions
@@ -76,6 +76,18 @@ object nativeMemUtils {
unsafe.copyMemory(source, baseOffset, null, dest.address, length.toLong())
}
fun getCharArray(source: NativePointed, dest: CharArray, length: Int) {
val clazz = CharArray::class.java
val baseOffset = unsafe.arrayBaseOffset(clazz).toLong();
unsafe.copyMemory(null, source.address, dest, baseOffset, length.toLong() * 2)
}
fun putCharArray(source: CharArray, dest: NativePointed, length: Int) {
val clazz = CharArray::class.java
val baseOffset = unsafe.arrayBaseOffset(clazz).toLong();
unsafe.copyMemory(source, baseOffset, null, dest.address, length.toLong() * 2)
}
fun zeroMemory(dest: NativePointed, length: Int): Unit = unsafe.setMemory(dest.address, length.toLong(), 0)
internal class NativeAllocated(override val rawPtr: NativePtr) : NativePointed
@@ -147,10 +147,11 @@ inline fun <reified T : CPointer<*>>
NativePlacement.allocArrayOf(elements: List<T?>): CArrayPointer<CPointerVarOf<T>> {
val res = allocArray<CPointerVarOf<T>>(elements.size)
elements.forEachIndexed { index, value ->
res[index] = value
var index = 0
while (index < elements.size) {
res[index] = elements[index]
++index
}
return res
}
@@ -163,8 +164,9 @@ fun NativePlacement.allocArrayOf(elements: ByteArray): CArrayPointer<ByteVar> {
fun NativePlacement.allocArrayOf(vararg elements: Float): CArrayPointer<FloatVar> {
val res = allocArray<FloatVar>(elements.size)
var index = 0
for (element in elements) {
res[index++] = element
while (index < elements.size) {
res[index] = elements[index]
++index
}
return res
}
@@ -287,8 +289,6 @@ fun <T : CPointed> Array<CPointer<T>?>.toCValues() = cValuesOf(*this)
fun <T : CPointed> List<CPointer<T>?>.toCValues() = this.toTypedArray().toCValues()
/**
* TODO: should the name of the function reflect the encoding?
*
* @return the value of zero-terminated UTF-8-encoded C string constructed from given [kotlin.String].
*/
val String.cstr: CValues<ByteVar>
@@ -307,6 +307,21 @@ val String.cstr: CValues<ByteVar>
}
}
val String.wcstr: CValues<ShortVar>
get() {
val chars = CharArray(this.length, { i -> this.get(i)})
return object : CValues<ShortVar>() {
override val size get() = chars.size + 1
override fun getPointer(placement: NativePlacement): CPointer<ShortVar> {
val result = placement.allocArray<ShortVar>(chars.size + 1)
nativeMemUtils.putCharArray(chars, result.pointed, chars.size)
result[chars.size] = 0.toShort()
return result
}
}
}
/**
* TODO: should the name of the function reflect the encoding?
*
@@ -33,24 +33,50 @@ object nativeMemUtils {
// TODO: optimize
fun getByteArray(source: NativePointed, dest: ByteArray, length: Int) {
val sourceArray = source.reinterpret<ByteVar>().ptr
for (index in 0 .. length - 1) {
var index = 0
while (index < length) {
dest[index] = sourceArray[index]
++index
}
}
// TODO: optimize
fun putByteArray(source: ByteArray, dest: NativePointed, length: Int) {
val destArray = dest.reinterpret<ByteVar>().ptr
for (index in 0 .. length - 1) {
var index = 0
while (index < length) {
destArray[index] = source[index]
++index
}
}
// TODO: optimize
fun getCharArray(source: NativePointed, dest: CharArray, length: Int) {
val sourceArray = source.reinterpret<ShortVar>().ptr
var index = 0
while (index < length) {
dest[index] = sourceArray[index].toChar()
++index
}
}
// TODO: optimize
fun putCharArray(source: CharArray, dest: NativePointed, length: Int) {
val destArray = dest.reinterpret<ShortVar>().ptr
var index = 0
while (index < length) {
destArray[index] = source[index].toShort()
++index
}
}
// TODO: optimize
fun zeroMemory(dest: NativePointed, length: Int): Unit {
val destArray = dest.reinterpret<ByteVar>().ptr
for (index in 0 .. length - 1) {
var index = 0
while (index < length) {
destArray[index] = 0
++index
}
}
@@ -60,6 +60,8 @@ class StubGenerator(
"true", "try", "typealias", "val", "var", "when", "while"
)
val platformWStringTypes = setOf("LPCWSTR")
/**
* For this identifier constructs the string to be parsed by Kotlin as `SimpleName`
* defined [here](https://kotlinlang.org/docs/reference/grammar.html#SimpleName).
@@ -516,12 +518,24 @@ class StubGenerator(
return pointeeType
}
private fun Type.isAliasOf(names: Set<String>): Boolean {
var type = this
while (type is Typedef) {
if (names.contains(type.def.name)) return true
type = type.def.aliased
}
return false
}
fun representCFunctionParameterAsString(type: Type): Boolean {
val unwrappedType = type.unwrapTypedefs()
return unwrappedType is PointerType && unwrappedType.pointeeIsConst &&
unwrappedType.pointeeType.unwrapTypedefs() == CharType
}
// We take this approach as generic 'const short*' shall not be used as String.
fun representCFunctionParameterAsWString(type: Type)= type.isAliasOf(platformWStringTypes)
fun getCFunctionParamBinding(type: Type): OutValueBinding {
if (representCFunctionParameterAsString(type)) {
return OutValueBinding(
@@ -532,6 +546,15 @@ class StubGenerator(
)
}
if (representCFunctionParameterAsWString(type)) {
return OutValueBinding(
kotlinType = "String?", // TODO: mention the C type (e.g. with annotation).
kotlinConv = { name -> "$name?.wcstr?.getPointer(memScope).rawValue" },
memScoped = true,
kotlinJniBridgeType = "NativePtr"
)
}
representCFunctionParameterAsValuesRef(type)?.let {
val pointeeMirror = mirror(it)
return OutValueBinding(
+6
View File
@@ -0,0 +1,6 @@
import win32.*
fun main(args: Array<String>) {
MessageBoxW(null, "Konan говорит:\nЗДРАВСТВУЙ МИР!\n",
"Заголовок окна", MB_YESNOCANCEL or MB_ICONQUESTION)
}
+12
View File
@@ -0,0 +1,12 @@
@echo off
setlocal
set DIR=.
set "PATH=..\..\dist\bin;..\..\bin;%PATH%"
if "%TARGET%" == "" set TARGET=mingw
set "LFLAGS=-Wl,--subsystem,windows"
call cinterop -def "%DIR%\win32.def" -target "%TARGET%" -o win32 || exit /b
call konanc -target "%TARGET%" "%DIR%\MessageBox.kt" -library win32 -linkerOpts "%LFLAGS%" -opt -o MessageBox || exit /b
copy MessageBox.kexe MessageBox.exe
+3
View File
@@ -0,0 +1,3 @@
headers = windows.h
headerFilter = win**.h
compilerOpts = -DUNICODE -Wno-incompatible-pointer-types -Wno-deprecated-declarations