Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Ez a témakör bemutatja, hogyan portolhatja Windows-futtatókörnyezet C++ sablontár (WRL) kódját a C++/WinRT-ben lévő megfelelőjéhez.
A C++/WinRT-hez való portolás első lépése a C++/WinRT támogatás manuális hozzáadása a projekthez (lásd Visual Studio C++/WinRT-támogatás). Ehhez telepítse a Microsoft.Windows. CppWinRT NuGet-csomag a projektbe. Nyissa meg a projektet a Visual Studióban, kattintson a Project>Manage NuGet Packages...>Tallózás elemre, írja be vagy illessze be a Microsoft.Windows.CppWinRT szöveget a keresőmezőbe, jelölje ki az elemet a keresési eredmények között, majd kattintson a Telepítés gombra a csomag projekthez való telepítéséhez. A változás egyik hatása, hogy a C++/CX támogatása ki van kapcsolva a projektben. Ha C++/CX-et használ a projektben, akkor kikapcsolhatja a támogatást, és a C++/CX-kódot C++/WinRT-re is frissítheti (lásd: Áthelyezés C++/WinRT-re a C++/CX-ről). Vagy visszakapcsolhatja a támogatást (a projekttulajdonságokban a C/C++>General>Consume Windows-futtatókörnyezet Extension>Yes (/ZW)), és először a WRL-kód portolására összpontosíthat. A C++/CX és a C++/WinRT kód együtt létezhet ugyanabban a projektben, kivéve az XAML fordítótámogatást, valamint Windows-futtatókörnyezet összetevőket (lásd: Áthelyezés C++/WinRT-ra C++/CX-ről).
Állítsa a projekt Általános>Célplatform verziója tulajdonságát 10.0.17134.0-ra (Windows 10, 1803-as verzió) vagy újabb verzióra.
Az előre lefordított fejlécfájlban (általában pch.h) vegye fel az winrt/base.h elemet.
#include <winrt/base.h>
Ha bármilyen C++/WinRT által kivetített Windows API-fejlécet beilleszt (például winrt/Windows.Foundation.h), akkor nem kell külön beillesztenie a(z) winrt/base.h elemet, mert az automatikusan be lesz illesztve.
WRL COM intelligens mutatóinak portolása (Microsoft::WRL::ComPtr)
Módosítson minden olyan kódot, amely Microsoft::WRL::ComPtr<T> típust használ, úgy, hogy winrt::com_ptr<T> típust használjon. Íme egy kód előtti és utáni példa. Az utána verzióban a com_ptr::put tagfüggvény lekéri a mögöttes nyers mutatót, hogy be lehessen állítani.
ComPtr<IDXGIAdapter1> previousDefaultAdapter;
DX::ThrowIfFailed(m_dxgiFactory->EnumAdapters1(0, &previousDefaultAdapter));
winrt::com_ptr<IDXGIAdapter1> previousDefaultAdapter;
winrt::check_hresult(m_dxgiFactory->EnumAdapters1(0, previousDefaultAdapter.put()));
Fontos
Ha van egy winrt::com_ptr, amely már be van állítva (a belső nyers mutatója már egy célobjektumra mutat), és át szeretné állítani, hogy egy másik objektumra mutasson, akkor először a nullptr értéket kell hozzárendelnie — ahogy az alábbi kódpéldában is látható. Ha nem, akkor egy már beállított com_ptr felhívja a figyelmet a problémára (amikor meghívja a com_ptr::put vagy a com_ptr::put_void függvényt) azzal, hogy ellenőrzi, hogy a belső mutatója nem null értékű.
winrt::com_ptr<IDXGISwapChain1> m_pDXGISwapChain1;
...
// We execute the code below each time the window size changes.
m_pDXGISwapChain1 = nullptr; // Important because we're about to re-seat
winrt::check_hresult(
m_pDxgiFactory->CreateSwapChainForHwnd(
m_pCommandQueue.get(), // For Direct3D 12, this is a pointer to a direct command queue, and not to the device.
m_hWnd,
&swapChainDesc,
nullptr,
nullptr,
m_pDXGISwapChain1.put())
);
Ebben a következő példában (az after verzióban) a com_ptr::put_void tagfüggvény a mögöttes nyers mutatót void mutatóra mutató mutatóként kéri le.
ComPtr<ID3D12Debug> debugController;
if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController))))
{
debugController->EnableDebugLayer();
}
winrt::com_ptr<ID3D12Debug> debugController;
if (SUCCEEDED(D3D12GetDebugInterface(__uuidof(debugController), debugController.put_void())))
{
debugController->EnableDebugLayer();
}
ComPtr::Get with com_ptr::get.
m_d3dDevice->CreateDepthStencilView(m_depthStencil.Get(), &dsvDesc, m_dsvHeap->GetCPUDescriptorHandleForHeapStart());
m_d3dDevice->CreateDepthStencilView(m_depthStencil.get(), &dsvDesc, m_dsvHeap->GetCPUDescriptorHandleForHeapStart());
Ha a mögöttes nyers mutatót egy olyan függvénynek szeretné átadni, amely az IUnknown függvényre vár, használja a winrt::get_unknown szabad függvényt, ahogyan az a következő példában is látható.
ComPtr<IDXGISwapChain1> swapChain;
DX::ThrowIfFailed(
m_dxgiFactory->CreateSwapChainForCoreWindow(
m_commandQueue.Get(),
reinterpret_cast<IUnknown*>(m_window.Get()),
&swapChainDesc,
nullptr,
&swapChain
)
);
// Note: In a WinUI 3 desktop app, use CreateSwapChainForHwnd instead of
// CreateSwapChainForCoreWindow, since WinUI 3 doesn't use CoreWindow.
winrt::agile_ref<winrt::Windows::UI::Core::CoreWindow> m_window;
winrt::com_ptr<IDXGISwapChain1> swapChain;
winrt::check_hresult(
m_dxgiFactory->CreateSwapChainForCoreWindow(
m_commandQueue.get(),
winrt::get_unknown(m_window.get()),
&swapChainDesc,
nullptr,
swapChain.put()
)
);
WRL-modul portolása (Microsoft::WRL::Module)
Ez a szakasz a Microsoft::WRL::Module típust használó portolókódra vonatkozik.
Fokozatosan hozzáadhat C++/WinRT-kódot egy meglévő projekthez, amely a WRL használatával implementál egy összetevőt, és a meglévő WRL-osztályok továbbra is támogatottak lesznek. Ez a szakasz bemutatja, hogyan.
Ha egy új Windows-futtatókörnyezet-összetevő (C++/WinRT) projekttípust hoz létre a Visual Studio, és létrehozza, a rendszer létrehozza a fájltGenerated Files\module.g.cpp. Ez a fájl két hasznos C++/WinRT függvény definícióit tartalmazza (alább látható), amelyeket másolhat és hozzáadhat a projekthez. Ezek a függvények WINRT_CanUnloadNow és WINRT_GetActivationFactory , és amint látható, feltételesen meghívják a WRL-t, hogy támogassák a portolás bármely szakaszát.
HRESULT WINRT_CALL WINRT_CanUnloadNow()
{
#ifdef _WRL_MODULE_H_
if (!::Microsoft::WRL::Module<::Microsoft::WRL::InProc>::GetModule().Terminate())
{
return S_FALSE;
}
#endif
if (winrt::get_module_lock())
{
return S_FALSE;
}
winrt::clear_factory_cache();
return S_OK;
}
HRESULT WINRT_CALL WINRT_GetActivationFactory(HSTRING classId, void** factory)
{
try
{
*factory = nullptr;
wchar_t const* const name = WINRT_WindowsGetStringRawBuffer(classId, nullptr);
if (0 == wcscmp(name, L"MoveFromWRLTest.Class"))
{
*factory = winrt::detach_abi(winrt::make<winrt::MoveFromWRLTest::factory_implementation::Class>());
return S_OK;
}
#ifdef _WRL_MODULE_H_
return ::Microsoft::WRL::Module<::Microsoft::WRL::InProc>::GetModule().GetActivationFactory(classId, reinterpret_cast<::IActivationFactory**>(factory));
#else
return winrt::hresult_class_not_available().to_abi();
#endif
}
catch (...) { return winrt::to_hresult(); }
}
Ha már rendelkezik ezekkel a függvényekkel a projektben, a Modul::GetActivationFactory közvetlen meghívása helyett hívja meg WINRT_GetActivationFactory (amely belsőleg meghívja a WRL függvényt). Íme egy kód előtti és utáni példa.
HRESULT WINAPI DllGetActivationFactory(_In_ HSTRING activatableClassId, _Out_ ::IActivationFactory **factory)
{
auto & module = Microsoft::WRL::Module<Microsoft::WRL::InProc>::GetModule();
return module.GetActivationFactory(activatableClassId, factory);
}
HRESULT __stdcall WINRT_GetActivationFactory(HSTRING activatableClassId, void** factory);
HRESULT WINAPI DllGetActivationFactory(_In_ HSTRING activatableClassId, _Out_ ::IActivationFactory **factory)
{
return WINRT_GetActivationFactory(activatableClassId, reinterpret_cast<void**>(factory));
}
Module::Terminate közvetlen meghívása helyett hívja meg a(z) WINRT_CanUnloadNow függvényt (amely belsőleg a WRL függvényt hívja meg). Íme egy kód előtti és utáni példa.
HRESULT __stdcall DllCanUnloadNow(void)
{
auto &module = Microsoft::WRL::Module<Microsoft::WRL::InProc>::GetModule();
HRESULT hr = (module.Terminate() ? S_OK : S_FALSE);
if (hr == S_OK)
{
hr = ...
}
return hr;
}
HRESULT __stdcall WINRT_CanUnloadNow();
HRESULT __stdcall DllCanUnloadNow(void)
{
HRESULT hr = WINRT_CanUnloadNow();
if (hr == S_OK)
{
hr = ...
}
return hr;
}
Microsoft::WRL::Wrappers burkolóosztályok átültetése
Ez a szakasz az olyan kód portolására vonatkozik, amely a Microsoft::WRL::Wrappers burkolóit használja.
Ahogy az alábbi táblázatban látható, a szálkezelő segédek cseréjéhez javasoljuk, hogy használja a Standard C++ száltámogatási kódtárat. A WRL-wraperek egy az egyben való megfeleltetése félrevezető lehet, mert a választás az Ön igényeitől függ. Emellett bizonyos, nyilvánvalónak tűnő leképezések újak a C++20 szabványhoz, ezért ezek nem lesznek praktikusak, ha még nem frissített.
| Típus | Portolási megjegyzések |
|---|---|
| CriticalSection osztály | A száltámogatási kódtár használata |
| Eseményosztály (WRL) | A winrt::event struct sablon használata |
| HandleT osztály | A winrt::handle struct vagy a winrt::file_handle struct használata |
| HString osztály | Használja a winrt::hstring struct |
| HStringReference osztály | Nincs csere, mert a C++/WinRT úgy kezeli ezt belsőleg, hogy ugyanolyan hatékony legyen, mint a HStringReference , azzal az előnnyel, hogy nem kell gondolni rá. |
| Mutex-osztály | A száltámogatási kódtár használata |
| RoInitializeWrapper osztály | Használja a winrt::init_apartment és a winrt::uninit_apartment függvényt; vagy írjon saját egyszerű burkolófüggvényt a CoInitializeEx és a CoUninitialize függvények köré. |
| Semaphore osztály | A száltámogatási kódtár használata |
| SRWLock osztály | A száltámogatási kódtár használata |
Fontos API-k
Kapcsolódó témakörök
Windows developer