www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - DMD-64 2.062 and GCC can't pass >8byte structs?

reply "E.S. Quinn" <onetruequinn hotmail.com> writes:
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.
Apr 13 2013
parent reply "E.S. Quinn" <onetruequinn hotmail.com> writes:
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);
}
Apr 13 2013
parent "Dicebot" <m.strashun gmail.com> writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5570
Apr 14 2013