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:

enter image description 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

Popular posts from this blog

javascript - jQuery: Add class depending on URL in the best way -

caching - How to check if a url path exists in the service worker cache -

Redirect to a HTTPS version using .htaccess -