c++ - 如何使用 mingw 编译和链接最小的 .NET C++ 程序
问题描述
我正在尝试编译 .NET C++ 代码的最小示例(只需调用 CLRCreateInstance 并启动 CLR 运行时主机)。我没有使用 Visual Studio,而是 mingw。我安装了带有 .NET 好东西的 Windows 10 SDK,并且我在 Program Files 中正确安装了头文件和 lib 文件。但是,我无法让 g++ 链接我的程序:
$ g++ -o clr.exe -I"C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\Include\um" -L"C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\Lib\um\x64" -lmscoree clr.cpp
C:\Users\XXX\AppData\Local\Temp\cciBbZmZ.o:clr.cpp:(.text+0x3d): undefined reference to `_GUID const& __mingw_uuidof<ICLRMetaHost>()'
C:\Users\XXX\AppData\Local\Temp\cciBbZmZ.o:clr.cpp:(.text+0x4f): undefined reference to `CLRCreateInstance'
C:\Users\XXX\AppData\Local\Temp\cciBbZmZ.o:clr.cpp:(.text+0x78): undefined reference to `_GUID const& __mingw_uuidof<ICLRRuntimeInfo>()'
C:\Users\XXX\AppData\Local\Temp\cciBbZmZ.o:clr.cpp:(.text+0xb3): undefined reference to `_GUID const& __mingw_uuidof<ICLRRuntimeHost>()'
collect2.exe: error: ld returned 1 exit status
该计划是:
#include <iostream>
#include <Windows.h>
#include <metahost.h>
#include <mscoree.h>
#pragma comment(lib, "mscoree.lib")
int main()
{
HRESULT hr;
ICLRMetaHost *pMetaHost = NULL;
ICLRRuntimeInfo *pRuntimeInfo = NULL;
ICLRRuntimeHost *pClrRuntimeHost = NULL;
// build runtime
hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_PPV_ARGS(&pMetaHost));
hr = pMetaHost->GetRuntime(L"v4.0.30319", IID_PPV_ARGS(&pRuntimeInfo));
hr = pRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost,
IID_PPV_ARGS(&pClrRuntimeHost));
// start runtime
hr = pClrRuntimeHost->Start();
hr = pClrRuntimeHost->Stop();
}
解决方案
我终于使它与以下两个更正一起工作:
我从 vanilla MinGW 切换到 msys2 封装的。这解决了对 CLRCreateInstance 的未定义引用,我不知道为什么香草 MinGW 会失败。这基本上包括下载 msys2 并运行
pacman -S mingw-w64-x86_64-gcc
.感谢这个问题,我能够解决其他三个未定义的引用。我仍然不确定所有这些 COM 的东西是如何工作的,所以不幸的是,我不确定这是否是解决问题的正确方法,或者我是否只是引入了一个致命错误但是......我进入
mscoree.h
了metahost.h
. NET SDK 安装目录,并查找链接器抱怨的内容。
例如,在mscoree.h
我发现:
EXTERN_GUID(IID_ICLRRuntimeHost, 0x90F1A06C, 0x7712, 0x4762, 0x86, 0xB5, 0x7A, 0x5E, 0xBA, 0x6B, 0xDB, 0x02);
所以我去了我的 clr.cpp 文件并添加了:
__CRT_UUID_DECL(ICLRRuntimeHost, 0x90F1A06C, 0x7712, 0x4762, 0x86, 0xB5, 0x7A, 0x5E, 0xBA, 0x6B, 0xDB, 0x02);
这似乎工作得很好。对其他两个做了同样的事情,我的代码进入了这个,它编译并运行没有错误:
#include <Windows.h>
#include <metahost.h>
#include <mscoree.h>
#include <cstdio>
__CRT_UUID_DECL(ICLRMetaHost, 0xD332DB9E, 0xB9B3, 0x4125, 0x82, 0x07, 0xA1, 0x48, 0x84, 0xF5, 0x32, 0x16);
__CRT_UUID_DECL(ICLRRuntimeInfo, 0xBD39D1D2, 0xBA2F, 0x486a, 0x89, 0xB0, 0xB4, 0xB0, 0xCB, 0x46, 0x68, 0x91);
__CRT_UUID_DECL(ICLRRuntimeHost, 0x90F1A06C, 0x7712, 0x4762, 0x86, 0xB5, 0x7A, 0x5E, 0xBA, 0x6B, 0xDB, 0x02);
int main(int argc, char *argv[])
{
HRESULT hr;
ICLRMetaHost *pMetaHost = NULL;
ICLRRuntimeInfo *pRuntimeInfo = NULL;
ICLRRuntimeHost *pClrRuntimeHost = NULL;
// build runtime
if (CLRCreateInstance(CLSID_CLRMetaHost, IID_PPV_ARGS(&pMetaHost)) != S_OK) {
printf("[x] Error: CLRCreateInstance(..)\n");
return 2;
}
if (pMetaHost->GetRuntime(L"v4.0.30319", IID_PPV_ARGS(&pRuntimeInfo)) != S_OK) {
printf("[x] Error: GetRuntime(..)\n");
return 2;
}
if (pRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_PPV_ARGS(&pClrRuntimeHost)) != S_OK) {
printf("[x] Error: GetInterface(..)\n");
return 2;
}
// start runtime
if (pClrRuntimeHost->Start() != S_OK) {
printf("[x] Error: Start(..)\n");
return 2;
}
// start runtime
if (pClrRuntimeHost->Stop() != S_OK) {
printf("[x] Error: Stop(..)\n");
return 2;
}
printf("success!\n");
return 0;
}
推荐阅读
- c++ - 将二进制文件读入 uint32_t 的向量
- android - Android Studio 问题,kt 文件以未知形式出现?
- java - 从 Java 中的单词打印元音
- c# - 实体框架:部署时 DBContext 无法连接到另一台 PC 上的服务器
- c++ - unordered_map 的存在决定了是使用复制构造函数还是移动构造函数
- python - 可以使用 Python 在 Plotly 中定义 X 和 Y 值吗?
- perl - 如何使用 moose 设置默认 FileHandle 属性
- centos - 正确的 /var/www 的 Centos 分区设置
- dart - 正确 Flutter 小部件序列以在应用加载时提取数据
- javascript - 脚本标签在反应上相对或直接不起作用