Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > GDI+: подгрузка функций LoadLibrary(gdiplus.dll)


Автор: malor 7.7.2011, 20:24
Есть приложение, оно компилится.  В нем есть динамическая линковка GDI+:
HMODULE hGDIPlsu = LoadLibrary(_T("gdiplus.dll")); 

В хэдере объявлен структура для хранения адресов функций из "gdiplus.dll":
Код

typedef struct{
    Status (WINAPI *pfnGdiplusStartup)(ULONG_PTR*, const GdiplusStartupInput*, GdiplusStartupOutput*);
    VOID (WINAPI *pfnGdiplusShutdown)(ULONG_PTR);
    Status (WINAPI *pfnGetImageEncoders)(UINT, UINT, ImageCodecInfo*);
    Status (WINAPI *pfnGetImageEncodersSize)(UINT*, UINT*);
    Status (WINAPI *pfnGdipCreateBitmapFromScan0)(INT, INT, INT, PixelFormat, BYTE*, GpBitmap**);
    Status (WINAPI *pfnGdipBitmapLockBits)(GpBitmap*, const GpRect*, UINT, PixelFormat, BitmapData*);
    Status (WINAPI *pfnGdipBitmapUnlockBits)(GpBitmap*, BitmapData*);
    Status (WINAPI *pfnGdipSaveImageToFile)(GpImage*, const WCHAR*, const CLSID*, const EncoderParameters*);
    Image  (WINAPI *pfnGetThumbnailImage)(UINT, UINT, GetThumbnailImageAbort, VOID*);
    Status (WINAPI *pfnGdipCreateBitmapFromHBITMAP)(HBITMAP, HPALETTE, GpBitmap**);    
}DYN_DLLS, *LPDYN_DLLS;

В cpp-файле она заполняется нужными значениями:
Код
(FARPROC&)DynDlls.pfnGdiplusStartup = GetProcAddress(hGDIPlsu, "GdiplusStartup");
(FARPROC&)DynDlls.pfnGdiplusShutdown = GetProcAddress(hGDIPlsu, "GdiplusShutdown");
(FARPROC&)DynDlls.pfnGetImageEncoders = GetProcAddress(hGDIPlsu, "GdipGetImageEncoders");
(FARPROC&)DynDlls.pfnGetImageEncodersSize = GetProcAddress(hGDIPlsu, "GdipGetImageEncodersSize");
(FARPROC&)DynDlls.pfnGdipCreateBitmapFromScan0 = GetProcAddress(hGDIPlsu, "GdipCreateBitmapFromScan0");
(FARPROC&)DynDlls.pfnGdipBitmapLockBits = GetProcAddress(hGDIPlsu, "GdipBitmapLockBits");
(FARPROC&)DynDlls.pfnGdipBitmapUnlockBits = GetProcAddress(hGDIPlsu, "GdipBitmapUnlockBits");
(FARPROC&)DynDlls.pfnGdipSaveImageToFile = GetProcAddress(hGDIPlsu, "GdipSaveImageToFile");

Вставляю в него свой кусок кода, для сохранения скриншота в файл на диске:
Код
int Width, Height;
HDC scrdc, memdc;
HBITMAP membit;
scrdc  = GetDC(0);
Height = GetSystemMetrics(SM_CYSCREEN);
Width  = GetSystemMetrics(SM_CXSCREEN);
memdc  = CreateCompatibleDC(scrdc);
membit = CreateCompatibleBitmap(scrdc, Width, Height);
SelectObject(memdc, membit);
BitBlt(memdc, 0, 0, Width, Height, scrdc, 0, 0, SRCCOPY);
Bitmap *bmp = new Bitmap(membit, NULL);
Image  *img = bmp->GetThumbnailImage(Width, Height);
CLSID imgClsid;
EncoderParameters encoderParams;
int quality = 65;
encoderParams.Count = 1;
encoderParams.Parameter[0].Guid           = EncoderQuality;
encoderParams.Parameter[0].Type           = 4;
encoderParams.Parameter[0].NumberOfValues = 1;
encoderParams.Parameter[0].Value          = &quality;
GetEncoderClsid(L"image/jpeg", &imgClsid);
//result = img->Save(L"Z:\\ImageDesktop.jpeg", &imgClsid, &encoderParams);  
// САМЫЙ ГЛАВНЫЙ МОМЕНТ, НО ПОКА ЗАКОММЕНЧУ
//if (DynDlls.pfnGdipSaveImageToFile(img, L"Z:\\ImageDesktop.jpeg", &imgClsid, &encoderParams) == Ok)
//    bRes = TRUE;

delete bmp;
delete img;

DeleteObject(membit);
DeleteObject(memdc);
ReleaseDC(0, scrdc);

Начинают выдаваться компилятором следующие сообщения:
Цитата
error LNK2001: unresolved external symbol _EncoderQuality
GdiplusTest.obj : error LNK2019: unresolved external symbol _GdipFree@4 referenced in function "public: static void __cdecl Gdiplus::GdiplusBase::operator delete(void *)" (??3GdiplusBase@Gdiplus@@SAXPAX@Z)
error LNK2019: unresolved external symbol _GdipAlloc@4 referenced in function "public: static void * __cdecl Gdiplus::GdiplusBase::operator new(unsigned int)" (??2GdiplusBase@Gdiplus@@SAPAXI@Z)
error LNK2019: unresolved external symbol _GdipDisposeImage@4 referenced in function "public: class Gdiplus::Image * __thiscall Gdiplus::Image::GetThumbnailImage(unsigned int,unsigned int,int (__stdcall*)(void *),void *)" (?GetThumbnailImage@Image@Gdiplus@@QAEPAV12@IIP6GHPAX@Z0@Z)
error LNK2019: unresolved external symbol _GdipGetImageThumbnail@24 referenced in function "public: class Gdiplus::Image * __thiscall Gdiplus::Image::GetThumbnailImage(unsigned int,unsigned int,int (__stdcall*)(void *),void *)" (?GetThumbnailImage@Image@Gdiplus@@QAEPAV12@IIP6GHPAX@Z0@Z)
error LNK2019: unresolved external symbol _GdipCloneImage@8 referenced in function "public: virtual class Gdiplus::Image * __thiscall Gdiplus::Image::Clone(void)" (?Clone@Image@Gdiplus@@UAEPAV12@XZ)
error LNK2019: unresolved external symbol _GdipCreateBitmapFromHBITMAP@12 referenced in function "public: __thiscall Gdiplus::Bitmap::Bitmap(struct HBITMAP__ *,struct HPALETTE__ *)" (??0Bitmap@Gdiplus@@QAE@PAUHBITMAP__@@PAUHPALETTE__@@@Z)
.\Debug/GdiplusTest.exe : fatal error LNK1120: 7 unresolved externals
Нужно указанные компилятором функции 
GdipFree, GdipAlloc, GdipDisposeImage, GdipGetImageThumbnail, GdipCloneImage, GdipCreateBitmapFromHBITMAP 
прописать в структуре DYN_DLLS, расположенной в хэдере?

Автор: Vetos 9.7.2011, 22:44
Ну конечно нужно!

Автор: xvr 11.7.2011, 14:47
Цитата(malor @  7.7.2011,  20:24 Найти цитируемый пост)
Нужно указанные компилятором функции 
GdipFree, GdipAlloc, GdipDisposeImage, GdipGetImageThumbnail, GdipCloneImage, GdipCreateBitmapFromHBITMAP 
прописать в структуре DYN_DLLS, расположенной в хэдере?

Нет, их нужно написать в своей программе (раз уж вы взялись за животноводство, я имею в виду попытку скрестить ужа с ежом, точнее попытку динамически загрузить gdiplus)

ВСЕ классы из Gdp+ обращаются к функциям из gdiplus.dll, и функций этих вагон и маленькая тележка. Засунуть их в какую либо структуру не получится, т.к. сорцы Gdi+ (которые находятся в ее хидерах) о ваших намерениях не знают ни сном ни духом  smile 


Автор: Dem_max 11.7.2011, 15:12
а зачем изобретать велосипед ???
Вызов нативного кода уже предусмотрен. Достаточно вызвать функцию так:
Код

DllExports::GdipGetImageHeight(pImage, &ImgHeight);

Автор: xvr 11.7.2011, 15:15
Цитата(Dem_max @  11.7.2011,  15:12 Найти цитируемый пост)
Вызов нативного кода уже предусмотрен. Достаточно вызвать функцию так:

ТС нужно наоборот.  smile У него нет DllExports::*, а нужно сделать new Bitmap (который обязательно в эти самые DllExports::* полезет)

Автор: Dem_max 11.7.2011, 15:31
тогда ТС нужна статическая линковка GDIplus.lib

Автор: xvr 11.7.2011, 19:07
Цитата(Dem_max @ 11.7.2011,  15:31)
тогда ТС нужна статическая линковка GDIplus.lib

Вот и я тоже не понимаю, зачем ТС пытается родить ежа и сделать динамическую линковку с Gdi+  smile 

Автор: ASMatic 11.7.2011, 23:16
Цитата(Dem_max @  11.7.2011,  13:31 Найти цитируемый пост)
тогда ТС нужна статическая линковка GDIplus.lib 


Цитата(malor @  7.7.2011,  18:24 Найти цитируемый пост)
HMODULE hGDIPlsu = LoadLibrary(_T("gdiplus.dll")); 

разницу чувствуете?
ТС, хз как на тех плюсах делать подобное, но на си п1 должен был бы поехать..

Автор: xvr 12.7.2011, 08:00
Цитата(ASMatic @  11.7.2011,  23:16 Найти цитируемый пост)
разницу чувствуете?

Чувствуем, и пытаемся донести ее до ТС  smile 
Цитата(ASMatic @  11.7.2011,  23:16 Найти цитируемый пост)
ТС, хз как на тех плюсах делать подобное, но на си п1 должен был бы поехать.. 

п1 имеется в виду 'статическая линковка'? Если да, то на плюсах это тоже замечательно поедет. (Кстати - на С это не 'поедет' - Gdi+ это С++ библиотека  smile , ее в С программе использовать затруднительно)

2 ТС - озвучь, пожалуйста, зачем тебе именно динамическая загрузка Gdi+? Может есть какие нибудь более безболезненные пути сделать то же самое?


Автор: ASMatic 12.7.2011, 21:06
Цитата(xvr @  12.7.2011,  06:00 Найти цитируемый пост)
? Если да, то на плюсах это тоже замечательно поедет. (Кстати - на С это не 'поедет' - Gdi+ это С++ библиотека   , ее в С программе использовать затруднительно)

не пойму - то не поедет, то затруднительно smile 
а по поводу си - тут интерфейсы "спокойно" юзаются, не то чтобы с++ библиотека,)

Цитата(xvr @  12.7.2011,  06:00 Найти цитируемый пост)
имеется в виду 'статическая линковка'

в первом посту ТС пытается создать прототипы и получить адрес функи, ну и "запушать" аргументы функе, соответственно объявленому прототипу = без труда это все делается на СИ, как на тех плюсах зло**их = хз)

Автор: xvr 13.7.2011, 09:01
Цитата(ASMatic @  12.7.2011,  21:06 Найти цитируемый пост)
а по поводу си - тут интерфейсы "спокойно" юзаются,

Там не интерфейсы, там полноценные классы, увы  smile 
Цитата(ASMatic @  12.7.2011,  21:06 Найти цитируемый пост)
в первом посту ТС пытается создать прототипы и получить адрес функи, ну и "запушать" аргументы функе, соответственно объявленому прототипу = без труда это все делается на СИ,  

Это он сделал, и наступил на то, чего не сделал  smile Его (не к ночи будь упомятут) GdiPlus::Bitset лезет во внутренности gdiplus.dll напрямую, и чихать он хотел на все перенаправления ТС  smile 

Автор: ASMatic 13.7.2011, 14:08
Цитата(xvr @  13.7.2011,  07:01 Найти цитируемый пост)
полноценные классы, увы

юзается хоть на асм...

Цитата(xvr @  13.7.2011,  07:01 Найти цитируемый пост)
Это он сделал, и наступил на то, чего не сделал 

одно из тех почему не юзаем с++

вообщето как понимаю >GdiPlus::Bitset лезет во внутренности gdiplus.dll<  лезет туда только через vtable[] , т.е. при инициализации нам возвращается таблица с адресочками и компиль уже себе этими адресами оперирует, т.к. при компиляции никто не знает где именно в длл окажется GdiPlus::Bitset

Автор: Dem_max 13.7.2011, 18:33
если не использовать классы GDI+ то нужно вызывать нативный API (DllExports::GdipGetImageHeight(pImage, &ImgHeight);) только при этом не нужно вызывать DLL динамически, а просто слинковать статически и не иметь геморроя.

Автор: xvr 13.7.2011, 20:07
Цитата(ASMatic @  13.7.2011,  14:08 Найти цитируемый пост)
юзается хоть на асм...

Неа, там исходные тексты на С++. Их можно выбросить и написать свое, на С, но заюзать напрямую из С нельзя - ну не понимает С компилятор С++ исходников  smile 

Цитата(ASMatic @  13.7.2011,  14:08 Найти цитируемый пост)
вообщето как понимаю >GdiPlus::Bitset лезет во внутренности gdiplus.dll<  лезет туда только через vtable[]

Нет, он лезет во внутренности DllExports::*, причем это явно написано в коде. Ну вот, например:
Код

inline 
Bitmap::Bitmap(
    IN const WCHAR *filename, 
    IN BOOL useEmbeddedColorManagement
    )
{
    GpBitmap *bitmap = NULL;

    if(useEmbeddedColorManagement) 
    {
        lastResult = DllExports::GdipCreateBitmapFromFileICM(filename, &bitmap);
    }
    else
    {
        lastResult = DllExports::GdipCreateBitmapFromFile(filename, &bitmap);
    }

    SetNativeImage(bitmap);
}

и все остальное в том же духе. (Это кусок заголовочного файла из Gdi+, конкретно GdiPlusBitmap.h)

Автор: ASMatic 14.7.2011, 02:49
xvr, исходные тексты, inline - никогда не высматривал чо там именно в gdi+. Теперь все на своих местах, сенкс)
ТС пишите свои обёртки  smile

Автор: xvr 14.7.2011, 08:39
2 ТС, в порядке телепатии. Если вы делаете динамическую загрузку для того, что бы программа могла работать и без Gdi+, то это делается гораздо проще. Пишете свою dll с функцией CreateSnapshort (или как она у вас там называется), ее собираете статически с dll Gdi+, а уж ее саму (вашу dll) грузите динамически. Т.к. у вас оттуда торчит только одна plain C функция, то никаких проблем с загрузкой вашей dll не предвидится


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)