Search code examples
stringd

How should I handle C-strings in D?


I'm converting the header files of a C library to D modules, and was wondering how I should handle C strings.

Using DMD 1, this works:

void f(char* s);  // Definition for C library's function.

But using DMD 2 (which I personally use, but I would like the modules to work for both) strings are const, so to get the same code using the modules to work requires

void f(const(char)* s);  // Definition for C library's function.

What should I do? Just use char* and make the 'client' code make the strings mutable somehow? Or modify the type depending on the version of the compiler compiling the code? If the former, what's the best way to make them mutable? I thought .dup would do it, but the compiler wasn't having a bar of it. If the latter, how would I go about doing it? I tried this:

version (D_Version2) {
    alias const(char)* charptr;
} else {
    alias char* charptr;
}

void f(charptr s);

But alas, the DMD 2 version isn't valid code for DMD 1, and all code in version blocks must be valid code for the compiler compiling the code, even if the code wouldn't be included in the resulting executable. So currently the code compiles in both, but you have to modify the alias first which, as you can imagine, isn't ideal.


Solution

  • You can use the mixin construct to use language-version-specific code that isn't valid in all versions. Example:

    static if(version_major<2)
    {
        alias char* charptr;
    }
    else
    {
        mixin("alias const(char)* charptr;");
    }
    

    Regarding your actual question, I would suggest doing the same as when interfacing C libraries with C++ - define a type that's const(char)* for D2 and char* for D1, but only use it when appropriate (for example, if a function takes a char* for a buffer to write to, it probably wouldn't be appropriate to name const(char)* something as generic as "charptr"). LPCSTR could work ;)

    I didn't understand the "What's the best way to make them mutable" question.