这在某种程度上是如何使用 midlrt.exe 将 .idl 编译为 .winmd 的后续内容?
我的 CMakeLists.txt 中有这个。我的问题不是关于 CMake 逻辑,而是关于 midl 和 cppwinrt 命令的输出,以及随后的编译和链接错误。我怀疑我可能缺少一些命令行选项。
# Pathnames for WinRT References
set (WINSDKREFDIR "$ENV{WindowsSdkDir}References\\$ENV{WindowsSDKVersion}")
# Remove trailing \ from $ENV{WindowsSDKVersion}
string (REGEX MATCH "[^\\]*" WINSDKVER $ENV{WindowsSDKVersion})
# COMMAND lines wrapped in this post for readability, not wrapped in the actual CMakeLists.txt
add_custom_target (MYLIB_PREBUILD ALL
COMMAND midl /winrt /ns_prefix /x64 /nomidl
/metadata_dir
"${WINSDKREFDIR}windows.foundation.foundationcontract\\3.0.0.0"
/reference
"${WINSDKREFDIR}windows.foundation.foundationcontract\\3.0.0.0\\Windows.Foundation.FoundationContract.winmd"
/reference
"${WINSDKREFDIR}Windows.Foundation.UniversalApiContract\\8.0.0.0\\Windows.Foundation.UniversalApiContract.winmd"
/out "${MYDIR}\\GeneratedFiles" "${MYDIR}\\MyClass.idl"
COMMAND cppwinrt
-in "${MYDIR}\\GeneratedFiles\\MyClass.winmd"
-ref ${WINSDKVER} -component -pch "pch.h" -out "${MYDIR}\\GeneratedFiles"
)
add_dependencies (MYLIB MYLIB_PREBUILD)
在 cppwinrt 命令中,我尝试了不同形式的 -ref [spec] 和 -pch 选项,但无论如何似乎都得到了相同的结果。这些是我遇到的问题:
MIDLRT 生成的头文件“MyClass.h”有几个问题:
- 它#includes <windows.h>,最终#defines 为GetClassName 和GetCurrentTime 定义预处理器宏,这些宏会在具有这些名称的WinRT 函数中导致编译器错误。
- 我花了几个小时来跟踪它并学习使用#define COM_NO_WINDOWS_H 进行编译以防止这种情况发生。
- 它#includes WinRT References Contracts 目录而不是 Include 目录中不存在的 *.h 文件:
- #include "C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Foundation.FoundationContract\3.0.0.0\Windows.Foundation.FoundationContract.h"
- #include "C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Foundation.UniversalApiContract\8.0.0.0\Windows.Foundation.UniversalApiContract.h"
- 所以我复制了这个文件并用 #include <winrt/Windows.Foundation.h> 替换了那些
CPPWINRT 生成#includes "MyNamespace.MyClass.h" 的"module.g.cpp",但不生成那个.h 文件。它确实会生成“MyNamespace/MyClass.h”(注意“/”而不是“.”),所以我创建了前一个 .h 并从中简单地#include 后一个 .h。
CPPWINRT 不会生成我在 Microsoft 示例中看到的所有基本标头。它只生成与 MyClass 直接相关的头文件——例如,定义模板基类 winrt::MyNamespace::implementation::MyClassT<>、包装器 winrt::MyNamespace::MyClass 等。
winrt::MyNamespace::factory_implementation::MyClass 未定义。MyClassT<> 在那里定义,但不是 MyClass。我从 Microsoft 示例中找到了一个范例并将其粘贴到:
// Missing from the generated stuff -- derived from a Microsoft example:
namespace winrt::MyNamespace::factory_implementation
{
struct MyClass : MyClassT<MyClass, implementation::MyClass>
{
};
}
- 我收到了关于 CHECK_NS_PREFIX_STATE 定义不一致的编译器警告:在某些地方它是“总是”,而在其他地方它是“从不”。所以现在我#define MIDL_NS_PREFIX 和#define CHECK_NS_PREFIX_STATE="always"
现在构建通过编译器,但我在链接器中有未解析的外部符号。我认为这些东西应该在“winrt/base.h”中内联定义,但是 cppwinrt 没有导出这样的文件(正如我在 Microsoft 示例中看到的那样),系统目录中的等效文件只包含原型,而不包含身体:
WINRT_GetRestrictedErrorInfo
WINRT_RoInitialize
WINRT_RoOriginateLanguageException
WINRT_SetRestrictedErrorInfo
WINRT_WindowsCreateString
WINRT_WindowsCreateStringReference
WINRT_WindowsDeleteString
WINRT_WindowsPreallocateStringBuffer
WINRT_WindowsDeleteStringBuffer
WINRT_WindowsPromoteStringBuffer
WINRT_WindowsGetStringRawBuffer
WINRT_RoGetActivationFactory
WINRT_WindowsDuplicateString
我是否遗漏了一些简单的东西来解决所有这些与丢失、不完整和不正确的生成文件有关的问题?