Could anyone please provide an example of how to c...
# kotlin-native
a
Could anyone please provide an example of how to call a c-function that takes a va_list argument from Kotlin Native? e.g.
vsnprintf
b
You mean an array?
a
yeah, calling vsnprintf with an array of args
b
Something like this:
Copy code
fun run(args: Array<String>? = null) = memScoped {
    vsnprintf(args?.size ?: 0, args?.toCStringArray(this))
  }
a
Trying to pass the result of toCStringArray() where va_list is expected gives me this:
Copy code
e: /Users/am/projects/sdg12-deeds-ios/deedster-common/lib-common/src/iOSMain/kotlin/se/sdg12/deedster/util/sprintf.kt: (21, 25): Type mismatch: inferred type is CPointer<CPointerVar<ByteVar /* = ByteVarOf<Byte> */> /* = CPointerVarOf<CPointer<ByteVarOf<Byte>>> */> but va_list? /* = CPointer<__va_list_tag>? */ was expected
b
Hmm, try adding
.reinterpret()
after it
a
hmmm, some sort of crash unfortunately. Thanks for your help, gotta run unfortunately will revisit this later
d
I was researching this recently and I don't think it's possible. The only reason the va_list function is exposed at all, is so you can pass
null
as the argument.
If you have no other alternative, you can use cinterop to make a
...
wrapper for it. Then you can call it through that.
a
Yeah I found those. Don't really think that solves my problem though. As I understand it I'm only allowed to call the vararg version of c methods with
*àrrayOf(...)
, which means I need to know the amount of args ahead of time. If I try to call with
*runtimeConstructedAssignedArrayVariable
it failes to compile.
d
Yeah, I have the same issue in a project of mine. Variadic functions are also quite limited in C it seems.
You also need to know the type of the arguments ahead of time.
a
Okay, so maybe this is a dead end... Did you find some workaround? Basically I'm just trying to get a cross-platform equivalent of String.format() / snprintf where I don't need to know types and amount of args beforehand.
d
Same issue here. Best to just implement sprintf in pure Kotlin. I'm surprised no one has done it yet (AFAIA).
a
okay, thanks
m
Weird. I see in `platform.posix`:
Copy code
@CCall("knifunptr_platform_posix672_sprintf")
external fun sprintf(__s: CValuesRef<ByteVar>?, @CCall.CString __format: String?, vararg variadicArguments: Any?): Int

@CCall("knifunptr_platform_posix675_vsprintf")
external fun vsprintf(__s: CValuesRef<ByteVar>?, @CCall.CString __format: String?, __arg: __gnuc_va_list?): Int
d
You can't call it without knowing the type and count of the args at compile time. And there's no way to provide a compile time wrapper, with an inline function of something.
m
Copy code
import platform.posix.printf
fun main() {
    printf("Hello %s%c", "World", '!'.toInt())
}
Copy code
Hello World!
a
Yeah that works @msink, but now try it where the args ("World" and "!") are from an array.
d
n
Variadic arguments are definitely, a "*pain* in the void" 😆 . Using the GTK libraries, and found in a few cases if there is a corresponding C function that takes a single item (instead of variadic arguments) then it is easier to use that function instead.
m
Hm, I think in K/N stdlib should be (currently missed) variant of
memScoped
function with
vararg
parameter, something like
fun memScoped(va: Array<>, block: (va_list) -> Unit)
🤔 1
âž• 2