我从C#调用一个Delphi函数,得到错误:
托管调试助手“PInvokeStackImbalance”在…中检测到问题。。。
我已经尝试过改变.Net代码以适应Delphi签名,为什么它不能与基本的整数一起使用,这让我很困惑,有人知道我哪里出错了吗?
即使是使用2个整数的最简单函数也会产生错误。
我的目标是x86,并投入了几个小时的研究,但以下解决方案没有帮助
here
,
here
和
here
还有这个
one
.
这是Delphi代码(编译的DLL版本可以从
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 = '' then
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) then exit;
Gate.Enter;
StrP.Insert( I, OutStr);
if I >= 0 then
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
A := 1;
B := 2
end;
procedure OneTwoC( var A, B: integer);
begin
A := 1;
B := 2
end;
procedure OneTwoCS( var A, B: integer);
begin
A := 1;
B := 2
end;
initialization
Gate := TCriticalSection.Create;
Strs := TStringList.Create;
StrP := TList<PChar>.Create
finalization
Strs.Free;
Gate.Free;
StrP.Free
end.
这是.Net代码:
[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)
{
}
}
编辑1:
我
认为
我使用TimTam正确输入了EntryPoint,因为我得到了
系统入口点未找到异常
如果我尝试其他方法,请看这里: