diff --git a/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/Varargs.kt b/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/Varargs.kt index 6a9cdbf1641..20d50b041e3 100644 --- a/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/Varargs.kt +++ b/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/Varargs.kt @@ -40,7 +40,15 @@ private tailrec fun convertArgument( } is String -> { - location.reinterpret>()[0] = argument.cstr.getPointer(additionalPlacement) + location.reinterpret>()[0] = if (!isVariadic) { + // If it is fixed argument, then it is not C string because it must have been already converted; + // then treat it as NSString. + // TODO: handle fixed NSString arguments in the stub instead. + interpretCPointer(CreateNSStringFromKString(argument)) + } else { + // It is passed as variadic argument; no type information available, so treat it as C string. + argument.cstr.getPointer(additionalPlacement) + } FFI_TYPE_KIND_POINTER } diff --git a/backend.native/tests/build.gradle b/backend.native/tests/build.gradle index 9358fe3bd6d..bea36c4942a 100644 --- a/backend.native/tests/build.gradle +++ b/backend.native/tests/build.gradle @@ -2332,6 +2332,7 @@ if (isMac()) { goldValue = "84\nFoo\nHello, World!\nKotlin says: Hello, everybody!\nHello from Kotlin\n2, 1\n" + "true\ntrue\n" + "Global string\nAnother global string\nnull\nglobal object\n" + + "5\n" + "Deallocated\nDeallocated\n" source = "interop/objc/smoke.kt" diff --git a/backend.native/tests/interop/objc/smoke.h b/backend.native/tests/interop/objc/smoke.h index ef0ca056a9d..a9818eefa9c 100644 --- a/backend.native/tests/interop/objc/smoke.h +++ b/backend.native/tests/interop/objc/smoke.h @@ -55,3 +55,5 @@ Class (^ _Nonnull getClassGetter(NSObject* obj))(void); extern NSString* globalString; extern NSObject* globalObject; + +int formatStringLength(NSString* format, ...); diff --git a/backend.native/tests/interop/objc/smoke.kt b/backend.native/tests/interop/objc/smoke.kt index e57b1aa69ce..4689922d0fa 100644 --- a/backend.native/tests/interop/objc/smoke.kt +++ b/backend.native/tests/interop/objc/smoke.kt @@ -60,6 +60,8 @@ fun run() { override fun description() = "global object" } println(globalObject) + + println(formatStringLength("%d %d", 42, 17)) } fun MutablePairProtocol.swap() { diff --git a/backend.native/tests/interop/objc/smoke.m b/backend.native/tests/interop/objc/smoke.m index 1d3b8aa0191..276fd513165 100644 --- a/backend.native/tests/interop/objc/smoke.m +++ b/backend.native/tests/interop/objc/smoke.m @@ -60,3 +60,11 @@ Class (^ _Nonnull getClassGetter(NSObject* obj))() { NSString* globalString = @"Global string"; NSObject* globalObject = nil; + +int formatStringLength(NSString* format, ...) { + va_list args; + va_start(args, format); + NSString* result = [[NSString alloc] initWithFormat:format arguments:args]; + va_end(args); + return result.length; +}