digitalmars.D - Problem passing string to cpp on 64bit linux
- Gerrit Wichert (95/95) Jul 03 2011 Hello,
- Walter Bright (3/5) Jul 03 2011 Passing structs as value parameters do not follow the C ABI on Linux 64....
Hello, currently i'm trying to get wxD running on my opensuse 11.4 64bit box. I've got it running before on opensuse 11.3 32bit using dmd 2.41 (with some little tweaking to the wxd sources). After Upgrading my box, I installed the 64bit version of dmd 2.43 and tried to compile it in 64bit mode. It needed a little more tweaking (casting down some length properties where wxWidgets expected int), but finally I got it to compile and link with my app. But when I tried to run it I only got a segfault. Using GDB on it I was able to locate the problem. For passing strings to cpp wxD makes use of a neat little trick. Strings were just passed to a C function expecting a struct of type 'dstr' like in this testing code. app.d ================================ import std.stdio; // struct d_str { // size_t length; // const(char) *data; // this( string text) { // length = text.length; // data = text.ptr; // } // } // static extern (C) void cpp_test( d_str text); static extern (C) void cpp_test( string text); void main( string[] args) { //d_str dtext = "this is a testcall"; string dtext = "this is a testcall"; cpp_test( dtext); } test.cpp ============================== #include <stdio.h> #include <string.h> struct dstr { size_t length; const char* data; }; extern "C" void cpp_test( dstr ctext) { printf( "string is: %.*s\n", (int)ctext.length, ctext.data); return; } =================================== compiled with: g++ -g -Wall -c -o test.o test.cpp && dmd -gc test.o app. As said above this worked fine in 32 bit mode but stopped working when compiled in 64 bit mode. The received struct in the called cpp function just contains garbage. The calling and receiving functions disassemble to the following sequences. Dump of assembler code for function D main: 0x000000000045ae40 <+0>: push %rbp 0x000000000045ae41 <+1>: mov %rsp,%rbp 0x000000000045ae44 <+4>: sub $0x10,%rsp 0x49ac08 <_TMP0+8> 0x49ac00 <_TMP0> 0x000000000045ae56 <+22>: mov %rax,-0x10(%rbp) 0x000000000045ae5a <+26>: mov %rdx,-0x8(%rbp) 0x000000000045ae5e <+30>: rex.W push %rdx 0x000000000045ae60 <+32>: rex.W push %rax 0x000000000045ae62 <+34>: callq 0x45adf4 <cpp_test(dstr)> 0x000000000045ae67 <+39>: add $0x10,%rsp 0x000000000045ae6b <+43>: xor %eax,%eax 0x000000000045ae6d <+45>: leaveq 0x000000000045ae6e <+46>: retq End of assembler dump. Dump of assembler code for function cpp_test(dstr): 0x000000000045adf4 <+0>: push %rbp 0x000000000045adf5 <+1>: mov %rsp,%rbp 0x000000000045adf8 <+4>: sub $0x10,%rsp 0x000000000045adfc <+8>: mov %rdi,%rdx 0x000000000045adff <+11>: mov %rsi,%rax 0x000000000045ae02 <+14>: mov %rdx,-0x10(%rbp) 0x000000000045ae06 <+18>: mov %rax,-0x8(%rbp) 0x000000000045ae0a <+22>: mov -0x8(%rbp),%rdx 0x000000000045ae0e <+26>: mov -0x10(%rbp),%rax 0x000000000045ae12 <+30>: mov %eax,%esi 0x000000000045ae14 <+32>: mov $0x49abc4,%edi 0x000000000045ae19 <+37>: mov $0x0,%eax 0x000000000045ae1e <+42>: callq 0x45a728 <printf plt> 0x000000000045ae23 <+47>: leaveq 0x000000000045ae24 <+48>: retq End of assembler dump. If I interpret this right then the problem is D pushing the array on the stack while cpp is expecting the structs values in the rdi and rsi registers. The GDB command 'ptype dtext' returns 'type = ucent' for the D string type. Since this is a 128 bit type I thought it may be passed on the stack because it doesn't fit in the registers. I the tried to pass an explicit struct (outcommented code) but with the same outcome. It also seems to be passed on the stack. So now I'm at the end of my wits. Is this expected or a bug in the 64bit linux implementation? And what can i do to keep this neat little trick alive? Gerrit Wichert
Jul 03 2011
On 7/3/2011 9:42 AM, Gerrit Wichert wrote:Strings were just passed to a C function expecting a struct of type 'dstr' like in this testing code.Passing structs as value parameters do not follow the C ABI on Linux 64. This is a known bug.
Jul 03 2011