[英]Call native function from managed code
我試圖從托管代碼中調用本機函數,以便讀取作為數組sbyte參數傳遞的返回值。 但是,我什么也看不懂。 數組的字節數始終相同,並且永遠不會被本機函數修改。
以下是C ++函數簽名:
void __cdecl NativeFunction(int8_t StatusFlagOut[], int32_t *len);
另一個是我的C#包裝器:
[DllImport("NativeDll.dll")]
internal static extern void NativeFunction([Out] sbyte[] statusFlagOut, ref int len);
最后,這是我用來調用函數的方式:
sbyte[] output = null;
int len = 0;
NativeFunction(output, ref len); // while len is being filled properly, output never being changed.
該函數是cdecl,因此您需要在p / invoke中指定它:
[DllImport("NativeDll.dll", CallingConvention=CallingConvention.Cdecl)]
internal static extern void NativeFunction(
[Out] sbyte[] statusFlagOut,
ref int len
);
最大的問題是您沒有為本機函數分配內存。 似乎您期望本機代碼分配內存。 顯然,這不是它的設計方式,正確的是。 您總是希望呼叫者出於許多我不會在這里介紹的原因來分配內存。
似乎本機函數可以幫助您分配多少。 所以看來您可以編寫如下代碼:
int len = 0;
NativeFunction(null, ref len);
sbyte[] output = new sbyte[len];
NativeFunction(output, ref len);
最后,一個更籠統的觀點。 這是一個互操作性問題。 他們總是需要完全了解二進制互操作接口的兩側。 您沒有提供C ++方面的完整詳細信息。 您提供了功能簽名,但未提供該功能的語義。 因此,我進行了有根據的猜測。 包括這些細節非常重要,以防萬一我們的猜測能力失敗了!
使用cdecl
調用約定調用本機函數時,應明確指定它:
[DllImport("NativeDll.dll", CallingConvention = CallingConvention.Cdecl)]
如果您不這樣做,則CLR默認情況下會將其解釋為stdcall
,並期望被調用方清除堆棧,在cdecl
的情況下,調用方cdecl
,並且會發生不良情況。
正如評論中提到的那樣,在使用平台調用時, arrays
是一種特殊的方法,因為它們是通過值傳遞的。 MSDN上[Out]
頁面上描述了以下內容:
例如,可以將按值傳遞的數組(默認情況下封為In-only參數)可以更改為Out-only。 但是,當類型包括所有可變元素或字段時,該行為並不總是提供預期的語義,因為互操作封送處理程序使用固定。 如果您不關心將數據傳遞到被調用方,則僅輸出封送處理可以為不可拆分類型提供更好的性能。 將InAttribute和OutAttribute組合在一起時,將其應用於數組和格式化的,不可復制的類型時特別有用。 僅當您同時應用這兩個屬性時,呼叫者才能看到被呼叫者對這些類型所做的更改。 由於這些類型在封送處理期間需要復制,因此可以使用InAttribute和OutAttribute減少不必要的副本。
這意味着您的最終簽名應如下所示:
[DllImport("NativeDll.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern void
NativeFunction([In, Out] sbyte[] statusFlagOut, ref int len);
我解決了 您說對了,本機功能中有一個錯誤。
但是,還必須像您向我建議的那樣添加調用約定規范,因此最終簽名包裝將如下所示:
[DllImport("NativeDll.dll", CallingConvention=CallingConvention.Cdecl)]
internal static extern void NativeFunction(
[Out] sbyte[] statusFlagOut,
ref int len
);
非常感謝你。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.