在平台呼叫中,因為託管型別和非託管型別之間有差異,所以需要進行入參與出參的封送才可正常的呼叫非託管的函式。在所有要進行封送的引數型別之中,大體分為兩種:
可直接複製到本機結構中的型別(blittable)和非直接複製到本機結構中的型別(non-bittable)
blittable型別轉換對照表:
windows 資料型別
非託管資料型別
託管資料型別
託管資料型別解釋
byte/uchar/uint8
unsigned char
system.byte
無符號8位整型
sbyte/char/int8
char
system.sbyte
有符號8位整型
short/int16
short
system.int16
有符號16位整型
ushort/word/uint16/wchar
unsigned short
system.uint16
無符號16位整型
bool/hresult/int/long
long/int
system.int32
有符號32位整型
dword/ulong/uint
unsigned long/unsigned int
system.uint32
無符號32位整型
int64/longlong
_int64
system.int64
有符號64位整型
uint64/dwordlong/ulonglong
_uint64
system.uint64
無符號64位整型
int_ptr/handle/wparam
void*/int或_int64
system.intptr
有符號指標型別
handle
void*
system.uintptr
無符號指標型別
float
float
system.single
單精度浮點數
double
double
system.double
雙精度浮點數
除了上表列出來的簡單型別之外,還有一些複製型別也屬於可直接複製到本機結構中的資料型別:
(1) 資料元素都是可直接複製到本機結構中的一元陣列,如整數陣列,浮點陣列等
(2)只包含可直接複製到本機結構中的格式化值型別
(3)成員變數全部都是可複製到本機結構中的型別且作為格式化型別封送的類
上面提到的格式化指的是——在型別定義時,成員的記憶體布局在宣告時就明確指定的型別。在**中用structlayout屬性修飾被指定的型別,並將structlayout的layoutkind屬性設定為sequential或explicit。
non-bittable型別轉換對照表:
windows 資料型別
非託管資料型別
託管資料型別
託管資料型別解釋
bool
bool
system.boolean
布林型別
wchar/tchar
char/ wchar_t
system.char
ansi字元/unicode字元
lpcstr/lpcwstr/lpctstr/lpstr/lpwstr/lptstr
const char*/const wchar_t*/char*/wchar_t*
system.string
ansi字串/unicode字串,如果非託管**不需要更新此字串時,此時用string型別在託管**中宣告字串型別
lpstr/lpwstr/lptstr
char*/wchar_t*
system.stringbuilder
ansi字串/unicode字串,如果非託管**需要更新此字串,然後把更新的字串傳回託管**中,此時用stringbuilder型別在託管**中宣告字串
除了上表列出的型別之外,還有一些型別屬於非可直接複製型別,例如其他指標型別和控制代碼型別等。
相較於可直接複製型別,non-bittable型別因為在託管**記憶體中的儲存形式與非託管**中的記憶體儲存形式不同,所以需要做中間轉換處理,才能複製到被呼叫的函式之中。
若要封送結構體,需要先知道非託管函式的結構體引數的詳細資訊,然後再根據該資訊在託管**之中構建出相對應的結構體進行初始化並封送。在非託管函式宣告時,結構體引數要用ref關鍵字進行修飾,不能使用out,因為out引數在傳入前不會進行初始化。
若要封送類,也是同樣的道理,先要明確非託管函式中引數類的詳細資訊,然後在託管**中構建同樣的類,初始化並且進行封送。需要注意的是,在非託管函式宣告時,類引數要用[in]關鍵字進行修飾,這樣才能使初始值傳入到函式體之中,如果有進行修改並返回的需求,則還要加上[out]關鍵字,寫法[in, out]。
本文參考博主learning hard,如要更為細緻的了解互操作呼叫的相關知識,請參閱該博主的博文
平台呼叫 結構的封送
關於結構的封送,先看乙個類 structlayoutattribute 該類的作用是,允許控制記憶體中類或結構的資料字段的物理布局。該類的層次結構為 system.object system.attributesystem.runtime.interopservices.structlayoutat...
原 C 與非託管 封送和自動封送
之前說到了如何從c函式宣告通過簡單的查詢替換生成乙份c 的靜態引用宣告 c 與非託管 初體驗 因為只是簡單說明,所以全部採用的是基礎型別匹配和自動封送。自動封送雖然能省去我們不少編碼時間,但如果不理解自動封送背後的實際行為,那就如同看魔術師的黑盒子,知其然不知其所以然。而且,自動封送也不是永遠有效的...
託管呼叫非託管的DLL
dllimport createnewprocess.dll charset charset.unicode public static extern bool createprocess marshalas unmanagedtype.lpwstr string fullpath 以上是定義入口,...