如何将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 );
呼叫模式如下:
- 将
null
传递给StringBuilder
参数以找出缓冲区大小。 - 使用接收容量的构造函数重载来分配
StringBuilder
实例。 - 再次调用函数传递
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