如何(方便地)在 C++ 模块中使用 DirectX 库和函数?

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

我正在尝试将 C++ 模块用于 DirectX 12 图形引擎。我尝试使用像

CreateDXGIFactory2
这样的简单 API 调用,但该函数失败了;它返回一个
E_NOINTERFACE
返回码。

这是一个简单的程序示例。

Factory.ixx

module;
#include <dxgi1_6.h>
#include <wrl.h>
#include <cassert>
#pragma comment(lib, "dxgi")

export module Factory;

using namespace Microsoft::WRL;

export class Factory
{
    ComPtr<IDXGIFactory7> pFactory {};

    public:

    Factory() noexcept
    {
        HRESULT HResult { S_OK };
        HResult = CreateDXGIFactory2( DXGI_CREATE_FACTORY_DEBUG, IID_PPV_ARGS( &pFactory ) );
        assert( HResult == S_OK );
    }
};

Main.cpp

#include <cstdint>
#include <d3d12.h>
#include <dxgi1_6.h>
import Factory;

uint32_t main( void )
{
    Factory factory {};
    return 0;
}

这将构建,但断言失败。在调试中,HResult 的值恰好是

E_NOINTERFACE
。在我的测试中,模块文件似乎没有从库中加载符号。我已经尝试了很多东西,其中一些我觉得我现在已经忘记了,所以这里有一个不那么详尽的列表,没有特定的顺序:

  • 使用模块定义文件。

您可以使用 .def 文件导出库的符号/属性(?)。这是我为测试这个而制作的 .def 文件的文本:

EXPORTS
    CreateDXGIFactory2=dxgi.lib

不幸的是,这没有用。链接器返回

LNK1120: unresolved external symbol dll
的错误。我也尝试使用绝对路径,但是 Windows SDK 路径的“10.0.___”部分在解析过程中混淆了链接器……继续。

  • 使用来自源文件的虚拟调用来强制加载符号。

这个方法确实有效。如果我以这种方式改变

Main.cpp

#include <cstdint>
#include <d3d12.h>
#include <dxgi1_6.h>
#include <wrl.h>
import Factory;
using namespace Microsoft::WRL;
uint32_t main( void )
{
    HRESULT hr = CreateDXGIFactory2( DXGI_CREATE_FACTORY_DEBUG, IID_PPV_ARGS( &ComPtr<IDXGIFactory7>() ) );
    Factory factory {};
    return 0;
}

符号将在运行时加载并在

Factory.ixx
文件中可用;也就是说,
CreateDXGIFactory2
函数将在
S_OK
构造函数中返回一个
Factory
并且
pFactory
指针将有一个地址。但是,我希望有比这更好的方法,因为将我将使用的所有功能从
dxgi.lib
和其他库放入源文件听起来既乏味又缓慢。

  • 使用强制加载链接器选项。

关键是要在链接器中包含以下命令行:

/WHOLEARCHIVE:dxgi.lib
。虽然这个 does 构建,即使在全局模块部分没有
#pragma comment(lib, "dxgi.lib")
,函数
CreateDXGIFactory2
仍然返回一个讨厌的
E_NOINTERFACE
结果。此解决方案的另一个问题是,当以这种方式强制加载多个库时,您会得到重复的符号。这有它自己的解决方案,即定义一个默认库以更喜欢来自的符号;例如
/DEFAULTLIB:d3d12.lib
,但这并没有解决多个符号问题,而且绝对仍然没有解决
CreateDXGIFactory2
功能。

  • 使用
    import
    而不是
    #include

显然,导入仅适用于模块,不适用于库。我不知道为什么 ChatGPT 继续告诉我这样做。

  • dxgi.lib
    添加到您的附加依赖项中。

Windows SDK 中包含的库默认已链接。因此,显式地将库添加为依赖项并不能解决错误。

  • 使用
    IDXGIFactory
    的更高接口。

如果

CreateDXGIFactory2
函数可以使用
IDXGIFactory7
版本的接口正确调用源文件,那么模块也应该能够。无论如何,这是行不通的。

  • 完全倒转时间并使用旧版本的
    dxgi
    标头。
module;
#include <dxgi.h>
#include <wrl.h>
#include <cassert>
#pragma comment(lib, "dxgi.lib")

export module Factory;

using namespace Microsoft::WRL;

export class Factory
{
    ComPtr<IDXGIFactory> pFactory {};

    public:

    Factory() noexcept
    {
        HRESULT HResult { S_OK };
        HResult = CreateDXGIFactory( IID_PPV_ARGS( &pFactory ) );
        assert( HResult == S_OK );
    }
};

这行不通。

一些(可能不正确的)附加信息

事实上,模块系统有一个称为“首次使用时导入”的功能。

c++ directx c++20 linker-errors c++-modules
© www.soinside.com 2019 - 2024. All rights reserved.