I am calling a Delphi function from C# and get the error:I've exhausted attempts changing the .Net code to fit the Delphi signatures, why it doesn't work with basic Integers has me stumped, does anyone know where I am going wrong?Even the simplest function using 2 integers produces the error. I'm targeting x86 and have put in a couple of hours research but the following solutions haven't helped here,here and here and this one. This is the Delphi Code (compiled DLL version can be downloaded from here):unit PasBallEntry;interfaceprocedure EntryPoint( InInt: integer; InStr: PChar; var OutInt: integer; var OutStr: PChar); stdcall;procedure ReleaseString( OutStr: PChar); stdcall;procedure TimTamC( InInt: integer; InStr: PChar; var OutInt: integer; var OutStr: PChar); cdecl;procedure ReleaseStringC( OutStr: PChar); cdecl;procedure TimTamCS( InInt: integer; InStr: PChar; var OutInt: integer; var OutStr: PChar); cdecl; stdcall;procedure ReleaseStringCS( OutStr: PChar); cdecl; stdcall;procedure OneTwoS( var A, B: integer); stdcall;procedure OneTwoC( var A, B: integer); cdecl;procedure OneTwoCS( var A, B: integer); cdecl; stdcall;exportsEntryPoint name 'TimTam',ReleaseString name 'ReleaseString';implementationuses Windows, SyncObjs, Classes, Generics.Collections;var Gate: TCriticalSection; Strs: TStrings; StrP: TList<PChar>;procedure EntryPoint( InInt: integer; InStr: PChar; var OutInt: integer; var OutStr: PChar);var InStrL, OutStrL: string;begin OutInt := 2 * InInt; InStrL := InStr; OutStrL := InStrL + '_OUT!'; UniqueString( OutStrL); if OutStrL = '' then OutStr := nil else begin OutStr := PChar( OutStrL); Gate.Enter; Strs.Add( OutStrL); StrP.Add( OutStr ); Gate.Leave endend;procedure ReleaseString( OutStr: PChar);var I: integer;begin if not assigned( OutStr) then exit; Gate.Enter; StrP.Insert( I, OutStr); if I >= 0 then begin StrP.Delete( I); Strs.Delete( I) end; Gate.Leaveend;procedure TimTamC( InInt: integer; InStr: PChar; var OutInt: integer; var OutStr: PChar);begin EntryPoint( InInt, InStr, OutInt, OutStr)end;procedure ReleaseStringC( OutStr: PChar);begin ReleaseString( OutStr)end;procedure TimTamCS( InInt: integer; InStr: PChar; var OutInt: integer; var OutStr: PChar);begin EntryPoint( InInt, InStr, OutInt, OutStr)end;procedure ReleaseStringCS( OutStr: PChar);begin ReleaseString( OutStr)end;procedure OneTwoS( var A, B: integer);begin A := 1; B := 2end;procedure OneTwoC( var A, B: integer);begin A := 1; B := 2end;procedure OneTwoCS( var A, B: integer);begin A := 1; B := 2end;initialization Gate := TCriticalSection.Create; Strs := TStringList.Create; StrP := TList<PChar>.Createfinalization Strs.Free; Gate.Free; StrP.Freeend.Here is the .Net code:[DllImport("PascalBall.dll", EntryPoint = "TimTam", CallingConvention = CallingConvention.Cdecl)]public static extern void OneTwoC(ref int a, ref int b);[DllImport("PascalBall.dll", EntryPoint = "TimTam", CallingConvention = CallingConvention.StdCall)]public static extern void OneTwoS(ref int a, ref int b);[DllImport("PascalBall.dll", EntryPoint = "TimTam", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]public static extern void TimTamC(int inputInt, string inputString, ref int outputInt, ref string outputString);private void button1_Click(object sender, EventArgs e){ int a = 0; int b = 0; //Both these PInvoke calls fail (either StdCall or Cdecl) OneTwoS(ref a, ref b); OneTwoC(ref a, ref b); System.Diagnostics.Debug.WriteLine(a + b);}private void button2_Click(object sender, EventArgs e){ int outInt = 1; string outStr = "world"; const int stringBufferSize = 1024; var outputStringBuffer = new String('\x00', stringBufferSize); try { TimTamC(1, outputStringBuffer, ref outInt, ref outputStringBuffer); ReleaseString(ref outStr); } catch (Exception ex) { }}Edit 1: I think I have the EntryPoint correct using TimTam, because I get a System.EntryPointNotFoundException if I try anything else, see here: 解决方案 There are a very large number of mistakes here. The immediate problem is here:[DllImport("PascalBall.dll", EntryPoint = "TimTam", CallingConvention = CallingConvention.Cdecl)]public static extern void OneTwoC(ref int a, ref int b);[DllImport("PascalBall.dll", EntryPoint = "TimTam", CallingConvention = CallingConvention.StdCall)]public static extern void OneTwoS(ref int a, ref int b);Why are you specifying EntryPoint = "TimTam"? That function is not the one you are trying to import and has an incompatible signature. Hence the stack imbalance error. You need to export OneTwoS and OneTwoC by adding them to the Delphi exports clause. And you need to import these functions in the C# by removing the erroneous EntryPoint specification. You functions using strings are wrong too and can't be fixed without changing both sides of the code. The simple fix is to use WideString parameters in Delphi, var parameters. Map that to ref string in C#, marshaled as UnmanagedType.BStr. The answer you linked to in comments shows you how: https://stackoverflow.com/a/26043567/495455 这篇关于托管调试助手"PInvokeStackImbalance"已检测到一个...无关紧要的方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!
10-27 09:59