从 C# asp.net 调用 Delphi XE6 unicode dll
Call Delphi XE6 unicode dll from C# asp.net
在打开主题之前搜索了更多的回复为我服务,我的错误仍然存在,在 Delphi XE6 64x 中创建了一个 dll,如下所示:
function GeraChave(Action : PAnsiChar; StrCrip : PAnsiChar; Cnpj : PAnsiChar; idPC: PAnsiChar): PAnsiChar; stdcall;
var
KeyLen : Integer;
KeyPos : Integer;
OffSet : Integer;
Dest, Key : String;
SrcPos : Integer;
SrcAsc : Integer;
TmpSrcAsc : Integer;
Range, I : Integer;
matKey : Array[0..7] of String;
begin
if (StrCrip = '') Then
begin
Result:= '';
Exit;
end;
for I := 0 to 8 do
matKey[I] := Copy(idPC, I, 1);
Key := 'A#%tgNh*'+ matKey[0] +'UJklo'+ matKey[1] + 'O' + cnpj + 'O' +
'798DS'+ matKey[2] +'Cea'+ matKey[3] +'SEc%7*I'+ matKey[4] +'u@Ed#'+
matKey[5] +'f$f'+ matKey[6] +'%g&j-9'+ matKey[7] +'sc';
Dest := '';
KeyLen := Length(Key);
KeyPos := 0;
SrcPos := 0;
SrcAsc := 0;
Range := 256;
if (Action = UpperCase('C')) then
begin
Randomize;
OffSet := Random(Range);
Dest := Format('%1.2x',[OffSet]);
for SrcPos := 1 to Length(StrCrip) do
begin
SrcAsc := (Ord(StrCrip[SrcPos]) + OffSet) Mod 255;
if KeyPos < KeyLen then KeyPos := KeyPos + 1 else KeyPos := 1;
SrcAsc := SrcAsc Xor Ord(Key[KeyPos]);
Dest := Dest + Format('%1.2x',[SrcAsc]);
OffSet := SrcAsc;
end;
end
Else if (Action = UpperCase('D')) then
begin
OffSet := StrToInt('$' + copy(StrCrip,1,2));
SrcPos := 3;
repeat
SrcAsc := StrToInt('$' + copy(StrCrip,SrcPos,2));
if (KeyPos < KeyLen) Then KeyPos := KeyPos + 1 else KeyPos := 1;
TmpSrcAsc := SrcAsc Xor Ord(Key[KeyPos]);
if TmpSrcAsc <= OffSet then TmpSrcAsc := 255 + TmpSrcAsc - OffSet
else TmpSrcAsc := TmpSrcAsc - OffSet;
Dest := Dest + Chr(TmpSrcAsc);
OffSet := SrcAsc;
SrcPos := SrcPos + 2;
until (SrcPos >= Length(StrCrip));
end;
Result := PAnsiChar(Dest);
end;
Exports
GeraChave;
begin
end.
我的 C# .NET 代码如下所示:
public partial class _Default : System.Web.UI.Page
{
[DllImport(@"H:\FTP\HOME\Web\testes\dllDelphi\Bin\DllChave.dll",
CallingConvention = CallingConvention.StdCall,
CharSet = CharSet.Ansi)]
public static extern string GeraChave(string xAction, string StrCrip, string Cnpj, string idPC);
protected void Page_Load(object sender, EventArgs e)
{
string str = "A75BD3FD" + "|15/12/2016|" + "04564521020004";
string xTp = "C";
string Cnpj = "04564521020004";
string IDPC = "A75BD3FD";
string xRes = "";
xRes = GeraChave(xTp, str, Cnpj, IDPC);
}
}
而当我调用 DLL 时出现错误 "BadImageFormatException was unhandled by user code"
谢谢!
BadImageFormatException
通常表示位数不匹配。您的 Delphi 模块是 64 位的,而 C# 模块是 32 位的,反之亦然。
您还有其他问题。至少满足以下条件:
- 您将 UTF-16
UnicodeString
字符串转换为 PAnsiChar
。该演员表不正确。
- 你return一个局部变量的地址。当函数 returns 时,局部变量超出范围。因此,您正在 return 指向无效内存的指针。您需要找到另一种方法 return 该缓冲区。
- 您的 C# 代码假定 returned 值是通过调用
CoTaskMemAlloc
分配的。因此,它会在您 return 编辑的指针上调用 CoTaskMemFree
,这显然是错误的。当您解决上述问题时,该问题就会解决。
我可能会 return 字符串作为 WideString
输出参数并将其与 C# 端的 UnmanagedType.BStr
匹配:Why can a WideString not be used as a function return value for interop? 这允许被调用者分配要释放的字符串和调用者。
我是这样决定的:
在 Delphi
function GeraChave(xAction : PChar; StrCrip : PChar; Cnpj : PChar; idPC: PChar; Saida : PChar; len : Integer): Integer; stdcall;
begin
StrLCopy(Saida, PChar(Dest), len);
Result := 1;
end;
在 C# 上
public static extern int GeraChave(string xAction, string StrCrip, string Cnpj, string idPC, StringBuilder Saida, int len);
StringBuilder str = new StringBuilder(256);
int retval = GeraChave(xTp, strCrip, Cnpj, IDPC, str, str.Capacity);
在打开主题之前搜索了更多的回复为我服务,我的错误仍然存在,在 Delphi XE6 64x 中创建了一个 dll,如下所示:
function GeraChave(Action : PAnsiChar; StrCrip : PAnsiChar; Cnpj : PAnsiChar; idPC: PAnsiChar): PAnsiChar; stdcall;
var
KeyLen : Integer;
KeyPos : Integer;
OffSet : Integer;
Dest, Key : String;
SrcPos : Integer;
SrcAsc : Integer;
TmpSrcAsc : Integer;
Range, I : Integer;
matKey : Array[0..7] of String;
begin
if (StrCrip = '') Then
begin
Result:= '';
Exit;
end;
for I := 0 to 8 do
matKey[I] := Copy(idPC, I, 1);
Key := 'A#%tgNh*'+ matKey[0] +'UJklo'+ matKey[1] + 'O' + cnpj + 'O' +
'798DS'+ matKey[2] +'Cea'+ matKey[3] +'SEc%7*I'+ matKey[4] +'u@Ed#'+
matKey[5] +'f$f'+ matKey[6] +'%g&j-9'+ matKey[7] +'sc';
Dest := '';
KeyLen := Length(Key);
KeyPos := 0;
SrcPos := 0;
SrcAsc := 0;
Range := 256;
if (Action = UpperCase('C')) then
begin
Randomize;
OffSet := Random(Range);
Dest := Format('%1.2x',[OffSet]);
for SrcPos := 1 to Length(StrCrip) do
begin
SrcAsc := (Ord(StrCrip[SrcPos]) + OffSet) Mod 255;
if KeyPos < KeyLen then KeyPos := KeyPos + 1 else KeyPos := 1;
SrcAsc := SrcAsc Xor Ord(Key[KeyPos]);
Dest := Dest + Format('%1.2x',[SrcAsc]);
OffSet := SrcAsc;
end;
end
Else if (Action = UpperCase('D')) then
begin
OffSet := StrToInt('$' + copy(StrCrip,1,2));
SrcPos := 3;
repeat
SrcAsc := StrToInt('$' + copy(StrCrip,SrcPos,2));
if (KeyPos < KeyLen) Then KeyPos := KeyPos + 1 else KeyPos := 1;
TmpSrcAsc := SrcAsc Xor Ord(Key[KeyPos]);
if TmpSrcAsc <= OffSet then TmpSrcAsc := 255 + TmpSrcAsc - OffSet
else TmpSrcAsc := TmpSrcAsc - OffSet;
Dest := Dest + Chr(TmpSrcAsc);
OffSet := SrcAsc;
SrcPos := SrcPos + 2;
until (SrcPos >= Length(StrCrip));
end;
Result := PAnsiChar(Dest);
end;
Exports
GeraChave;
begin
end.
我的 C# .NET 代码如下所示:
public partial class _Default : System.Web.UI.Page
{
[DllImport(@"H:\FTP\HOME\Web\testes\dllDelphi\Bin\DllChave.dll",
CallingConvention = CallingConvention.StdCall,
CharSet = CharSet.Ansi)]
public static extern string GeraChave(string xAction, string StrCrip, string Cnpj, string idPC);
protected void Page_Load(object sender, EventArgs e)
{
string str = "A75BD3FD" + "|15/12/2016|" + "04564521020004";
string xTp = "C";
string Cnpj = "04564521020004";
string IDPC = "A75BD3FD";
string xRes = "";
xRes = GeraChave(xTp, str, Cnpj, IDPC);
}
}
而当我调用 DLL 时出现错误 "BadImageFormatException was unhandled by user code"
谢谢!
BadImageFormatException
通常表示位数不匹配。您的 Delphi 模块是 64 位的,而 C# 模块是 32 位的,反之亦然。
您还有其他问题。至少满足以下条件:
- 您将 UTF-16
UnicodeString
字符串转换为PAnsiChar
。该演员表不正确。 - 你return一个局部变量的地址。当函数 returns 时,局部变量超出范围。因此,您正在 return 指向无效内存的指针。您需要找到另一种方法 return 该缓冲区。
- 您的 C# 代码假定 returned 值是通过调用
CoTaskMemAlloc
分配的。因此,它会在您 return 编辑的指针上调用CoTaskMemFree
,这显然是错误的。当您解决上述问题时,该问题就会解决。
我可能会 return 字符串作为 WideString
输出参数并将其与 C# 端的 UnmanagedType.BStr
匹配:Why can a WideString not be used as a function return value for interop? 这允许被调用者分配要释放的字符串和调用者。
我是这样决定的:
在 Delphi
function GeraChave(xAction : PChar; StrCrip : PChar; Cnpj : PChar; idPC: PChar; Saida : PChar; len : Integer): Integer; stdcall;
begin
StrLCopy(Saida, PChar(Dest), len);
Result := 1;
end;
在 C# 上
public static extern int GeraChave(string xAction, string StrCrip, string Cnpj, string idPC, StringBuilder Saida, int len);
StringBuilder str = new StringBuilder(256);
int retval = GeraChave(xTp, strCrip, Cnpj, IDPC, str, str.Capacity);