C++是如何运行C#/.Net的?

前言

C#这门语言是运行在.Net平台上面的。那么.Net平台是依靠什么运行的呢?没错就是C++。严格来说是类C的C++。本篇来看下。.

概括

1.引申
知乎上有个提问:C#和C++语句有区别吗?
当时回答的是:
C++严格来说是C#的干爹
那么反过来,C#是C++的干儿子
为什么这么说呢?C#的运行时CLR的小型主机CoreRun超过90%类C的C++。
那么C#的亲爹是谁呢?自然是微软了

2.托管与非托管
实际上大部分.Net程序员都是通过DllImport来导入非托管的C++ API。尤其是Windows上的API,来通过托管代码运行非托管代码。这其实是微软通过CLR虚拟机提供的托管运行非托管的能力。
但是这里有个前提就是,托管要能够运行的起来。如何让托管运行起来呢?一切解决的万事万物,无非就是二进制里面的面向过程的语言C/C++了。这里举几个例子:
一:Java源码通过C++虚拟机JVM来运行的
二:Go的Runtime实现了90%以上的自举,但是它的引导程序依然是C
三:Python,Python作为一种解释性的语言,它解释器里面包含了编译器和虚拟机,它这个虚拟机就是C++.
以上是当今比较流行的几大语言,其实他们的运行模式几乎都是一模一样。编译-》解释-》执行。
这里要说的是.Net依然如此,它是通过C++启动虚拟机进行运行的。

3.代码
一段简单的C#代码:

internal class Program{   static void Main(string[] args)   {       Console.WriteLine("Hello, World!");       Console.ReadLine();   }}

如果要用C++加载这段托管的代码,应该怎么做呢?

下面一段代码就是C加载托管的DLL,运行托管的入门代码HelloWorld

#include <stdio.h>#include <Windows.h>#include "hostfxr.h"hostfxr_main_startupinfo_fn startupinfo_fptr;// 实例化一个运行时入口函数指针,此指针用以调用了.Net 托管代码里面的Main函数入口
int main(int argc, char** argv){        // 这个就是上面的Host_Path路径。注意CPP里面的路径是双斜杠  const wchar_t* Host_Path = L"E:\\Visual Studio Project\\Test\\Test\\bin\\Debug\\net6.0";  //这个就是上面的ConsoleApp  const wchar_t* ConsoleApp = L"E:\\Visual Studio Project\\Test\\Test\\bin\\Debug\\net6.0\\Test.dll";  //这个呢,就是上面的DotNet_Root路径。  const wchar_t* DotNet_Root = L"C:\\Program Files\\dotnet\\shared\\Microsoft.NETCore.App\\7.0.0";  //这里的argvV参数区别于Main的argv参数,主要用于运行时入口函数指针的参数。  const wchar_t* argvV = L"";  //用LoadLibraryExA加载上面前期准备的步骤里的hostfxr.dll  HMODULE h = LoadLibraryExA("C:\\Program Files\\dotnet\\host\\fxr\\7.0.0\\hostfxr.dll", NULL, 0);  //通过GetProcAddress函数获取到运行时入口函数指针,也就是上面实例化的startupinfo_fptr变量  startupinfo_fptr = (hostfxr_main_startupinfo_fn)GetProcAddress(h, "hostfxr_main_startupinfo");  //通过传入运行时入口函数指针的参数,包括Host_Path,DotNet_Root,ConsoleApp等参数。来运行CLR,用以调用ConsoleApp里面的Main函数入口。  startupinfo_fptr(1, &argvV, Host_Path, DotNet_Root, ConsoleApp);  return 0;}

头文件:

https://github.com/dotnet/runtime/blob/main/src/native/corehost/hostfxr.h

非常简单的一段程序,轻轻松松通过非托管的C加载调用托管的DLL,把它运行出来。