D string to C struct fixed-size array

Jack jckj33 at gmail.com
Mon Jan 4 16:35:23 UTC 2021


On Sunday, 3 January 2021 at 08:43:34 UTC, bdh wrote:
> Hi,
>
> I'm trying to create bindings to the GraphcicsMagick C library 
> which has the following struct defined:
>
> [...]

Do you mean fill .filename member from a D string? something like 
this?

>import std.stdio;
>
> [...]

>    struct Image
>    {
>      /* other members skipped */
>      char[MaxTextExtent] filename;
>    }
>}
>
> [...]
>import std.stdio;
>
>extern(C)
>{
> 
>    enum MaxTextExtent = 2053;

>    struct Image
>    {
>      /* other members skipped */
>      char[MaxTextExtent] filename;
>    }
>}
>
>void main()
>{
>    import std.string : toStringz;
>    import core.stdc.string : memcpy, strlen;
>
>    auto i = Image();
>    auto dstr = "hello world!!!"; // D string
>    auto cs = toStringz(dstr); // now it's C-null-terminatted 
> string

>    // since .filename isn't a pointer but an array, I think
>    // you have to use memcpy() here. = operator wouldn't work 
> properly.
>    memcpy(&i.filename[0], &cs[0], strlen(cs)+1);
>
>    // casting away arrayness to make it a pointer (that a C's 
> array is after all)
>    printf("str = [%s]\n", &i.filename[0]);
>}
>
> [...]

note that even if .filename was a pointer, in order to the C 
converted stirng don't turn into garbage in a GC cycle, you would 
have to either keep reference to dstr around or malloc() and 
memcpy() it. So you need to convert from C to D: you can use 
fromStringz() on D string then to!string to convert to a D 
string, like this:

> import std.conv : to;
> import std.string : fromStrinz;
> string s = to!string(cstr.fromStringz);


More information about the Digitalmars-d-learn mailing list