将字符串从 delphi dll 返回到 c#
Returning string from delphi dll to c#
我正在尝试将一个加密函数从我们的遗留代码中分离到一个我可以从 C# 调用的 dll,但是我在让它工作时遇到了问题,并且在调用 dll 时我一直遇到访问冲突。
我不确定 AV 发生在哪里,因为 delphi 当 dll 附加到另一个进程时很难达到我的断点。
我昨天使用 David Heffernan 的回答让它工作:Returning a string from delphi dll to C# caller in 64 bit
但我的成功是短暂的,因为我将字符串参数更改为常规 string
的 (delphi) 发现它不起作用并将它们更改回 AnsiString
(我们的加密例程期望 Ansi)。因为我改变了这些参数类型。我无法让它再次工作。
这是我的 Delphi 代码:
procedure Encrypt(const Source: AnsiString; const Key: AnsiString; var OutPut:PAnsiChar; const OutputLength: Integer);
var
EncryptedString, EncodedString: AnsiString;
begin
EncryptedString := Crypt(Source, Key);
EncodedString := Encode(EncryptedString);
if Length(EncodedString) <= OutputLength then
System.AnsiStrings.StrPCopy(Output, EncodedString);
end;
exports
Encrypt;
我的 C# 调用者:
[DllImport("AsmEncrypt.dll", CharSet = CharSet.Ansi)]
public static extern void Encrypt(string password, string key, StringBuilder output, int outputlength);
// using like this:
Encrypt(credentials.Password, myKey, str, str.Capacity);
我现在最好的选择是我搞砸了 dll 的一些参数,因为它似乎在到达 OutputDebugStr()
我放在 Encrypt()
[ 的第一行之前就崩溃了=18=]
所有帮助将不胜感激
The AnsiString structure contains a 32-bit length indicator, a 32-bit reference count, a 16-bit data length indicating the number of bytes per character, and a 16-bit code page.
所以 AnsiString
不仅仅是指向字符数组的指针 -- 它是指向编码一堆信息的特殊结构的指针。
然而,.NET 的 P/Invoke 机制将传递一个指向字符数组的指针。 Delphi 将尝试将其解释为指向其特殊 AnsiString 结构的指针,但事情不会顺利进行。
我认为您将很难在互操作中使用 AnsiString
。您最好选择 .NET 和 Delphi 都知道的字符串类型。如果您随后需要将其转换为 AnsiString
,请在 Delphi.
中执行此操作
将Delphi函数更改为
procedure Encrypt(Source, Key, OutPut: PAnsiChar; OutputLength: Integer); stdcall;
为了使此代码正常工作。
您可能还应该设置长度参数 IN/OUT,以便调用者可以在调用 returns 后调整字符串生成器对象的大小。这也将允许被调用者向调用者发出任何错误信号,这是您当前设计中的另一个缺陷。
我还必须说,使用 AnsiString
作为字节数组是失败的秘诀。现在是您开始正确加密的时候了。如果您有文本,则将其编码为具有特定编码的字节数组,通常这意味着 UTF-8。然后将该字节数组加密为另一个字节数组。
我正在尝试将一个加密函数从我们的遗留代码中分离到一个我可以从 C# 调用的 dll,但是我在让它工作时遇到了问题,并且在调用 dll 时我一直遇到访问冲突。
我不确定 AV 发生在哪里,因为 delphi 当 dll 附加到另一个进程时很难达到我的断点。
我昨天使用 David Heffernan 的回答让它工作:Returning a string from delphi dll to C# caller in 64 bit
但我的成功是短暂的,因为我将字符串参数更改为常规 string
的 (delphi) 发现它不起作用并将它们更改回 AnsiString
(我们的加密例程期望 Ansi)。因为我改变了这些参数类型。我无法让它再次工作。
这是我的 Delphi 代码:
procedure Encrypt(const Source: AnsiString; const Key: AnsiString; var OutPut:PAnsiChar; const OutputLength: Integer);
var
EncryptedString, EncodedString: AnsiString;
begin
EncryptedString := Crypt(Source, Key);
EncodedString := Encode(EncryptedString);
if Length(EncodedString) <= OutputLength then
System.AnsiStrings.StrPCopy(Output, EncodedString);
end;
exports
Encrypt;
我的 C# 调用者:
[DllImport("AsmEncrypt.dll", CharSet = CharSet.Ansi)]
public static extern void Encrypt(string password, string key, StringBuilder output, int outputlength);
// using like this:
Encrypt(credentials.Password, myKey, str, str.Capacity);
我现在最好的选择是我搞砸了 dll 的一些参数,因为它似乎在到达 OutputDebugStr()
我放在 Encrypt()
[ 的第一行之前就崩溃了=18=]
所有帮助将不胜感激
The AnsiString structure contains a 32-bit length indicator, a 32-bit reference count, a 16-bit data length indicating the number of bytes per character, and a 16-bit code page.
所以 AnsiString
不仅仅是指向字符数组的指针 -- 它是指向编码一堆信息的特殊结构的指针。
然而,.NET 的 P/Invoke 机制将传递一个指向字符数组的指针。 Delphi 将尝试将其解释为指向其特殊 AnsiString 结构的指针,但事情不会顺利进行。
我认为您将很难在互操作中使用 AnsiString
。您最好选择 .NET 和 Delphi 都知道的字符串类型。如果您随后需要将其转换为 AnsiString
,请在 Delphi.
将Delphi函数更改为
procedure Encrypt(Source, Key, OutPut: PAnsiChar; OutputLength: Integer); stdcall;
为了使此代码正常工作。
您可能还应该设置长度参数 IN/OUT,以便调用者可以在调用 returns 后调整字符串生成器对象的大小。这也将允许被调用者向调用者发出任何错误信号,这是您当前设计中的另一个缺陷。
我还必须说,使用 AnsiString
作为字节数组是失败的秘诀。现在是您开始正确加密的时候了。如果您有文本,则将其编码为具有特定编码的字节数组,通常这意味着 UTF-8。然后将该字节数组加密为另一个字节数组。