Direct2D Clear/DrawBitmap 抛出异常

问题描述 投票:0回答:1

在 C++ DLL 中,我初始化了 Direct2D,然后初始化了一些绘制函数。当调用

pRenderTarget->Clear(...)
时,它会抛出 AccessViolationException(尝试访问受保护的内存...)。

这是示例:

初始化 Direct2D
DLL_EXPORT void Direct2D_Init(HWND _hwnd, UINT width, UINT height)
{
    D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pD2DFactory);

    // Create WIC factory
    HRESULT hr = CoCreateInstance(CLSID_WICImagingFactory, nullptr, CLSCTX_INPROC_SERVER,
        IID_IWICImagingFactory, reinterpret_cast<void**>(&g_pWICFactory));
    if (FAILED(hr))
    {
        // Handle error
        return;
    }

// Create a render target
    D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties(
        D2D1_RENDER_TARGET_TYPE_DEFAULT, D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED));
    pD2DFactory->CreateHwndRenderTarget(props, D2D1::HwndRenderTargetProperties(_hwnd, D2D1::SizeU(width, height)), &pRenderTarget);
}

// Exception is thrown when invoking this:
DLL_EXPORT void Direct2D_Clear()
{
    pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::White));
}
在 C# 代码中,调用是这样完成的:
[DllImport(".\\d2dlib.dll")]
static extern void Direct2D_Clear();
        
public void Begin()
{
    if (renderOption == RenderOption.Direct2D)
    { 
        Direct2D_Clear(); // System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'
    }
    else
        ...
}         

可能出了什么问题?这看起来很不寻常。

小更新

直接在C++中运行绘图循环似乎没有问题。这似乎是有效的:

// The same init method as already displayed
Direct2D_Init(hWnd, 800, 600);
while (true)
{
    pRenderTarget->BeginDraw();
    pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::CornflowerBlue));
    pRenderTarget->EndDraw();
}

^ This was rendered out onto a CreateWindow result

在 C# 程序的上下文之外,我相信这可能就是我编写 DLL 的方式。 DLL 和 C# 程序都编译为 x64。或者关于 PInvoke 的东西。

c++ pinvoke direct2d rendertarget
1个回答
0
投票

问题出在窗口创建上,正如所建议的那样。当我创建 WinForm 窗口并使用其句柄时,会导致此异常。我在应用此方法来获取窗口时发现了这一点:

if (RewBatch.renderOption == RenderOption.Direct2D || RewBatch.renderOption == RenderOption.Both)
{
    Process proc = Process.Start(".\\TestBed.exe");
    START:
    if (proc.MainWindowHandle == IntPtr.Zero)
    {
        Task.WaitAll(Task.Delay(100));
        proc.Refresh();
        goto START;
    }
    Direct2D_InitEx(handle = proc.MainWindowHandle, (uint)window.Width, (uint)window.Height);
}

我创建了一个具有特定窗口尺寸的 CPP 应用程序,并使用该窗口的句柄。这是一个基本的解决方案。我不太确定为什么 WinForms 尝试停止工作,但我一直在对敏感代码进行大量更新。

© www.soinside.com 2019 - 2024. All rights reserved.