0

我有一个调用用 Delphi 编写的 Win32 Dll 的应用程序。我的应用程序是用 C# 开发并在 IIS 下运行的。除了 Windows Server 2012 之外,我可以在 Server 2003 以上的每个 Windows 版本上成功调用 Delphi Dll。对外部方法的调用不会返回任何错误,错误日志中也没有任何内容。它只是从不返回任何数据。

在我的 C# 中,我声明:

[DllImport("MyTest.dll", CharSet = CharSet.Unicode,
       CallingConvention = CallingConvention.StdCall)]
    public static extern void Encrypt(string szPlainText, StringBuilder szCipherText);

然后我使用以下命令调用该函数:

StringBuilder encText = new StringBuilder(128);
StringBuilder plainString = new StringBuilder("test");

Encrypt(plainString.ToString(), encText);

WinServer 2012 中有什么改变会阻止它工作吗?

我可以访问的 Delphi 代码如下所示:

procedure Encrypt(szPlainText: PChar; szCipherText : PChar) ; stdcall ; export;
var
   sTemp : String ;
   sPlainText : String ;
   cipher : TCipher ;

 begin
   cipher := TLogixCipher.Create ;
   sPlainText := szPlainText ;

   sTemp  := cipher.Encrypt(sPlainText ) ;
   StrPCopy(szCipherText,sTemp);    
   FreeAndNil(cipher) ;
 end;
4

1 回答 1

2

注意:此答案是为匹配问题的原始版本而编写的。由于它是编写的,因此问题已更改为包含以下建议的更改。


p/invoke 声明一开始可能是错误的。第一个参数是输入参数(我认为),因此应声明为字符串。我会像这样声明 p/invoke:

public static extern void Encrypt(
    string szPlainText, 
    StringBuilder szCipherText
);

这并不重要,但是当函数返回时将纯文本编组回托管代码几乎没有意义,因为纯文本不会改变。

第二个问题是szCipherText调用前需要在参数中分配缓冲区。

因此,假设您知道缓冲区的长度必须为 100,您可以这样写:

StringBuilder CipherText = new StringBuilder(100);
Encrypt(PlainText, CipherText);

也许这个功能的机制是密文和明文的长度相同。在这种情况下,您的电话将是:

StringBuilder CipherText = new StringBuilder(PlainText.Length);
Encrypt(PlainText, CipherText);

您注意到您调用的函数不会返回任何错误。这并不奇怪,因为它没有这样做的机制。

为什么您的代码现在开始出现异常行为?您已经切换了操作系统,这似乎引起了变化。但这意味着你的代码一直都是错误的,而你之前只是侥幸逃脱。并且您使用的新版本的操作系统恰好与您的错误代码表现不同。


在您进行各种更新后,问题中的代码现在是正确的。这让我怀疑 Delphi 代码确实返回了空字符串。在这种情况下,逻辑结论是cipher.Encrypt返回空字符串。尝试用这个函数替换 Delphi 代码来测试界面:

procedure Encrypt(szPlainText: PChar; szCipherText: PChar); stdcall;
begin
  StrPCopy(szCipherText, szPlainText);    
end;
于 2013-10-11T08:21:57.787 回答