程式集的初始化及合併

2021-09-05 16:18:03 字數 2874 閱讀 1493

程式集的初始化及合併<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

摘要 : 這裡**.net assembly 的初始化與合併,很多情況下開發功能庫時,需要在assembly 載入時就進行一些初始化行為,比如說某些.net 混淆器,在以前通常採用在所有類中的靜態構造器中插入初始化方法,而現在,就可以僅僅在程式集初始化時就直接執行方法。

當我們要編寫一些元件庫的時候,必須以dll形式發布或者因為某種需求,如何在執行時初始化程式集,而不是強迫使用者呼叫初始化方法呢?

clr

的載入機制估計很多人都知道:

首先引導程式集,但僅僅讀取所有元資料,當第一次呼叫程式集某個模組的成員時,按以下程式載入: 1.

呼叫模組的靜態建構函式,並建立乙個模組的例項 2.

呼叫被呼叫成員的型別的靜態建構函式,如果是全域性方法\成員,則直接到第三步。 3.

執行呼叫過程/返回值。 4.

如果被呼叫的託管方法,clr檢查是否經過jit編譯,如沒有編譯,則編譯為本地**。 5.

執行方法呼叫。

上面說的託管模組的入口在程式集實際上依然為乙個類,如果經常使用reflector,則必然可以在根命名空間中看到名稱為 「」 的類,在下文中,我們將把「」稱為模組類

模組類非常特殊,首先它並不是從system.object 派生的,因為clr執行庫同樣有模組類,這也許是.net 唯一不從object 繼承的類了;模組類僅僅能包含三種成員,靜態建構函式、靜態方法、以及靜態字段,可以定義模組的建構函式,但是執行時clr會丟擲system.typeinitializationexception異常,例項方法可以定義,但是會被ilasm 在編譯時忽略。

而下面,為了演示模組構造器;我們從無所不能的c++/cli 入手。

#include

"stdafx.h"

using

namespace

system;

intinitzer()

intinit = initor();

intmain(

array

^args)

上面**的結果大家應該都知道:

module initilizing...

hello world!

但是,在c#、vb中,這樣的執行順序是不可能的(靜態構造器除外);看出他們**不同沒有?

對了,這個c++/cli 編寫的assembly 完全沒有任何類包裝,而c# 和vb 是純粹oo,不給類容器就不能執行。

這才是真正的全域性變數,無論程式如何執行,總是需要設定全域性變數,c++/cli的通用模組類建構函式如下(使用reflector反編譯):

[debuggerstepthrough]

()

(&languagesupport);

::_languagesupport_initialize(&languagesupport);

::_languagesupport_(&languagesupport); }

c++/cli

就這樣完成了執行時的初始化,恩沒錯,c++要間接的在模組構造時進行操作很方便。而c#、vb.net,是不可能的,我們可以期望microsoft 在.net framework 3.5 或更高的版本中提供乙個[module: moduleinitializerattribute(inittype)],inittype為初始化的型別(呼叫靜態構造方法)或介面(呼叫介面方法),當然,在這裡也有別的解決方案。

用il實現我們的願望,**如下:

.assembly extern mscorlib{}

.assembly test

.module moda

//定義模組靜態建構函式

.method public hidebysig specialname rtspecialname static void .cctor() cil managed

.namespace testa

.method private hidebysig static void main(string args) cil managed}}

注:在module 初始化時如果呼叫模組中某類的成員,將會導致clr 初始化該類,因此,在模組建構函式中是可以呼叫該模組中的成員的,但是不能訪問呼叫棧的上層,否則會丟擲異常,因為上層屬於clr,並不是託管**。

用在命令列中輸入命令ilasm moda.il 編譯上面的**,我們將得到乙個moda.exe。

執行後,輸出結果如下:

#module initializeing...

*type initlizeing...

+here is main method, welcome!

+press any key to exit...

現在我們得到我們想要的結果了,但是這只能用il 完成,將整個功能庫用il 寫,顯然是不現實的。

幸運的是microsoft 為我們提供了工具

ilmerge

,我們可以用它完成兩個純粹的.net程式集的合併;於csc 和vbc 的/addmodule 選項不同,ilmerge 直接把兩個程式集中的所有模組合併為乙個,而/addmodule 則是將兩個模組合併為乙個程式集,實際上依舊是兩個模組。

當然,我們不只能夠合併.net 程式集,還能夠合併nativepe 檔案,這個我們需要乙個叫做mergebin 的程式,我是在

sqlite for .net provider

的原始碼包中發現它的,使用它有一些限制,要設定data_seg 為 『.clr』,並且為該section 保留足夠容納.net assembly 的大小,具體可以用mergebin 計算出來,其他的細節就不做細表。

zealic 2007-04-19

關於初始化及初始化順序

首先,類的成員變數會被自動初始化,並且會在構造器被呼叫前發生,如下 public class testinitialization public static void main string args 如下 主類 public class staticinitialization 呼叫main之前...

初始化 關於tensorflow的初始化

在寫mnist手寫體識別任務 已放github 時遇到的 問題 我們都知道在session run的時候需要初始化。但是初始化在什麼位置是至關重要的。來看下這段 sess tf.session sess.run tf.global variables initializer mnist model ...

MVS初始化相關資料集

系統初始化相關的重要系統資料集 1.主目錄資料集 主目錄 master catalog 是乙個vsam型別的資料集,記載著其它資料集及駐留磁碟卷資訊,用於定位資料和使用者目錄 user catalog 2.頁交換資料集 頁交換資料集 page data set 也是 vsam型別的資料集,用來儲存位...