Can anyone give me a hand with the following C to ...
# kotlin-native
c
Can anyone give me a hand with the following C to Kotlin conversion? 🧵
Copy code
typedef struct opaque_struct opaque_t;

size_t do_something(opaque_t **output); // Returns number of elements that have been populated
void do_something_else(opaque_t *value);

// Where typical use would be something like:
opaque_t **result = NULL;
size_t elements = do_something(output);

for (int i = 0; i < elements; i++) {
	do_something_else(result[i]);
}
I'm stuck on:
Copy code
val result = zeroValue<CPointerVar<CPointerVar<opaque_t>>>()
val elements = do_something(result)

for (i in 0 until elements) {
	do_something_else(/* what goes here */)
}
l
You're passing in the equivalent of do_something(NULL) in C when you pass in the zeroed pointer. You should instead allocPointerTo and pass that in.
c
ah of course, I need to allocate a pointer, to the pointer of pointers, such that the library call can dereference the pointer being passed in, to then set it's value
(right :X?)
l
You need to allocate a pointer to a pointer (kotlin implicitly handles a level of pointer since it's JVM-based, which makes c pointers fun to reason about). The type system should help, just make sure to watch out for zero and null. Kotlin can't give you the 'pointer' it uses under the hood, so no equivalent to &x
c
ahhh
l
I like to substitute the term array when applicable (kotlin also has a CArrayPointer alias for you). Here you are passing in a pointer to an array of opaque types. The library creates this array and sets your input to point to it.
c
I haven't felt this pain in a long time! Genuine learning. So,
Copy code
val output = allocArray<CPointerVar<opaque_t>>(0)
Would that be what you would expect?
l
I think that works. I'm on mobile right now, so can't check it.
c
no worries, this isn't mission critical, so any help, even shooting from the hip is massively appreciated. I guess I could do with learning the basics rather than jumping straight to this level of pointer manipulation
l
Actually, I think the array is in the wrong spot (shouldn't matter since array pointer is an alias anyways). I'd do allocPointerTo<CArrayPointer<opaque_t>>()
Thinking about it, I may be wrong. You may need allocPointerTo<opaque_t>().ptr, since you need the pointer to be set properly. It's been a minute since I've dealt with this. Try a few permutations and one'll eventually work.
c
I was able to get it working in the end, though I think someone with more experience would be able to improve it. I'm messing about with
libusb
. I ended up with
Copy code
fun devices(): List<UsbDevice> {
        return memScoped {
            val deviceList: CPointer<CPointerVar<CPointerVar<libusb_device>>> = allocArray(22)
            val deviceCount = libusb_get_device_list(null, deviceList.reinterpret())
            val devices = mutableListOf<UsbDevice>()
            for (i in 0 until deviceCount) {
                deviceList.pointed.pointed!!.ptr[i]?.let { ptr ->
                    val desc: libusb_device_descriptor = alloc<libusb_device_descriptor>()
                    libusb_get_device_descriptor(ptr, desc.ptr)
                    devices.add(UsbDevice(desc.idVendor, desc.idProduct))
                }
            }
            devices
        }
    }
it 'works' but I think I was just changing things randomly to get to that point, I still don't fully understand what I was doing