toStringz or not toStringz

Steven Schveighoffer schveiguy at yahoo.com
Fri Jul 8 06:48:30 PDT 2011


On Fri, 08 Jul 2011 07:53:20 -0400, Regan Heath <regan at netmail.co.nz>  
wrote:

> On Fri, 08 Jul 2011 10:49:08 +0100, Walter Bright  
> <newshound2 at digitalmars.com> wrote:
>
>> On 7/8/2011 2:26 AM, Regan Heath wrote:
>>> Why can't we have the
>>> compiler call it automatically whenever we pass a string, or char[] to  
>>> an extern
>>> "C" function, where the parameter is defined as char*?
>>
>> Because char* in C does not necessarily mean "zero terminated string".
>
> Sure, but in many (most?) cases it does.  And in those cases where it  
> doesn't you could argue ubyte* or byte* should have been used in the D  
> extern "C" declaration instead.  Plus, in those cases, worst case  
> scenario, D passes an extra \0 byte to those functions which either  
> ignore it because they were also passed a length, or expect a fixed  
> sized structure, or .. I don't know what as I can't imagine another case  
> where char* would be used without it being a "zero terminated string",  
> or passing/knowing the length ahead of time.
>
> D is already allocating an extra \0 byte for string constants right?   
> And, I assume, toStringz is already clever enough to detect cases where  
> there is already a \0 in the correct position, or utilises the existing  
> preallocated space remaining in a dynamic array, making it almost a  
> no-op.  The only case it actually does any work is a dynamic or static  
> array which is full.  In the former case the array is resized, and I'm  
> not sure about the latter but I suspect it's more expensive.  So, it  
> seems the cost of this is very low.

What about a template function that does this automatically? I'm thinking  
something like opDispatch:

extern(C) foo(const(char)* c);

struct CCall
{
    auto opDispatch(string call, S...)(S args) if(call is a C function (can  
check this somehow?) )
    {
        /* determine which args of S are char[], and translate them to  
zero-terminated */
        ...
    }
}

usage:

string s;
CCall.foo(s);

I personally think, barring this idea, the best path is simply to wrap C  
functions you want to call with toStringz'd versions.

-Steve


More information about the Digitalmars-d mailing list