Thread overview
DMD-64 2.062 and GCC can't pass >8byte structs?
Apr 13, 2013
E.S. Quinn
Apr 13, 2013
E.S. Quinn
Apr 14, 2013
Dicebot
April 13, 2013
Hi! I've been helping with some code to interface to a C library,
and I think I've discovered a bit of a hangup in the 64-bit linux
version of DMD.

If a struct is eight bytes or less (the size of two uints), it
can be passed just fine between D and C code, but if it's any
larger than that, the data gets messed up somewhere along the
way. This doesn't happen when the code is compiled in 32-bit mode
(with -m32)

Here's some example code to trigger the bug:

structyc.c:
-----

#include <stdio.h>

struct passingstruct {
	unsigned int a;
	unsigned int b;
	int c;
};

void printatest (struct passingstruct value)
{
	printf ("hello!\n");
	printf ("%u %u %d\n", value.a, value.b, value.c);
}
-----

structyd.d:
------
import std.stdio;

struct passingstruct {
	uint a;
	uint b;
	int c;
	
	void printme () {
		writefln ("%d %d", a, b);
	}
}

int main (char[][] args)
{
	auto thingy = passingstruct( 300, 200, 0);
	writefln ("%u %u %d", test.a, test.b, test.c);
	
	printatest (test);
	return 0;
}

extern (C)
{
	void printatest (passingstruct value);
}
-------

When compiled and linked in 64-bit mode, it produces this output:

300 200 0
hello!
394682976 32695 402542592

However, 32-bit mode produces the expected output:

300 200 0
hello!
300 200 0

Additionally, if the third element (.c) is taken out of the
"testman" struct, or if b and c are made ushort or ubyte, the
program works fine in 64-bit mode. GDC(an admittedly out-of-date
version--ubuntu only packages 4.6.3) also successfully passes the
whole struct in 64bit mode.
April 13, 2013
Er, my apologies. The code on that post won't actually do what it's supposed to.  I wrote my testcode originally with very idiosyncratic variable names, and hadn't actually recompiled the code after I changed them for my post. This should actually work:

structc.c:
-------

#include <stdio.h>

struct passingstruct {
	unsigned int a;
	unsigned int b;
	int c;
};

void printatest (struct passingstruct value)
{
	printf ("hello!\n");
	printf ("%u %u %d\n", value.a, value.b, value.c);
}
----
structd.d:
------
import std.stdio;

struct passingstruct {
	uint a;
	uint b;
	int c;
	
	void printme () {
		writefln ("%d %d", a, b);
	}
}

int main (char[][] args)
{
	passingstruct test = passingstruct( 300, 200, 0);
	writefln ("%u %u %d", test.a, test.b, test.c);
	
	printatest (test);
	return 0;
}

extern (C)
{
	void printatest (passingstruct value);
}
April 14, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=5570