Hi everyone, I'm working on a GIR generator to cre...
# kotlin-native
r
Hi everyone, I'm working on a GIR generator to create kotlin native bindings for GTK and other GObject based libraries. I reached a stage where I can almost compile the bindings for GLib but I'm stuck with the handling of `vararg`s. For example
g_string_append_printf
, which is mapped with this:
Copy code
@kotlinx.cinterop.internal.CCall public external fun g_string_append_printf(string: kotlinx.cinterop.CValuesRef<native.glib.GString /* = native.glib._GString */>?, @kotlinx.cinterop.internal.CCall.CString format: kotlin.String?, vararg variadicArguments: kotlin.Any?): kotlin.Unit { /* compiled code */ }
It seems to expect a
vararg variadicArguments: kotlin.Any?
, but if I send that to it like this:
Copy code
public fun appendPrintf(format: String, vararg variadicArguments: Any): Unit {
        g_string_append_printf(cPointer.reinterpret(), format, variadicArguments)
    }
I get this error when I build the module:
Copy code
type kotlin.Array<out kotlin.Any>  is not supported here: doesn't correspond to any C type
The GIR parameter only gives a name (
...
) and has a tag `varargs`:
Copy code
<parameter name="..." transfer-ownership="none">
            <doc xml:space="preserve"
                 filename="glib-2.0.c"
                 line="32361">the parameters to insert into the format string</doc>
            <varargs/>
          </parameter>
But there are no other information about the type. I am an Android developer and not very familiar with C Interop. Does anyone have a suggestion of what this
vararg variadicArguments: kotlin.Any?
should be converted to?
a
handling interop for varargs is an open issue https://youtrack.jetbrains.com/issue/KT-56164 There might be some sort of workaround by writing a custom C function, but I haven’t tried it
r
Oh wow, so are you saying that everything that takes a vararg cannot currently be called by Kotlin Native?
a
varargs can be called from Kotlin Native, but not
vararg Any
- but there’s a workaround (maybe - I’m not 100% sure)
r
ok, I don't know if I'm saying something completely wrong but, could it be a partial workaround to check if the vararg is one of the
CValues<ShortVar>
,
CValues<ByteVar>()
, etc type and forward that to the native call and throw an
IllegalArgumentException
if is not one of the supported type? I don't know if this make sense, I just saw that the compiler doesn't throws error if I send
cValuesOf(1, 2, 3)
instead of the
vararg
a
yeah exactly, if you tell Kotlin what the type is then it should work https://stackoverflow.com/a/71442518/4161471
r
OK, the compiler seems to be happy if I send this
values: CValues<out CPrimitiveVar>
Could this be a good option?
Since I'm generating the code with KotlinPoet I can add easily as many variable arguments as I want. Isn't pretty but, if it works...
Isn't pretty, but if it works:
Copy code
public fun appendPrintf(format: String, vararg variadicArguments: CValues<out CPrimitiveVar>): Unit {
        when (variadicArguments.size) {
            0 -> g_string_append_printf(cPointer.reinterpret(), format)
            1 -> g_string_append_printf(cPointer.reinterpret(), format, variadicArguments[0])
            2 -> g_string_append_printf(cPointer.reinterpret(), format, variadicArguments[0], variadicArguments[1])
            3 -> g_string_append_printf(cPointer.reinterpret(), format, variadicArguments[0], variadicArguments[1], variadicArguments[2])
            else -> error("appendPrintf() can only accept up to 3 variable number of arguments (vararg)")
        }
    }
b
So am I (as a passion project to learn gtk)! Is your project oss for me to have a peek for ideas? What online resources did you use to get started? I found google very disappointing when trying to surface any gir documentation.
r
Hey, sure, it's completely OSS! You can find it here and it would make me really happy to get some feedback! The project includes the latest bindings, but they do not build yet. As for the documentation, I tried to join the effort to improve the https://gitlab.com/gtk-kt/gir-kt, but the main maintainer lost interest. I then decided to port the gir generator from https://github.com/bailuk/java-gtk: It seems to me more complete than the one from gir-kt. I just started looking at how the java code is generated and, from there, I'm now writing the KotlinPoet code to generate the Kotlin Native code. My goal is to make the gir generator generic enough to be able to port any GObject based library. That's why I called the project KtGObject instead of KtGTK or GTK-Kotlin. If you want to get your hands dirty, please let me know! 🙂
c
Varargs are impossible. They are done in C at compile time, and C does not support vararg manipulation like JVM does.
That is why there are numerous notes through gtk-kt & disabled warnings in gir-kt about vararg methods
r
this is how I'm generating the code now for the varargs, but I doubt that
CPointer<out CPrimitiveVar>
will cover all the cases. I can't use
Any
, @Clocks do you have any suggestion for a better type?
b
Doesn't this only ever pass a single arg to g_string_printf regardless of va size? What am I missing here?
r
oh damn, I need to sleep 😅 Yep, thanks for pointing that out
b
Phew, thought I was going bonkers myself 😀
e
platform-specific ASM could set up the stack for
va_list
or C varargs, if you really need dynamic varargs. there's no platform-independent way to do it.
r
@Big Chungus thanks again, it would have took me some time to notice it
(fixing the one with size 0, just notice that there is a
va
too much in there)
e
maybe just a poor example, but… printf accepts non-pointer arguments as well, which aren't necessarily passed the same way pointers are