本机 DLL - C#

Jul*_*cki 2 c# delphi dll

我有用 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)。

你有过期吗?谢谢你的帮助

Dav*_*nan 5

返回值为 时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就可以了。

其他选项包括导出释放器或要求调用者分配缓冲区。网络上有很多关于如何实现各种选项的示例。