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
0x000000000045ae48 <+8>: mov 0x3fdb9(%rip),%rdx #
0x49ac08 <_TMP0+8>
0x000000000045ae4f <+15>: mov 0x3fdaa(%rip),%rax #
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