You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#调用Delphi加密DLL返回字符串时出现访问违规问题求助

错误原因

  1. 你在导出函数的参数中使用了Delphi专有的AnsiString类型,该类型的内存布局、生命周期管理都是Delphi runtime私有的,C#互操作封送器无法正确识别,参数传递阶段就会触发内存访问错误,这是你函数入口断点还没触发就崩溃的核心原因。
  2. Delphi侧Output参数错误添加了var修饰符:var PAnsiChar等价于指向字符指针的二级指针,而C#传入的StringBuilder封送后是一级字符指针,参数类型不匹配。
  3. 导出函数未显式指定调用约定,Delphi默认调用约定为register,C#平台调用默认约定为stdcall,约定不一致会导致栈内存失衡。

修复方案

Delphi侧代码修改

// 所有参数使用标准C兼容类型,显式指定stdcall调用约定
procedure Encrypt(const Source: PAnsiChar; const Key: PAnsiChar; OutPut: PAnsiChar; const OutputLength: Integer); stdcall;
var
  EncryptedString, EncodedString: AnsiString;
begin
  // 内部逻辑依然可以用AnsiString,仅需把输入的PAnsiChar做转换即可
  EncryptedString := Crypt(AnsiString(Source), AnsiString(Key));
  EncodedString := Encode(EncryptedString);
  if Length(EncodedString) <= OutputLength then
    System.AnsiStrings.StrPCopy(Output, EncodedString);
end;

exports
  Encrypt;

C#侧代码修改

// 显式指定调用约定匹配Delphi侧的stdcall
[DllImport("AsmEncrypt.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public static extern void Encrypt(string password, string key, StringBuilder output, int outputlength);

// 调用前请确保StringBuilder初始化了足够的容量,容量需要大于加密输出的最大可能长度
// 示例:StringBuilder str = new StringBuilder(512);
Encrypt(credentials.Password, myKey, str, str.Capacity);

额外校验点

  • 确保Delphi编译DLL的目标平台(x86/x64)和C#项目的目标平台完全一致,不要使用Any CPU配置。
  • 不需要引入ShareMem单元,该方案中输出内存由C#侧的StringBuilder分配,不存在跨运行时内存释放的问题。

内容的提问来源于stack exchange,提问作者Matt Baech

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 04:45:02