I have a C library that internally handles strings as {len, u8*} with no null termination. It is painful to rewrite these as null terminated char* at API boundary. I think it is still better than forcing a non-standard string type on api consumers.

Has anyone hit on an API design strategy here that's better than converting to char* in practice?

Thinking of returning length sizeof(size_t) bytes before the char*, so a toll free cast to the original type is possible for api consumers in the know.

@michaellabbe the new WebGPU C API simply says 'fuck you' and forces a WGPUStringView type on the user: https://github.com/webgpu-native/webgpu-headers/blob/c8b371dd2ff8a2b028fdc0206af5958521181ba8/webgpu.h#L193-L196

...not sure how I feel about that. For input args it's okay-ish since you can simply create a 'WGPUStringView make_string_view(const char* c_str)' that doesn't need to allocate, but the opposite direction (WGPUStringView => c_str) sucks because it needs a buffer to copy into big enough for the zero-byte.

webgpu-headers/webgpu.h at c8b371dd2ff8a2b028fdc0206af5958521181ba8 · webgpu-native/webgpu-headers

webgpu.h - C version of the JS API, for both native and Wasm. A multi-vendor standard between Dawn/Emdawnwebgpu and wgpu-native. Designed primarily for binding into higher-level languages. - webgpu...

GitHub

@michaellabbe e.g. one solution would be two helper funcs:

string_view to_view(const char* c_str);

const char* to_cstr(string_view view, char* buf, size_t buf_len);

(the latter returns zero if the string + zero-byte doesn't fit into the provided buffer)

@michaellabbe ...or if you can guarantee that all strings coming out of the API can be zero-terminated you could also just use Zig's 'sentinal-terminated slices' idea, e.g. your return a ptr/len string_view, but the pointer points to a zero-terminated string so it can be used directly as a C string without intermediate copy into a buffer.

@floooh *IF* WebGPU is justified in doing it, it would be because their API surface is large and important and its use is localized to one part of a larger codebase (the "renderer"). It is what I am trying to avoid for my library!

I like the zig approach. I suppose putting len after string pointer lets you decay into a string pointer.

@michaellabbe @floooh A disadvantage of adding a null-terminator to Pascal-style (length+pointer) strings is that you lose the ability to make sub-strings without having to copy any of the parent string's memory.