曾幾何時,一直想自己客製化一個CLR執行時玩玩。滿足下技術控的虛榮心,本篇帶你一步一步打造一個屬於自己的.Net 7執行時。
假設你的電腦已經安裝了.Net,並且執行正常。在進行自定義執行時之前,首先需要準備三樣東西。
其一:
找到你當前安裝的.Net宿主目錄,一般的預設目錄都是:
C:\Program Files\dotnet\host\fxr
在這個目錄下面是你的當前電腦安裝的.Net 版本了。比如7.0.0或者其它版本,它是一個資料夾,它的路徑看起來是這樣:
C:\Program Files\dotnet\host\fxr\7.0.0
這個路徑下面有一個hostfxr.dll檔案,記住它,後面要用。
其二:
我們進入到這個網址:
https://github.com/dotnet/runtime/blob/main/src/native/corehost/hostfxr.h
可以看到這個github路徑下,是一個hostfxr.h的標準C標頭檔案。你把它裡面的內容複製到記事本,然後儲存檔名為:hostfxr.h。後面要用。
其三:
準備一個.Net 控制檯應用程式,程式碼就是一個Helloworld輸出,如下:
internal class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello, World!");
Console.ReadLine();
}
}
把它編譯之後,找到它的路徑。
.Net 7的執行時裡面有個規定。路徑分為,主機路徑Host_path也就是你需要執行程式的Debug路徑,比如本例的
Host_Path=E:\Visual Studio Project\Test\Test\bin\Debug\net6.0
APP路徑,也就是的程式編譯之後的DLL路徑,本例如下:
ConsoleApp=\Visual Studio Project\Test\Test\bin\Debug\net6.0\Test.dll
.Net根目錄路徑:
DotNet_Root=C:\Program Files\dotnet\shared\Microsoft.NETCore.App\6.0.8
OK,假如你以上三樣準備好了,我們繼續下面的步驟。
用Visual Studio新建一個C++控制檯應用程式,取名:SuZhu。新建之後,會跳出一個SuZhu.cpp檔案。把裡面的程式碼全部刪掉。用下面的程式碼替代:
#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";//這個是上面的AppConsole路徑。
//這個呢,就是上面的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;
}
然後引入上面步驟二里面儲存記事本的檔案hostfxr.h。
點選專案展開-》標頭檔案-》右鍵新增--》現有專案,選擇hostfxr.h。
如果你以上步驟都實現了,並且沒有問題。那麼現在請摁Visual Sutdio的F5按鈕執行當前CPP程式。
結果就會列印出Hello, World!
如下圖所示:
這個是一個非常小型且精簡的CLR執行時程式。遮蔽了繁瑣的實現過程。你可以通過這個小型的CLR執行時,構建自己的客製化型的執行時。比如這個Host_Path,ConsoleApp傳參方式等等。本篇只是最基礎的展示。
以上是C++和C#混搞,對於部分.Net程式設計師可能有點難度。
如果你對.Net的CLR核心技術感興趣,或者有不明白的地方,可以掃碼關注我。