www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Calling a C Function with C-style Strings

reply =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
I'm struggling to call mktemp in D:

     import core.sys.posix.stdlib;
     import std.string: toStringz;
     auto name = "alpha";
     auto tmp = mktemp(name.toStringz);

but I can't figure out how to use it so DMD complains:

     /home/per/Work/justd/fs.d(1042): Error: function 
core.sys.posix.stdlib.mktemp (char*) is not callable using 
argument types (immutable(char)*)

How do I create a mutable zero-terminated C-style string?

I think I've read somewhere that string literals (`const` or 
`immutable`) are implicitly convertible to zero (null)-terminated 
strings.
Nov 30 2013
next sibling parent reply "Dicebot" <public dicebot.lv> writes:
On Saturday, 30 November 2013 at 15:48:28 UTC, Nordlöw wrote:
 I think I've read somewhere that string literals (`const` or 
 `immutable`) are implicitly convertible to zero 
 (null)-terminated strings.
AFAIR, this should work: char[] name = "alpha".dup; mktemp(name.ptr); D literals are zero-terminated so toStringz is only needed if you want to pass to C function slice of literal or some runtime input. Another option is to declare extern(C) function to take `const (char)*` argument, as far as I remember C it should not affect mangling but will allow to pass literal directly without allocating a mutable copy.
Nov 30 2013
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 11/30/2013 07:58 AM, Dicebot wrote:

 char[] name = "alpha".dup;
 mktemp(name.ptr);

 D literals are zero-terminated so toStringz is only needed if you want
 to pass to C function slice of literal or some runtime input.
However, I doubt that .dup copies that '\0' character. Although the literal has the termination, we are in slice land beyond that literal so the termination must somehow be ensured. Ali
Nov 30 2013
parent "Dicebot" <public dicebot.lv> writes:
On Saturday, 30 November 2013 at 18:58:30 UTC, Ali Çehreli wrote:
 However, I doubt that .dup copies that '\0' character. Although 
 the literal has the termination, we are in slice land beyond 
 that literal so the termination must somehow be ensured.

 Ali
Hm, yes, this also sounds like a valid concern. I thought that for literals \0 is part of actual string but after making a quick check it looks "hidden" behind actual length. So yep, perfectly wrong answer from me :)
Nov 30 2013
prev sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Saturday, 30 November 2013 at 15:48:28 UTC, Nordlöw wrote:
     /home/per/Work/justd/fs.d(1042): Error: function 
 core.sys.posix.stdlib.mktemp (char*) is not callable using 
 argument types (immutable(char)*)
This is because mktemp needs to write to the string. From mktemp(3): The last six characters of template must be XXXXXX and these are replaced with a string that makes the filename unique. Since it will be modified, template must not be a string constant, but should be declared as a character array. So what you want to do here is use a char[] instead of a string. I'd go with: import std.stdio; void main() { import core.sys.posix.stdlib; // we'll use a little mutable buffer defined right here char[255] tempBuffer; string name = "alphaXXXXXX"; // last six X's are required by mktemp tempBuffer[0 .. name.length] = name[]; // copy the name into the mutable buffer tempBuffer[name.length] = 0; // make sure it is zero terminated yourself auto tmp = mktemp(tempBuffer.ptr); import std.conv; writeln(to!string(tmp)); }
Nov 30 2013
next sibling parent "Dicebot" <public dicebot.lv> writes:
On Saturday, 30 November 2013 at 15:59:38 UTC, Adam D. Ruppe 
wrote:
 This is because mktemp needs to write to the string.
Ah disregard my post then, I thought it is yet another C function that misses `const` in signature :)
Nov 30 2013
prev sibling parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 11/30/2013 07:59 AM, Adam D. Ruppe wrote:

      tempBuffer[name.length] = 0; // make sure it is zero terminated
 yourself
Because char.init is not 0 in D: :) assert(tempBuffer[name.length + 1] == '\xff'); Ali
Nov 30 2013