digitalmars.D.learn - What exactly gets returned with extern(C) export string func() ?
- cc (51/51) Jun 13 2021 D under dmd/Win10/64-bit currently seems to store strings
D under dmd/Win10/64-bit currently seems to store strings (slices) internally like so: ```d static struct DString { size_t length; immutable(char)* ptr; } static assert(DString.sizeof == string.sizeof); string s = "abcde"; DString d; memcpy(&d, &s, s.sizeof); assert(d.length == s.length); assert(d.ptr == s.ptr); ``` If I write a DLL export like: ```d extern(C) export string someDLLFunc() { return "hello"; } ``` struct DString { public long length; public IntPtr ptr; } [DllImport("mydll.dll")] extern DString someDLLFunc(); ... DString d = someDLLFunc(); System.Console.WriteLine("dstr: {0} : {1}", d.length, d.ptr); ``` value from `someDLLFunc()`, the length and ptr parameters are both 0. If I explicitly pass a struct back from D instead like so: ```d static struct DString { size_t length; immutable(char)* ptr; this(string str) { length = str.length; ptr = str.ptr; } } extern(C) export DString someDLLFunc() { return DString("hello"); } ``` explicitly disallow slices as an extern(C) export parameter type?
Jun 13 2021
On Sunday, 13 June 2021 at 10:02:45 UTC, cc wrote:explicitly disallow slices as an extern(C) export parameter type?The spec says that there is no equivalent to type[]. You get a type* instead.
Jun 13 2021
On Sunday, 13 June 2021 at 21:13:33 UTC, frame wrote:On Sunday, 13 June 2021 at 10:02:45 UTC, cc wrote:I can't seem to get it to work as a return type, but interestingly it does work as an out/pass by ref parameter. D: ```d export void D_testString(out string ret) { ret = "hello".idup; } ``` public struct DString { public ulong length; public IntPtr ptr; public string str { get { byte[] b = new byte[length]; for (int i = 0; i < (int)length; i++) { b[i] = Marshal.ReadByte(ptr, i); } return Encoding.UTF8.GetString(b); } } } [DllImport("test.dll")] private static extern void D_testString(out DString dd); public static string testString() { DString d; D_testString(out d); return d.str; } ```explicitly disallow slices as an extern(C) export parameter type?The spec says that there is no equivalent to type[]. You get a type* instead.
Jun 15 2021
On Wednesday, 16 June 2021 at 02:46:36 UTC, cc wrote:I can't seem to get it to work as a return type, but interestingly it does work as an out/pass by ref parameter.Probably for returning the struct it needs some allocation to do with the IntPtr. It may work if you use a struct on the DLL side too and convert any specific things like pointers to simple integers instead. The out keyword however basically is just a pointer to the struct, so reading directly from the memory offset from the DLL works instead. As long the GC sees the data alive - .(i)dup doesn't protect your memory here. The data could be collected by the GC anytime the function call goes out of scope.
Jun 16 2021