1 回答

TA貢獻1863條經(jīng)驗 獲得超2個贊
那個設(shè)定
所以,基本上,你得到的映射是
int* buffer
?→?buffer uintptr
int argc
→?unsafe.Pointer(&argsCount)
,其中&argsCount
是一個指向int
char* argv[]
→?unsafe.Pointer(&args)
,哪里args
是[]string
const char* fileName
→unsafe.Pointer(syscall.StringToUTF16Ptr(fileName))
const char* key
,?const char* prefix
,?const char* version
— 同上。
存在的問題
現(xiàn)在這有什么問題呢。
uintptr
禁止在函數(shù)之間傳遞包含活動 Go 對象地址的值。(稍后會詳細介紹。)argsCount
您將函數(shù)參數(shù)的地址傳遞給argc
。如果將其解釋為計數(shù),則典型的商品平臺/操作系統(tǒng)(例如 amd64/Windows)上的地址是一個極其巨大的值。我敢打賭,當函數(shù)嘗試從中讀取這么多元素時,它會崩潰,導致
argv
它讀取進程未映射的內(nèi)存。這里有兩個問題:
將切片值的地址作為參數(shù)傳遞,期望該切片的第一個元素的地址是錯誤的。
這是因為切片值(目前,在您應(yīng)該使用的“參考”Go 實現(xiàn)中)是具有
struct
3 個字段的:底層數(shù)據(jù)數(shù)組的地址、該數(shù)組中允許使用的元素數(shù)以及總數(shù)該數(shù)組中此類元素的計數(shù)append
,在對切片值調(diào)用時,函數(shù)可以使用這些元素,而無需重新分配。當您擁有
args []string
并執(zhí)行時&args
,您將獲得該結(jié)構(gòu)的地址,而不是該切片的第一個元素的地址。要執(zhí)行后者,請使用
&args[0]
.在 Go 中,字符串(通常是這樣,我們假設(shè)是這樣)包含編碼為 UTF-8 的字符。這通常不是 Windows 本機 C++ 代碼在表示需要
char *
.我猜,你需要首先為 構(gòu)建一個合適的東西
argv
,比如argv?:=?make([]unsafe.Pointer,?0,?len(args))for?i,?s?:=?range?args?{ ????argv[i]?=?unsafe.Pointer(syscall.StringToUTF16Ptr(s)) }
然后傳遞
&argv[0]
給被調(diào)用者。但請參閱下文
syscall.StringToUTF16Ptr()
。
您正在做的將字符串數(shù)據(jù)傳遞給具有該類型的其余參數(shù)的準備工作
const char*
似乎是正確的,但前提是被調(diào)用者確實意味著它char
是一個 16 位整數(shù)。換句話說,用于編譯該庫的源代碼和工具鏈必須確保它
char
確實是wchar_t
或WCHAR
。如果是,那么你的做法應(yīng)該沒問題;否則就不是。你應(yīng)該驗證這一點。
uintptr
關(guān)于在表達式之間傳遞 s 的注意事項
Go 具有垃圾收集功能,因此它的運行時必須知道指向所有當前活動對象的所有指針。只要存在一個變量,其中包含指向在程序運行時分配的內(nèi)存塊的指針,該塊就不會被垃圾收集。
值unsafe.Pointer
算作對內(nèi)存塊的正確引用,但uintptr
值則不然。這意味著當代碼
p?:=?new(someType) u?:=?uintptr(unsafe.Pointer(&p)) foo(u)return
p
正在運行時,一旦分配了地址,GC 就可以自由地回收由 分配的對象p
,因為p
是對該對象的唯一引用,但u
事實并非如此。
現(xiàn)在考慮參考 Go 實現(xiàn)中的 GC 與程序代碼同時運行。這意味著當foo
運行時,GC 也可能會執(zhí)行,并且它可能會將您的實例someType
從foo
.
作為此一般規(guī)則的一個例外,Go 編譯器保證uintptr(unsafe.Pointer)
同一語言表達式中發(fā)生的所有類型轉(zhuǎn)換都不受 GC 的影響。所以以我們之前的例子為例,這樣做就可以了
foo(uintptr(unsafe.Pointer(new(someType)))return
和
p?:=?new(someType) v?:=?unsafe.Pointer(&p) foo(uintptr(v))return
因為類型轉(zhuǎn)換發(fā)生uintptr
在單個表達式中——這是一個函數(shù)調(diào)用。
因此,您不能將指向 Go 對象的指針作為uintptr
s傳遞,除非它們包含從“C 端”獲取的指針。
- 1 回答
- 0 關(guān)注
- 182 瀏覽
添加回答
舉報