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);

Reply via email to