我有用 Delphi 编写的本机 DLL 库。我想从 C# 引用这个库并获取返回的字符串。
功能
function GetCode (aUser,aPassword: PAnsiChar): PAnsiChar; stdcall;
Run Code Online (Sandbox Code Playgroud)
C# 代码
[DllImport("C:\\library.dll", CallingConvention = CallingConvention.StdCall,
CharSet = CharSet.Ansi)]
private static extern String GetCode([MarshalAs(UnmanagedType.LPStr)]string aUser, [MarshalAs(UnmanagedType.LPStr)]string aPassword);
public String getCode(String login, String password) {
return GetCode(login, password);
}
Run Code Online (Sandbox Code Playgroud)
尝试调用函数应用程序退出,代码为-1073740940 (0xc0000374)。
你有过期吗?谢谢你的帮助
返回值为 时string,编组器承担释放返回字符串的责任。它通过调用来实现这一点CoTaskMemFree。毫无疑问,您的字符串没有在 COM 堆上分配。因此会出现错误,即 的NTSTATUS错误代码STATUS_HEAP_CORRUPTION。
你的 p/invoke 应该返回一个IntPtr来避免这种情况:
[DllImport("C:\\library.dll", CallingConvention = CallingConvention.StdCall,
CharSet = CharSet.Ansi)]
private static extern IntPtr GetCode(string aUser, string aPassword);
Run Code Online (Sandbox Code Playgroud)
要获取字符串,请将返回值传递给Marshal.PtrToStringAnsi。
public string getCode(string login, string password)
{
IntPtr retval = GetCode(login, password);
string result = Marshal.PtrToStringAnsi(retval);
// how do we deallocate retval
return result;
}
Run Code Online (Sandbox Code Playgroud)
另请注意,我删除了多余的MarshalAs属性。CharSet.Ansi负责输入参数编组。
您仍然需要弄清楚如何释放返回的内存。我们无法得知它是如何分配的。您需要联系 Delphi 代码的开发人员,或阅读源代码。如果使用本机 Delphi 堆,请不要感到惊讶,这会让您陷入困境。通过调用使用 COM 堆CoTaskMemAlloc实际上不是一个坏选择,然后你原来的 p/invoke 返回值string就可以了。
其他选项包括导出释放器或要求调用者分配缓冲区。网络上有很多关于如何实现各种选项的示例。
| 归档时间: |
|
| 查看次数: |
359 次 |
| 最近记录: |