String to byte array

What is a correct way to convert Julia-String UTF8 to byte array which can be exported as C-like string char* using ccall callback function ?
pseudo-code:

jString = String("a_šČô_φ_привет_일_迪弗尺")
strByteArray = toByteArray(jString)
len = length(strByteArray)
# fnc is pointer to C callback function void(__stdcall*)(const char* str, const size_t len);
fnc != Ptr{Void}(0) && ccall(fnc, Void, (Cstring, Int64), strByteArray, len) 

You can get the UTF8 bytes as an array with convert(Vector{UInt8}, jString) but I guess you still need to append a zero byte for C compatibility.

No need to call something like toByteArray, just pass the string to ccall, which will handle everything automatically. The only thing you need to figure out is the length of the string in bytes, which can be obtained using sizeof. Note that since you pass the length as an argument, you can use Ptr{UInt8} instead of Cstring to avoid checking for the presence of null bytes in the string. See the manual for details.

This would probably deserve a short mention in the manual. You could open an issue about that.

1 Like

thaks for hints. the resulting implementation:
Julia side

  jString = String("a_šČô_φ_привет_일_迪弗尺")
  fnc != C_NULL &&
    ccall(fnc, Void, (Ptr{UInt8}, Cint), jString, sizeof(jString)) # @nalimilan nalimilan

CPP side: possible implementation - write data as arrived…

void callbackfn(const char* data, const int len )
{
  std::ofstream ofs("myFile.txt", std::ios::binary);
  ofs.write(data, len); // don't worry about null-terminated string
  ofs.close();
}

Cool. Note you don’t even need to call String. Also, more importantly, use Cint instead of Int64 if you define len as int in the C code.

1 Like

I’ve corrected the Cint as well ac C_NULL in solution the code above.