如标题所示,我正在尝试编写一些 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/