1 module allegro5.internal.da5;
2 
3 /*
4  * Issue: MinGW 4.5 and below has a bizzare calling convention when
5  * returning structs. ColorWrapper takes care of the difference in
6  * calling convention. If this wrapper is necessary, then D programs
7  * that use DAllegro5 should link against allegro_color even when they
8  * never call any allegro_color function.
9  *
10  * The following toolchains (to compile Allegro DLLs) are free of this issue:
11  *  - MSVC,
12  *  - maybe MinGW 4.6.
13  * ColorWrapper resolves to a mere binding on all systems that don't
14  * need the caretaking, and allegro_color needs not be linked against
15  * then unless you call a function from allegro_color.
16  *
17  * ColorWrapper is private to DAllegro5. Call ColorWrapper in DAllegro5
18  * outside any "nothrow @nogc extern (C)" because ColorWrapper will
19  * insert attributes itself.
20  */
21 char[] ColorWrapper(
22 	in char[] prefix, in char[] func, in char[] arg_decls, in char[] arg_names)
23 {
24 	static if (NeedsMinGW4CallingConvention)
25 	{
26 		// Implement a new D function to wrap Allegro's C function,
27 		// fixing the calling convention (see comment for ColorWrapper above).
28 		return
29 			`nothrow @nogc ALLEGRO_COLOR ` ~ func ~ `(` ~ arg_decls ~ `)
30 			{
31 				auto ret = ` ~ prefix ~ func ~ `(` ~ arg_names ~ `);
32 				asm nothrow @nogc
33 				{
34 					sub ESP, 4;
35 				}
36 				return ret;
37 			}`;
38 	}
39 	else
40 	{
41 		// Declare function as a normal C binding.
42 		return
43 			`nothrow @nogc extern (C)
44 			ALLEGRO_COLOR ` ~ func ~ `(` ~ arg_decls ~ `);`;
45 	}
46 }
47 
48 bool NeedsMinGW4CallingConvention() pure nothrow @nogc
49 {
50 	version(ALLEGRO_MINGW_4_5)
51 	{
52 		return true;
53 	}
54 	else
55 	{
56 		return false;
57 	}
58 }