c# - Managed Debugging Assistant 'PInvokeStackImbalance' has detected a... on trivial method -
i calling delphi function c# , error:
managed debugging assistant 'pinvokestackimbalance' has detected problem in ...
i've exhausted attempts changing .net code fit delphi signatures, why doesn't work basic integers has me stumped, know going wrong?
even simplest function using 2 integers produces error.
i'm targeting x86 , have put in couple of hours research following solutions haven't helped here, here , here , one.
this delphi code (compiled dll version can downloaded here):
unit pasballentry; interface procedure 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; exports entrypoint name 'timtam', releasestring name 'releasestring'; implementation uses 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 = '' outstr := nil else begin outstr := pchar( outstrl); gate.enter; strs.add( outstrl); strp.add( outstr ); gate.leave end end; procedure releasestring( outstr: pchar); var i: integer; begin if not assigned( outstr) exit; gate.enter; strp.insert( i, outstr); if >= 0 begin strp.delete( i); strs.delete( i) end; gate.leave end; 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 := 1; b := 2 end; procedure onetwoc( var a, b: integer); begin := 1; b := 2 end; procedure onetwocs( var a, b: integer); begin := 1; b := 2 end; initialization gate := tcriticalsection.create; strs := tstringlist.create; strp := tlist<pchar>.create finalization strs.free; gate.free; strp.free end.
here .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 = 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: think have entrypoint correct using timtam, because system.entrypointnotfoundexception if try else, see here:
there large number of mistakes here. immediate problem 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 specifying entrypoint = "timtam"
? function not 1 trying import , has incompatible signature. hence stack imbalance error.
you need export onetwos
, onetwoc
adding them delphi exports
clause. , need import these functions in c# removing erroneous entrypoint
specification.
you functions using strings wrong , can't fixed without changing both sides of code. simple fix use widestring
parameters in delphi, var
parameters. map ref string
in c#, marshaled unmanagedtype.bstr
. answer linked in comments shows how: https://stackoverflow.com/a/26043567/495455
Comments
Post a Comment