MDA unbalanced stack C# dll PInvoke signature

 

A call to PInvoke function 'cCardControl::getPos' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.

我的某段程式會噴出上面的Error,當然簡單的可以直接停用MDA,但現在會有不確定的藍白跑出來Orz

C 的 prototype 為

typedef int (*GET_POS_FUNC)(long *top, long *left, long *bottom, long *right, long *width, long *height);

我的C# 寫法為

[DllImport(@"xxx.dll", EntryPoint = "getPipPos")]
public static extern int getPos(out int Top, out int Left, out int Bottom, out int Right, out int Width, out int Height);


這裡要注意的是 C 在 32 bit 的 long 為 4 byte,所以C#要改用 int,C#的long是 8 byte 的,如果不確定就在 C 那邊使用 sizeof(long) 看一下。

我的程式會出現 unbalanced the stack 的錯誤。可是我另外一個簡單的小程式卻都沒有出現,後來發現是 .Net Framework 版本的問題,小程式是 .Net 2,我的程式是 .Net 4。於是開始搜尋,找到了下面的網頁。

http://msdn.microsoft.com/en-us/library/0htdy0k3.aspx

如果我英文沒看錯的話,他是說.Net 4 才會預設啟用這個 MDA,在 3.5 以下並不會啟用。等等,難得在.Net 2時也是有這個錯誤,只是我沒有啟用MDA就沒有抓到嗎?於是重新跑了一下,耶,在.Net2也是會有啟用這個MDA啊,好險沒有被騙了~

這樣就麻煩了,不知道為什麼.Net 2 跟 .Net 4 PInvoke的規則哪裡變嗎?

最後我是加上 ExactSpelling = true, CallingConvention = CallingConvention.Cdecl,在 .Net 4 就沒有錯誤了~

[DllImport(@"xxx.dll", EntryPoint = "getPos", ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
        public static extern int getPos(out int Top, out int Left, out int Bottom, out int Right, out int Width, out int Height);

CallingConvertion 有很多種規範,我也只知道由呼叫方清除or被呼叫方清除,有興趣的人可以自己去研究一下。

留言

匿名表示…
Thanks, I got the same proble and has used your method to resolve it!Genius and awsome.

這個網誌中的熱門文章

好貴的東元冷氣維修--馬達啟動電容

台大醫院 婁培人 耳鼻喉科 就診

機車無法充電之整流器壞掉--$650