com — переменная _vfptr C ++ Direct2D ID2D1HwndRenderTarget родительского класса IUnknown становится нулевой

У меня есть приложение Direct2D, которое я делаю, и я пишу библиотеку Direct2D, которая также облегчает мне использование Direct2D. Я опубликую точный проблемный код, если мне нужно, но моя главная проблема в том, что у меня есть ID2D1HwndRenderTarget в определении одного класса, я расширяю этот класс другим классом, в дочернем классе у меня есть метод, который вызывает метод родительского класса, который инициализирует цель рендеринга, а затем, в свою очередь, вызывает метод load дочернего класса. Однако, как только программа достигает метода загрузки содержимого дочернего класса, переменная __vfptr (я понятия не имею, что это) в части IUnknown ID2D1HwndRenderTarget теперь становится нулевой. Единственная причина, по которой я понял это, заключается в том, что в другом коде я получал ошибку нарушения доступа при использовании цели рендеринга для создания ID2D1Bitmap из IWicBitmapSource. Я не понимаю, как это происходит, потому что после инициализации цели рендеринга эта переменная _vfptr становится нулевой, как только возвращается метод с кодом инициализации. Кто-нибудь может объяснить, почему это может происходить? Мой соответствующий код ниже.

Этот код вызывается один раз для создания цели рендеринга hwnd и цели рендеринга за пределами экрана. Это в проекте DLL.
GameBase.cpp

HRESULT GameBase::Initialize(HINSTANCE hInst, HWND winHandle, struct DX2DInitOptions options)
{
this->mainRenderTarget = NULL;
this->offscreenRendTarget = NULL;
this->factory = NULL;

HRESULT result;

D2D1_FACTORY_OPTIONS factOptions;
D2D1_FACTORY_TYPE factType;

if(options.enableDebugging)
factOptions.debugLevel = D2D1_DEBUG_LEVEL::D2D1_DEBUG_LEVEL_ERROR;
else
factOptions.debugLevel = D2D1_DEBUG_LEVEL::D2D1_DEBUG_LEVEL_NONE;

if(options.singleThreadedApp)
factType = D2D1_FACTORY_TYPE_SINGLE_THREADED;
else
factType = D2D1_FACTORY_TYPE_MULTI_THREADED;

result = D2D1CreateFactory(factType, factOptions, &this->factory);

if(FAILED(result))
{
OutputDebugString(L"Failed to create a Direct 2D Factory!");
return result;
}

this->instance = hInst;
this->hwnd = winHandle;

D2D1_SIZE_U size = D2D1::SizeU(options.winWidth, options.winHeight);

this->width = options.winWidth;
this->height = options.winHeight;

result = factory->CreateHwndRenderTarget(D2D1::RenderTargetProperties(), D2D1::HwndRenderTargetProperties(winHandle, size), &this->mainRenderTarget);

if(FAILED(result))
{
OutputDebugString(L"Failed to create a render target to draw to the window with!");
return result;
}

result = this->mainRenderTarget->CreateCompatibleRenderTarget(&this->offscreenRendTarget);
if(FAILED(result))
{
OutputDebugString(L"Failed to create an offscreen render target from the main render target.");
return result;
}

return LoadContent();
}

После вызова LoadContent я ни разу не изменил значение mainRenderTarget.

DX2DImage.cpp

HRESULT DX2DImageLoader::LoadFromResource(LPCWSTR resourceName, LPCWSTR resourceType, HMODULE progModule, DX2DImage* image)
{
if(!this->isInit)
{
OutputDebugStringA("You must call InitializeImageLoader before using this image loader!");
return E_FAIL;
}

IWICBitmapDecoder *decoder = NULL;
IWICBitmapFrameDecode *source = NULL;
IWICStream *stream = NULL;
IWICFormatConverter *converter = NULL;

HRSRC imageResHandle = NULL;
HGLOBAL imageResDataHandle = NULL;
void *imageFile = NULL;
DWORD imageFileSize = 0;

HRESULT result;//Find the image.
imageResHandle = FindResource(progModule, resourceName, resourceType);
if(!imageResHandle)
{
OutputDebugStringA("Failed to get a handle to the resource!");
return E_FAIL;
}
//Load the data handle of the image.
imageResDataHandle = LoadResource(progModule, imageResHandle);
if(!imageResDataHandle)
{
OutputDebugStringA("Failed to load the image from the module!");
return E_FAIL;
}
//Lock and retrieve the image.
imageFile = LockResource(imageResDataHandle);
if(!imageFile)
{
OutputDebugStringA("Failed to lock the image in the module!");
return E_FAIL;
}
//Get the size of the image.
imageFileSize = SizeofResource(progModule, imageResHandle);
if(!imageFileSize)
{
OutputDebugStringA("Failed to retrieve the size of the image in the module!");
return E_FAIL;
}
//Create a stream that will read the image data.
result = this->factory->CreateStream(&stream);
if(FAILED(result))
{
OutputDebugStringA("Failed to create an IWICStream!");
return result;
}
//Open a stream to the image.
result = stream->InitializeFromMemory(reinterpret_cast<BYTE*>(imageFile), imageFileSize);
if(FAILED(result))
{
OutputDebugStringA("Failed to initialize the stream!");
return result;
}
//Create a decoder from the stream
result = this->factory->CreateDecoderFromStream(stream, NULL, WICDecodeMetadataCacheOnDemand, &decoder);
if(FAILED(result))
{
OutputDebugStringA("Failed to create a decoder from the stream!");
return result;
}
//Get the first frame from the image.
result = decoder->GetFrame(0, &source);
if(FAILED(result))
{
OutputDebugStringA("Failed to get the first frame from the decoder!");
return result;
}
//Create a format converter to convert image to 32bppPBGRA
result = this->factory->CreateFormatConverter(&converter);
if(FAILED(result))
{
OutputDebugStringA("Failed to create a format converter!");
return result;
}
//Convert the image to the new format.
result = converter->Initialize(source, GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, NULL, 0.0f, WICBitmapPaletteTypeMedianCut);
if(FAILED(result))
{
OutputDebugStringA("Failed to convert the image to the correct format!");
return result;
}

//Create the Direct2D Bitmap from the Wic Bitmap.
result = this->renderTarget->CreateBitmapFromWicBitmap(converter, NULL, &image->bitmap);
if(FAILED(result))
{
OutputDebugStringA("Failed to create a Direct 2D Bitmap from a WIC Bitmap!");
return result;
}

image->width = static_cast<UINT>(image->bitmap->GetSize().width);
image->height = static_cast<UINT>(image->bitmap->GetSize().height);

SafeRelease(&source);
SafeRelease(&converter);
SafeRelease(&decoder);
SafeRelease(&stream);

return S_OK;
}

Исключение нарушения доступа происходит на линии

result = this->renderTarget->CreateBitmapFromWicBitmap(converter, NULL, &image->bitmap);

где image-> bitmap — это текущий NULL (как и должно быть) ID2D1Bitmap.

Здесь переменная renderTarget — это та же переменная mainRenderTarget, что и в GameBase.cpp выше. Когда я отлаживаю строку, все родительские объекты RenderTarget не равны NULL, однако, как только я доберусь до интерфейса IUnknown под всем этим, _vfptr будет иметь значение NULL. Это не относится к переменной преобразователя, этой переменной или переменной изображения.

0

Решение

У меня недостаточно кода для отладки вашего кода, но из того, что я вижу, я подозреваю, что вызов converter->Initialize(...) быть недействительным с MSDN сказать:

If you do not have a predefined palette, you must first create one. Use
InitializeFromBitmap to create the palette object, then pass it in along
with your other parameters.

dither, pIPalette, alphaThresholdPercent, and paletteTranslate are used to
mitigate color loss when converting to a reduced bit-depth format. For
conversions that do not need these settings, the following parameters values
should be used: dither set to WICBitmapDitherTypeNone, pIPalette set to NULL,
alphaThresholdPercent set to 0.0f, and paletteTranslate set to
WICBitmapPaletteTypeCustom.

И в вашем коде вы не предоставляете действительный поддон (вы использовали NULL) и ваш paletteTranslate не является WICBitmapPaletteTypeCustom

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]