gpt4 book ai didi

c++ - RenderTarget->GetSize 不工作

转载 作者:行者123 更新时间:2023-11-30 03:57:34 26 4
gpt4 key购买 nike

为了学习我自己的 Direct2D,我正在关注 this example来自 MSDN。

但是我有一个问题。调用 D2D1_SIZE_F rtSize = m_pRenderTarget->GetSize(); 始终返回大小 0,0,并且在调试器中导致 DrawLine 调用异常。如果我省略 GetSize() 调用并使用有效值填充 D2D1_SIZE_F 结构,它就可以工作。

初始化渲染目标的相关代码为:

    RECT rc;
GetClientRect(m_hwnd, &rc);

D2D1_SIZE_U size = D2D1::SizeU(
rc.right - rc.left,
rc.bottom - rc.top
);

// Create a Direct2D render target.
hr = m_pDirect2dFactory->CreateHwndRenderTarget(
D2D1::RenderTargetProperties(),
D2D1::HwndRenderTargetProperties(m_hwnd, size),
&m_pRenderTarget
);

我已经通过调试器验证过有效值的大小。

调用GetSize的绘图代码部分:

    m_pRenderTarget->BeginDraw();

m_pRenderTarget->SetTransform(D2D1::Matrix3x2F::Identity());

m_pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::White));
D2D1_SIZE_F rtSize = m_pRenderTarget->GetSize();
// Draw a grid background.
int width = static_cast<int>(rtSize.width);
int height = static_cast<int>(rtSize.height);

for (int x = 0; x < width; x += 10)
{
m_pRenderTarget->DrawLine(
D2D1::Point2F(static_cast<FLOAT>(x), 0.0f),
D2D1::Point2F(static_cast<FLOAT>(x), rtSize.height),
m_pLightSlateGrayBrush,
0.5f
);
}

所以我的问题是为什么 GetSize() 会返回 0,0 并在稍后导致 AV?

顺便说一句:我正在使用:Windows 7 旗舰版 64 位代码:: block IDETDM-GCC-64 gcc编译器v4.8.1我在 Unicode 模式下编译 #define UNICODE无论我编译为 32 位还是 64 位,都会出现问题(是的,我对 64 位模式做了一些小调整,以确保我有一个指向 WndProc 中应用程序对象的有效指针)

最佳答案

Why does GetSize() return 0,0 and causes an AV later on?

因为 GCC/MinGW-W64 生成的 GetSize 调用与 d2d1.dll 中实现的调用约定不匹配。 GetSize 的返回类型 D2D_SIZE_F 是一个结构体。根据Microsoft Docs有两种方法可以从函数返回结构:

User-defined types can be returned by value from global functions and static member functions. To return a user-defined type by value in RAX, it must have a length of 1, 2, 4, 8, 16, 32, or 64 bits. It must also have no user-defined constructor, destructor, or copy assignment operator. It can have no private or protected non-static data members, and no non-static data members of reference type. It can't have base classes or virtual functions. And, it can only have data members that also meet these requirements. (This definition is essentially the same as a C++03 POD type. Because the definition has changed in the C++11 standard, we don't recommend using std::is_pod for this test.) Otherwise, the caller must allocate memory for the return value and pass a pointer to it as the first argument.

当 GCC/MinGW-W64 编译文章中的示例代码时,调用者仅为调用 GetSize 设置一个参数(在 rcx 中),并期望在 rax:

# AT&T syntax (destination operand last)
mov 0x10(%rbx),%rcx # rcx <- pointer to IRenderContext
mov (%rcx),%rax # rax <- pointer to virtual function table
callq *0x1a8(%rax) # virtual function call (expect result in rax)

在 Visual Studio 生成的代码中,调用者在调用 GetSize 之前将 rdx 设置为指向堆栈上的某个位置:

# Intel syntax (destination operand first)
mov rax,qword ptr [rsp+168h] # rax <- pointer to IRenderContext
mov rax,qword ptr [rax] # rax <- pointer to virtual function table
lea rdx,[rsp+68h] # rdx <- address of return value (hidden argument)
mov rcx,qword ptr [rsp+168h] # rcx <- this pointer (hidden argument)
call qword ptr [rax+1A8h] # virtual function call (expect result at [rdx])

在 GCC/MinGW-W64 上,rdx 中的值不是有效地址,因此当 GetSize 的实现尝试将返回值存储在内存中时,会发生访问冲突。

D2D_SIZE_F 是一个 64 位 POD 结构(只是两个 float 的结构),所以在我看来 GCC 在 rax 寄存器中返回它是正确的.我不知道是什么让 Visual Studio 使用指针返回,恐怕也不知道如何让 GCC 为兼容性做同样的事情。

关于c++ - RenderTarget->GetSize 不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27888109/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com