尝试调用 Dll,但该方法具有复杂的结构类型,我无法在 .Net 中定义它
Posted
技术标签:
【中文标题】尝试调用 Dll,但该方法具有复杂的结构类型,我无法在 .Net 中定义它【英文标题】:Try Call Dll, But the method has a complicated struct type, I can't define it in .Net 【发布时间】:2015-11-02 10:47:08 【问题描述】:C++ 中定义的结构是:
typedef struct _DEVICE_PATH_LIST_
int NumDevice;
TCHAR *devicePath[DEVICE_PATH_LIST_SIZE];
DEVICE_PATH_LIST;
而C++函数的定义是:
LandiWin_iGetDevicePathList( int iDeviceType, DEVICE_PATH_LIST * devicePathList);
然后我想调用那个方法,所以我需要定义一个可以表示DEVICE_PATH_LIST
的struct。这是我在 C# 中的定义:
[StructLayout(LayoutKind.Sequential)]
public unsafe struct DevicePathType
public int NumDevice;
[MarshalAs(UnmanagedType.ByValArray,SizeConst=32)]
public char*[] devicePath;
但这不对,我也尝试了所有其他类型但都失败了。请帮我定义一个正确的结构。
【问题讨论】:
如果需要通过超过 32 台设备怎么办?数据是传递给函数还是由函数返回?认为函数签名完全定义了接口是一个非常常见的错误。您还必须详细说明语义。这样做的一种好方法是在 C++ 中显示示例调用代码。 你的 [MarshalAs] 不错,最好使用 public IntPtr[] devicePath。根据 C 代码的构建方式,使用 Marshal.PtrToStringAnsi() 或 Marshal.PtrToStringUni() 恢复字符串。考虑到您在使用 char* 时遇到问题,可能是 Ansi。请注意,存在内存管理问题,如果调用者需要释放字符串,您可能会泄漏内存。通过调用该方法一百万次来测试它。并且您必须正确使用 CallingConvention,可能是 Cdecl。 @HansPassant,谢谢。当我使用 IntPtr[] 替换 char*[] 时它起作用了 【参考方案1】:C++代码如下:
typedef struct _DEVICE_PATH_LIST_
int NumDevice;
TCHAR *devicePath[DEVICE_PATH_LIST_SIZE];
DEVICE_PATH_LIST;
C#的代码应该是这样的:
[StructLayout(LayoutKind.Sequential)]
public struct DevicePathType
public int NumDevice;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public IntPtr[] devicePath;
【讨论】:
以上是关于尝试调用 Dll,但该方法具有复杂的结构类型,我无法在 .Net 中定义它的主要内容,如果未能解决你的问题,请参考以下文章
JNA 可以用于像 IMAPI 这样的复杂 Windows DLL