我正在尝试将 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 );
}
};
这行不通。
一些(可能不正确的)附加信息
事实上,模块系统有一个称为“首次使用时导入”的功能。