Is there a way to provide a ByteArray as a paramet...
# kotlin-native
p
Is there a way to provide a ByteArray as a parameter to a C-interop function that expects
const char*
? I've read the documentation but couldn't figure out how to do it. Adding
noStringConversion = xxx
doesn't seem to do anything for me. I don't want to convert to a String before passing the value, I just want to pass the ByteArray as is.
k
byteArray.toCValues().ptr
?
p
Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: public val <T : CPointed> ???.ptr: CPointer<???> defined in kotlinx.cinterop
k
you have to do it within memScoped { }
another option is probably to use
byteArray.refTo(0)
but I haven't tried that one
p
Type inference failed. Expected type mismatch: inferred type is CPointer<ByteVar /* = ByteVarOf<Byte> */> but String? was expected
k
can you post the whole block of code?
p
Copy code
actual suspend fun sendData(nScannerId: Int, pDataBuf: ByteArray): Int {
    return executeInWorker(blueWorker, SendData(nScannerId, pDataBuf)) { data ->
        memScoped {
            nim_SendData(data.scannerId, data.data.toCValues().ptr, data.data.size)
        }
    }
}
It's executed on a worker thread, don't know if it has anything to do with it
Copy code
data class SendData(val scannerId: Int, val data: ByteArray)
k
what about
executeInWorker
?
k
ok and
nim_SendData
?
p
Copy code
DLL_EXP int    nim_SendData         ( int nScannerID, const char *pDataBuf, int nLen );
This is the C interop function
const char* means Kotlin wants a String, but I don't want to convert my bytearray to a string before calling the function, because the encoding should not mess it up.
k
and how does the generated interop signature look like?
p
Where can I see this?
k
if you just control+click it in the IDE ?
but nevermind, it wants string, so you have to pass a string
p
But I don't want to 😞
And according to the documentation it should work, right? I have no idea, the Native documentation is not really intuitive
Apparently there is no other way than to encode it as a string with UTF-8, but I don't want to do that, because the byteArray might not be UTF-8 encoded
k
yes, I agree on that.. but it is strange because if you have a C function that is expecting
char *
than I would expect the generated kotlin knm with a
CValuesRef<ByteVar>
signature.. like in the example in the doc:
Copy code
void pass_string(char* str) {
}
becomes:
Copy code
fun pass_string(str: CValuesRef<ByteVar /* = ByteVarOf<Byte> */>?)
p
I think
char *
is different from
const char*
According to this it should work, but it doesn't currently, so I don't know
k
hm , you might be right, I was about to say you will have to call either:
Copy code
toKString()
or
Copy code
toKStringFromUtf8()
p
Yep, but I don't want to do that
If I do this, it works, but then my bytearray is utf-8 encoded, which I don't like
k
Ok, I see your point now.. so you say the
noStringConversion =
is not working?
did you regenerate the interop bindings after changing this?
p
Yes, I did
I deleted the whole build folder and tried again, but still same issue
Or do I have to do something like
byteArray.ptr
?
k
You should be able to see which type it is expecting. Do you see the generated stubs?
a
You can just simply write
"your string".cstr
p
@Animesh Sahu How does that help me? I don't have a string in the first place. And decoding it to string might loose information, depending on the encoding.
a
🤔 If that's the case cValuesOf seems to be the last option if I am right...