Native DLL - C#

本文关键字:DLL Native | 更新日期: 2023-09-27 18:16:23

我在Delphi中编写了本机DLL库。我想从c#中引用这个库并获得返回的字符串。

函数
function GetCode (aUser,aPassword: PAnsiChar): PAnsiChar; stdcall;

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);
}

尝试调用函数应用程序退出,代码为-1073740940 (0xc0000374).

你有这方面的经验吗?谢谢你的帮助

Native DLL - C#

如果返回值为string,则编组程序负责释放返回的字符串。它通过调用CoTaskMemFree来实现。毫无疑问,您的字符串没有在COM堆上分配。由此产生错误,即STATUS_HEAP_CORRUPTIONNTSTATUS错误码。

你的p/调用应该返回一个IntPtr来避免这种情况:

[DllImport("C:''library.dll", CallingConvention = CallingConvention.StdCall,
    CharSet = CharSet.Ansi)]
private static extern IntPtr GetCode(string aUser, string aPassword);

要获取字符串,将返回值传递给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;
}

还要注意,我删除了多余的MarshalAs属性。CharSet.Ansi负责输入参数的编组。

您仍然需要弄清楚如何释放返回的内存。我们不知道它是如何分配的。您需要联系Delphi代码的开发人员,或者阅读源代码。如果使用了本机Delphi堆,请不要感到惊讶,这会使您陷入困境。通过调用CoTaskMemAlloc来使用COM堆实际上是一个不错的选择,然后您的原始p/invoke返回值string就可以了。

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