如何将C函数签名转换为C#并在本机DLL中调用该函数?

int __stdcall getProps( /* [ in ] */ void * context, /* [ in ] */ const UINT32 index, /* [ in ] */ WCHAR * const pwszFilterPath, /* [ in, out ]*/ UINT32 * const pFilterPathSizeInCch, /* [ in ]*/ WCHAR * const pwszFilterName, /* [ in, out ] */ UINT32 * const pFilterNameSizeInCch ); 

对于签名在上面的C函数,这是正确的C#签名吗?

 [DllImport("myLib.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode)] public static extern int getProps( IntPtr context, uint index, [MarshalAs(UnmanagedType.LPWStr)] out StringBuilder pwszFilterPath, ref uint pFilterPathSizeInCch, [MarshalAs(UnmanagedType.LPWStr)] out StringBuilder pwszFilterName, ref uint pFilterNameSizeInCch ); 

这里有问题,我不知道(我不知道C#)。 有时当我让它工作时,我在StringBuilder变量中接收ANSI字符串,它们应该包含UNICODE字符。

想法是两次调用此函数。 首先将pwszFilterPath和pwszFilterName设置为NULL,以便检索所需的大小,然后为这两个缓冲区分配内存,然后在第二次调用时检索值。 我知道如何在C / C ++中实现它,而不是在C#中。

您必须从StringBuilder参数中删除out关键字。 普通的StringBuilder参数被编组为指向字符数组的指针。 如果希望本机代码接收NULL ,则传递C# null

 [DllImport("myLib.dll", CharSet = CharSet.Unicode)] public static extern int getProps( IntPtr context, uint index, StringBuilder pwszFilterPath, ref uint pFilterPathSizeInCch, StringBuilder pwszFilterName, ref uint pFilterNameSizeInCch ); 

呼叫模式如下:

  1. null传递给StringBuilder参数以找出缓冲区大小。
  2. 使用接收容量的构造函数重载来分配StringBuilder实例。
  3. 再次调用函数传递StringBuilder实例。

也许是这样的:

 uint filterPathLength = 0; uint filterNameLength int retval = getProps( context, index, null, ref filterPathLength, null, ref filterNameLength ); // check retval StringBuilder filterPath = new StringBuilder(filterPathLength); StringBuilder filterName = new StringBuilder(filterNameLength); int retval = getProps( context, index, filterPath, ref filterPathLength, filterName, ref filterNameLength ); // check retval 

并且您需要确保获得null终止符的长度约定。 我无法判断您的函数是否返回包含null终止符的长度。


正如@Ben指出的那样,您的注释与文本描述不匹配。

 /* [ in ] */ WCHAR * const pwszFilterPath 

[in]应该意味着数据正在流入函数。 如果是这样,那么类型应该是const WCHAR* 。 但事实并非如此。 这是一个out参数。 所以代码应该是:

 /* [ out ] */ WCHAR * const pwszFilterPath