簡體   English   中英

從托管代碼調用本機函數

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM