簡體   English   中英

PInvoke使堆棧不平衡

[英]PInvoke has unbalanced the stack

我正在嘗試在C#項目中使用C DLL。

我在C中有一個功能:

extern __declspec(dllexport) void InitBoard(sPiece board[8][8]);

sPiece結構:

typedef struct Piece
{
    ePieceType PieceType; //enum
    ePlayer Player; //enum
    int IsFirstMove;
} sPiece;

我在C#中有PInvoke:

[DllImport("chess_api.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
static extern void InitBoard([MarshalAs(UnmanagedType.LPArray, SizeConst = 64)]ref sPiece[] board);

C#上的sPiece結構:

[StructLayout(LayoutKind.Sequential)]
public struct sPiece
{
    public ePieceType PieceType;
    public ePlayer Player;
    public int IsFirstMove;
}

當我運行PInvoke時,出現以下錯誤:

調用PInvoke函數'Chess!Chess.Main :: InitBoard'會使堆棧不平衡。 這可能是因為托管PInvoke簽名與非托管目標簽名不匹配。 檢查PInvoke簽名的調用約定和參數是否與目標非托管簽名匹配。

我嘗試將調用約定更改為Cdecl ,但是當我運行它時,VS卡住了。

我應該做些什么?

你有兩個問題。 首先,您使用了錯誤的調用約定。 非托管函數使用cdecl,因此您需要托管函數來匹配它。

另一個更具挑戰性的問題是二維陣列。

void InitBoard(sPiece board[8][8]);

您不能使用p / invoke封送二維數組。 您需要切換到一維數組:

void InitBoard(sPiece board[]);

托管方如下所示:

[DllImport("chess_api.dll", CallingConvention = CallingConvention.Cdecl)]
static extern void InitBoard(sPiece[] board);

在實現內部,您可以訪問以下元素:

要將行/列對轉換為線性索引,請使用以下關系:

index = row*8 + col;

請注意,我也刪除了SetLastError的設置,因為我非常懷疑您的函數會調用SetLastError

C / C ++的默認調用約定為CDecl(請參閱本文 )。

__cdecl是C和C ++程序的默認調用約定。 因為堆棧是由調用方清理的,所以它可以執行vararg函數。 __cdecl調用約定比__stdcall創建更大的可執行文件,因為它要求每個函數調用都包括堆棧清除代碼。 以下列表顯示了此調用約定的實現。

在您的代碼中,指定CallingConvention = CallingConvention.StdCall 這是不兼容的。 更改為CallingConvention.Cdecl有關調用約定的更多信息,請參見此處

看一下這個討論:

調用PInvoke函數'[...]'使堆棧不平衡

也許問題出在調用約定上。

...

顯然在函數原型中添加__std並聲明對其進行修復。 謝謝

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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