c# - 如何将 C# 原型(prototype)编写为 P/Invoke 一个以 char* 作为参数并返回其值的函数

标签 c# interop string pinvoke

如标题所示,我正在尝试编写一些 C# 代码以与 C DLL 互操作(它基本上是一个 Windows 设备驱动程序)。 C中的错误码函数签名为:

UINT DLLErrorMsg( DWORD errorCode, char * pBuf, UINT nSize );

nSize 是 pBuf 的大小。如果 nSize 可以容纳错误消息,则将其复制到 pBuf 并返回 0,否则(缓冲区太小并且)返回值是缓冲区容纳错误消息所需的最小大小。

我已经尝试了以下的一些变体:

internal class DLLWrapper
{
    [DllImport(_libName, EntryPoint="DLLErrorMsg", CallingConvention=CallingConvention.Cdecl)]
    public static extern UInt32 GetErrorMessage(UInt32 dwError, ref char * pBuf, UInt32 nBufSize);
}

目前的客户端代码如下所示:

GetError( UInt32 errorCode )
{
    char[] errorMsg = new char[bufSize];            
    UInt32 moreChars = DLLWrapper.GetErrorMessage(errorCode, out errorMsg, bufSize);
    if (moreChars > 0)
    {
        errorMsg = new char[moreChars];
        TWLDLLInterface.GetErrorMessage(errorCode, out errorMsg, moreChars);
    }
}

但是我在调​​用 GetErrorMessage 时遇到异常:

An unhandled exception of type 'System.ArgumentException' occurred in NdevInterface.dll

Additional information: Method's type signature is not Interop compatible.

我也尝试过使用 IntPtr 并尝试使用 Marshal.IntPtrToStringAuto(),但这没有帮助,因为我需要分配缓冲区,而且我显然不能将 char[] 转换为 IntPtr。

我已经尝试通过 MSDN 和一般互联网搜索有关如何执行此操作的提示,但大多数似乎与我正在尝试的有所不同。

我做错了什么?

最佳答案

您可以使用 StringBuilder 对此进行编码。有关详细信息,请参阅 this P/Invoke intro :

[DllImport(_libName, EntryPoint="DLLErrorMsg", CallingConvention=CallingConvention.Cdecl)]
public static extern UInt32 GetErrorMessage(UInt32 dwError, StringBuilder pBuf, UInt32 nBufSize);

只要确保构造的 StringBuilder 有足够的内存来填充 pBuf。

关于c# - 如何将 C# 原型(prototype)编写为 P/Invoke 一个以 char* 作为参数并返回其值的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2209926/

相关文章:

c# - 中等信任度的 ASP.NET MVC

c# - 再锐化。为什么要转换为汽车属性(property)?

c# - Access.DoCMD.RunSQL 错误上的 InteropServices.COMException

Java 从哈希码重新创建字符串

string - 如何在混合元胞数组中找到某个字符串并将其替换为整数?

c# - 无法播放禁用的音频源(Unity 2d)

c# - 从netcore C#控制台应用程序调用rust dll时发生System.BadImageFormatException

C#/C++ 互操作 - 需要帮助定义我的数据结构

c - strcpy () 无法正常工作

c# - Puppeteer 中 LaunchAsync() 的线程安全