Как использовать GDI + в C?

Отказ от ответственности: я только начинаю работать на C, так что, вероятно, я пропущу что-то очевидное или не думаю правильно!:)

Как я могу использовать GDI + в чистом C? Как я понимаю, GDI + обернул объекты, сделанные для С++, но под ним лежит плоский API, доступный через gdiplusflat.h, C-дружественный заголовок.

Моя проблема в том, что когда я # включил его, я получаю следующие ошибки:

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...

Теперь, я думаю, эти ошибки обусловлены тем, что GpStatus не определяется, потому что просмотр в gdiplusflat.h показывает, что все функции имеют стиль:

// 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...

Проблема заключается в том, что GpStatus является typedef для Status в GdiPlusGpStubs.h (заголовок С++), а Status сам является перечислением, определенным в GdiPlusTypes.h (также заголовке С++). Я пробовал самостоятельно определять enum, но по какой-то причине компилятор не принял его!

Итак... как точно использовать функции GDI + в C? Должен ли я просто загружать gdiplus.dll динамически?

Ответ 1

Проблема в том, что gdiplusflat.h действительно требуется гораздо больше gdi *.h заголовочных файлов, которые были включены до него. Но многие из этих файлов заголовков, которые имеют необходимые объявления typedef, на которые ссылается gdiplusflat.h, также содержат объявления "class" и другие ключевые слова С++. Компилятор C будет выходить из строя, когда видит эти строки.

У вас есть два варианта.

  • Простой. Примите тот факт, что С++ по существу является надмножеством C. Затем просто переименуйте свой ".c" файл, который вы пытаетесь скомпилировать, чтобы иметь расширение ".cpp". Ваш код C будет скомпилирован как С++, но, скорее всего, он не изменит строку кода, который вы пишете. Затем #include gdiplus.h перед вами #include gdiplusflat.h

  • Harder. зависит от определений typedef в других файлах заголовков. Проблема в том, что многие из этих заголовочных файлов имеют определения класса и ключевые слова С++, которые компилятор C будет выходить из строя. Вам придется вручную переносить многие объявления C в свой собственный заголовочный файл, который включается перед gdiplusflat.h. Вот моя слабая попытка. Это не совсем так. Он получает половину ошибок компиляции. Но я слишком устал и просто пошел с вариантом №1. Вы можете закончить его, но вариант 1 выше намного проще.

х

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>

Ответ 2

Вы можете использовать Плоский API из MSDN. Там прямое преобразование из Flat API (C) в GDI + (С++), я думаю, это довольно просто.

P.S: Однако вы все равно можете использовать GDI прямо в C.