首页 > 解决方案 > 如何使用 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();
}

标签: c++.netmingw

解决方案


我终于使它与以下两个更正一起工作:

  1. 我从 vanilla MinGW 切换到 msys2 封装的。这解决了对 CLRCreateInstance 的未定义引用,我不知道为什么香草 MinGW 会失败。这基本上包括下载 msys2 并运行pacman -S mingw-w64-x86_64-gcc.

  2. 感谢这个问题,我能够解决其他三个未定义的引用。我仍然不确定所有这些 COM 的东西是如何工作的,所以不幸的是,我不确定这是否是解决问题的正确方法,或者我是否只是引入了一个致命错误但是......我进入mscoree.hmetahost.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;

}

推荐阅读