How to use GDI+ in C?

Meta picture Meta · Feb 25, 2011 · Viewed 7.5k times · Source

Disclaimer: I'm only getting started in C, so it's likely that I'm missing something obvious, or not thinking the right way! :)

How exactly would I go about using GDI+ in pure C? As I understand it, GDI+ has wrapped objects made for C++, but underneath it lies a flat API which is accessible through gdiplusflat.h, a C-friendly header.

My problem is that when I #include it, I get the following errors:

C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\gdiplusflat.h(30) : error C2143: syntax error : missing '{' before '__stdcall'
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\gdiplusflat.h(31) : error C2146: syntax error : missing ')' before identifier 'brushMode'
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\gdiplusflat.h(31) : error C2061: syntax error : identifier 'brushMode'
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\gdiplusflat.h(31) : error C2059: syntax error : ';'
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\gdiplusflat.h(31) : error C2059: syntax error : ','
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\gdiplusflat.h(31) : error C2059: syntax error : ')'
and 100 more...

Now, I think these errors are due to GpStatus not being defined because peeking into GdiPlusFlat.h shows that all the functions are of the style:

// WINGDIAPI is #defined as __stdcall
GpStatus WINGDIPAPI
GdipCreatePath(GpFillMode brushMode, GpPath **path);
GpStatus WINGDIPAPI
GdipCreatePath2(GDIPCONST GpPointF*, GDIPCONST BYTE*, INT, GpFillMode,
                                    GpPath **path);
GpStatus WINGDIPAPI
GdipCreatePath2I(GDIPCONST GpPoint*, GDIPCONST BYTE*, INT, GpFillMode,
                                     GpPath **path);
etc...

The problem is that GpStatus is a typedef to Status in GdiPlusGpStubs.h (a C++ header), and Status is itself an enum defined in GdiPlusTypes.h (also a C++ header). I tried defining the enum myself, but for some reason the compiler wouldn't take it!

So... how does one exactly use GDI+ functions in C? Should I just load gdiplus.dll dynamically?

Answer

selbie picture selbie · Feb 28, 2011

The problem is that gdiplusflat.h really needs many more gdi*.h header files included before it. But many of these header files that have the needed typedef declarations referenced by gdiplusflat.h also contain "class" declarations and other C++ keywords. The C compiler will error out when it sees these lines.

You have two choices.

  1. Simple. Accept the fact that C++ is essentially a superset of C. Then just rename your ".c" file you are trying to compile to have a ".cpp" extension. Your C code will get compiled as C++, but that likely won't change a line of code you write. Then #include gdiplus.h before you #include gdiplusflat.h

  2. Harder. depends on typedef definitions in other header files. The problem is that many of these header files have "class" definitions and C++ keywords that the C compiler will error out on. You'll have to manually port over many of the C declarations into your own header file that gets included before gdiplusflat.h. Here's my feeble attempt. It's not quite done. It gets half of the compilation errors out. But I got too tired and just went with option #1. You could finish it, but option 1 above is so much easier.

x

enum Status
{
    Ok = 0,
    GenericError = 1,
    InvalidParameter = 2,
    OutOfMemory = 3,
    ObjectBusy = 4,
    InsufficientBuffer = 5,
    NotImplemented = 6,
    Win32Error = 7,
    WrongState = 8,
    Aborted = 9,
    FileNotFound = 10,
    ValueOverflow = 11,
    AccessDenied = 12,
    UnknownImageFormat = 13,
    FontFamilyNotFound = 14,
    FontStyleNotFound = 15,
    NotTrueTypeFont = 16,
    UnsupportedGdiplusVersion = 17,
    GdiplusNotInitialized = 18,
    PropertyNotFound = 19,
    PropertyNotSupported = 20,
#if (GDIPVER >= 0x0110)
    ProfileNotFound = 21,
#endif //(GDIPVER >= 0x0110)
};



typedef Status GpStatus;

enum FillMode
{
    FillModeAlternate,        // 0
    FillModeWinding           // 1
};

typedef FillMode GpFillMode;

struct GpPath {};

typedef float REAL;

struct GpPointF
{
    REAL x;
    REAL y;
};

struct GpPoint
{
    int x;
    int y;
};
#include <gdiplusflat.h>