Problem Passing Struct to C

Mike Parker aldacron at gmail.com
Fri May 6 08:51:46 PDT 2011


On 5/6/2011 9:19 PM, Steven Schveighoffer wrote:
> On Fri, 06 May 2011 05:56:17 -0400, Mike Parker <aldacron at gmail.com> wrote:
>
>> Testing out a new binding I knocked up for a C library. One of the
>> functions takes a struct by value. It looks somewhat like this:
>>
>> struct S {}
>> struct Color
>> {
>> float r,g,b,a;
>> }
>>
>> extern C void function(S* s, Color color, int x, int y, in char*)
>> draw_text;
>>
>> Now, there is another function that adjusts color values when making a
>> color. In C, it is sometimes used like so:
>>
>> draw_text(s, map_color(255, 0, 0, 0), 0, 0, "Blarg");
>>
>> When I'm calling draw_text like this on the D side, my text output is
>> corrupt. I keep getting weird things like ^^P^, but in the appropriate
>> color. It's consistent, no matter what string I pass, but is different
>> for each color value. If I call draw_text like this:
>>
>> auto color = map_color(...);
>> draw_text(s, color, 0, 0, "Blarg");
>>
>> It works as expected. Has anyone else seen this, or know of a
>> workaround? I'm going to dig through bugzilla later on and see if it's
>> been reported already, but I'm curious if anyone knows of the cause
>> off hand.
>>
>
> There are two possible causes I can think of, depending on how draw_text
> is defined in C.
>
> 1. is it truly a function pointer? That is, does the definition look
> like void (*draw_text)(S* s, ...), or is it just void draw_text(S* s, ...)?

It's a pointer to a function symbol in a DLL. In Derelict, all functions 
are pointers on the D side, since the shared libraries are loaded 
manually. I've bound several C libs in the same way and never 
encountered this before.

>
> 2. It's possible that the extern C (BTW, I thought it had to be
> extern(C)?) is only applying to the symbol name draw_text and not the
> function type.

Yeah, that's a typo in my post. It's definitely declared as extern(C) in 
the source. And I checked with the pragma given below to make sure.

>
> If you answer no to #1, then your problem is your draw_text definition
> in D. It should look like this:
>
> extern(C) void draw_text(S * s, Color color, int x, int y, in char *);
>
> If you answer yes to #1, then to check what type the compiler is giving
> to draw text, do:
>
> pragma(msg, (typeof(draw_text)).stringof);
>
> This hopefully tells you that it's extern(C), but if not, that is likely
> the problem.
>
> If that's not it, I have no idea ;)
>

Thanks for the guesses. I don't believe any of the libraries I've bound 
before now have any functions that take a struct by value. If they have, 
I haven't had occasion to use them yet. So I wonder if this is an issue 
with how the compiler handles returning a value struct from a function. 
Could there be a difference in how it's pushed on to the stack in a D 
function call versus how it's expected in C? Just grasping.



More information about the Digitalmars-d-learn mailing list