Delphi 11 DLL向.NET 7 C# API返回未知长度字符串求助
Delphi 11 DLL返回字符串给.NET 7 C#的正确实现
核心问题分析
你遇到的所有错误本质上是两个问题:
- 调用约定不匹配:Delphi默认的函数调用约定是
register(快速调用),而你C#中指定的是CallingConvention.StdCall,栈参数传递方式不一致导致栈损坏,引发运行时错误或访问违规。 - 字符串类型兼容性:Delphi私有的
string类型(UnicodeString)无法被CLR识别;直接返回PChar会存在内存分配/释放的所有权问题;WideString本身是COM标准的BStr,但因为调用约定错误才导致报错。
推荐解决方案:使用COM BStr(WideString)
这是跨语言字符串传递最安全的方式,BStr由COM堆分配,CLR可以自动完成内存释放,无需手动管理。
修改后的Delphi代码
library Project1; uses SysUtils; {$R *.res} // 显式指定stdcall调用约定,匹配C#的StdCall function TestWide(aInput: WideString): WideString; stdcall; begin // 可返回任意长度字符串,示例拼接输入内容 Result := 'Delphi返回:' + aInput; end; exports TestWide; begin end.
对应的C#代码
using System.Runtime.InteropServices; internal class Program { [DllImport("Project1.dll", EntryPoint = "TestWide", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode)] [return: MarshalAs(UnmanagedType.BStr)] public static extern string TestWide([MarshalAs(UnmanagedType.BStr)] string input); private static void Main(string[] args) { try { string result = TestWide("Hello from C#"); Console.WriteLine(result); } catch (Exception ex) { Console.WriteLine($"错误:{ex.Message}"); } } }
替代方案:使用CoTaskMemAlloc分配字符串
如果需要返回PChar类型,必须确保内存由CoTaskMemAlloc分配(CLR会自动用CoTaskMemFree释放):
Delphi代码
function TestCoTaskString(aInput: PWideChar): PWideChar; stdcall; var outputStr: WideString; strLen: Integer; begin outputStr := '处理结果:' + aInput; strLen := Length(outputStr) + 1; // 包含终止符 // 用COM堆分配内存 Result := CoTaskMemAlloc(strLen * SizeOf(WideChar)); if Assigned(Result) then StringToWideChar(outputStr, Result, strLen); end; exports TestCoTaskString;
C#代码
[DllImport("Project1.dll", EntryPoint = "TestCoTaskString", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode)] [return: MarshalAs(UnmanagedType.LPWStr)] public static extern string TestCoTaskString(string input);
各测试函数错误原因说明
- TestWide报错(Runtime error 203):调用约定不匹配导致栈损坏,给Delphi函数添加
stdcall修饰符即可解决。 - TestPChar报错:同样是调用约定不匹配,且返回的输入
PChar内存由C#管理,可能已被回收;若Delphi分配PChar,C#无法释放Delphi堆内存,会引发泄漏或错误。 - TestString报错(AccessViolation):Delphi的
string是私有引用计数类型,CLR无法解析其内部结构,直接返回会触发内存访问违规。
内容的提问来源于stack exchange,提问作者Matt Baech
相关产品推荐
相关产品推荐

