从 C++ 获取复杂结构到 C#
Getting a complex struct from C++ to C#
几天前我做了这个问题:
幸运的是,它已经得到解答,代码似乎可以工作。
现在我需要做相反的情况,我的意思是,我需要将结构从 C++ dll 获取到我的 C# 代码。
我正在研究这个网站,尝试使用 IntPtr 类型,但没有成功。然后,由于我在 C# 中的结构被正确定义,我尝试使用 out 引用。
作为总结,将重新发布以两种语言定义的结构
typedef struct _ImParam
{
UINT Format;
UINT Resolution;
UINT ColorDepth;
} IM_PARAM;
typedef struct _sValues
{
UINT Xpos;
UINT Ypos;
UINT Width;
UINT Height;
BOOL Milli;
} S_VALUES;
typedef struct _sProperties
{
BOOL Enable;
S_VALUES Properties;
} S_PROPERTIES;
typedef struct _DevParam
{
BOOL Enable;
UINT Font;
char Symbol;
IM_PARAM Image1;
IM_PARAM Image2;
S_PROPERTIES Properties[10];
UINT FeedMode;
} DevParam;
// more code, comments, etc. etc.
// The function I want to use
BOOL GetParameters( DWORD ID, DevParam *dParam );
这就是我在 C# 中构建结构的方式
[StructLayout(LayoutKind.Sequential)]
public struct ImParam
{
public uint Format;
public uint Resolution;
public uint ColorDepth;
public ImParam(uint n)
{
Format = n;
Resolution = 300;
ColorDepth = 256;
}
};
[StructLayout(LayoutKind.Sequential)]
public struct sValues
{
public uint Xpos;
public uint Ypos;
public uint Width;
public uint Height;
public bool Milli;
public sValues(uint n)
{
Xpos = n;
Ypos = n;
Width = n;
Height = n;
Milli = false;
}
};
[StructLayout(LayoutKind.Sequential)]
public struct sProperties
{
public bool Enable;
public sValues Properties;
public sProperties(int n)
{
Enable = false;
Properties = new sValues(n);
}
};
[StructLayout(LayoutKind.Sequential)]
public struct DevParam
{
public bool Enable;
public uint Font;
public char Symbol;
public ImParam Image1;
public ImParam Image2;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
public sProperties[] Properties;
public uint FeedMode;
public DeviceParameters(int n)
{
Enable = true;
Font = 0;
Symbol = '?';
Image1 = new ImParam(3);
Image2 = new ImParam(3);
Properties = new sProperties[10];
for(int i = 0; i < 10; i++)
Properties[i] = new sProperties(n);
FeedMode = 1;
}
};
// This is the method imported from the C++ dll
[DllImport(path, EntryPoint = "?GetParameters@@YGHKPAU_DevParam@@@Z")]
public static extern bool GetParameters(int ID, out DevParam dParam);
这是电话
// Already got ID from somewhere else
DevParam DP;
bool res = Class1.GetParameters(ID, out DP);
Console.WriteLine("Result: " + res);
代码似乎有效,因为结果是 "true"。问题是它在结构成员中得到了错误的值,放置了默认值(数字总是 0,布尔值总是 false),即使我之前使用 SetParam(..) 方法(而且我知道那个方法有效,因为当我更改图像格式扫描仪会降低扫描速度)。
我错过了什么?
注意:我没有 .dll 的源代码
已编辑:
一直在尝试进行这些修改:
// At the dll wrapper class
[DllImport(path, EntryPoint = "?GetParameters@@YGHKPAU_DevParam@@@Z")]
public static extern bool GetParameters(int ID, ref IntPtr dParam);
// At main
int size = Marshal.SizeOf(typeof(DevParam));
IntPtr Ptr = Marshal.AllocHGlobal(size);
bool res = Class1.GetParameters(ID, ref Ptr);
Console.WriteLine("Result: " + res);
var test = Marshal.PtrToStructure(Ptr, typeof(DevParam));
// No idea what I'll do here
Marshal.FreeHGlobal(Ptr);
如果我尝试打印 "test",它应该给出一个地址,因为它是一个指针,但它是空的。都不知道如何从结构中提取数据。
有什么想法吗?
已解决!
// At the dll wrapper class
[DllImport(path, EntryPoint = "?GetParameters@@YGHKPAU_DevParam@@@Z")]
public static extern bool GetParameters(int ID, IntPtr dParam);
// At main
int size = Marshal.SizeOf(typeof(DevParam));
IntPtr Ptr = Marshal.AllocHGlobal(size);
bool res = Class1.GetParameters(ID, Ptr);
DevParam test = (DevParam)Marshal.PtrToStructure(Ptr, typeof(DevParam));
// For testing purpoises, previously changed the default values with another method
Console.WriteLine(test.Enable);
Marshal.FreeHGlobal(Ptr);
必须删除 ref 关键字。
几天前我做了这个问题:
幸运的是,它已经得到解答,代码似乎可以工作。
现在我需要做相反的情况,我的意思是,我需要将结构从 C++ dll 获取到我的 C# 代码。
我正在研究这个网站,尝试使用 IntPtr 类型,但没有成功。然后,由于我在 C# 中的结构被正确定义,我尝试使用 out 引用。
作为总结,将重新发布以两种语言定义的结构
typedef struct _ImParam
{
UINT Format;
UINT Resolution;
UINT ColorDepth;
} IM_PARAM;
typedef struct _sValues
{
UINT Xpos;
UINT Ypos;
UINT Width;
UINT Height;
BOOL Milli;
} S_VALUES;
typedef struct _sProperties
{
BOOL Enable;
S_VALUES Properties;
} S_PROPERTIES;
typedef struct _DevParam
{
BOOL Enable;
UINT Font;
char Symbol;
IM_PARAM Image1;
IM_PARAM Image2;
S_PROPERTIES Properties[10];
UINT FeedMode;
} DevParam;
// more code, comments, etc. etc.
// The function I want to use
BOOL GetParameters( DWORD ID, DevParam *dParam );
这就是我在 C# 中构建结构的方式
[StructLayout(LayoutKind.Sequential)]
public struct ImParam
{
public uint Format;
public uint Resolution;
public uint ColorDepth;
public ImParam(uint n)
{
Format = n;
Resolution = 300;
ColorDepth = 256;
}
};
[StructLayout(LayoutKind.Sequential)]
public struct sValues
{
public uint Xpos;
public uint Ypos;
public uint Width;
public uint Height;
public bool Milli;
public sValues(uint n)
{
Xpos = n;
Ypos = n;
Width = n;
Height = n;
Milli = false;
}
};
[StructLayout(LayoutKind.Sequential)]
public struct sProperties
{
public bool Enable;
public sValues Properties;
public sProperties(int n)
{
Enable = false;
Properties = new sValues(n);
}
};
[StructLayout(LayoutKind.Sequential)]
public struct DevParam
{
public bool Enable;
public uint Font;
public char Symbol;
public ImParam Image1;
public ImParam Image2;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
public sProperties[] Properties;
public uint FeedMode;
public DeviceParameters(int n)
{
Enable = true;
Font = 0;
Symbol = '?';
Image1 = new ImParam(3);
Image2 = new ImParam(3);
Properties = new sProperties[10];
for(int i = 0; i < 10; i++)
Properties[i] = new sProperties(n);
FeedMode = 1;
}
};
// This is the method imported from the C++ dll
[DllImport(path, EntryPoint = "?GetParameters@@YGHKPAU_DevParam@@@Z")]
public static extern bool GetParameters(int ID, out DevParam dParam);
这是电话
// Already got ID from somewhere else
DevParam DP;
bool res = Class1.GetParameters(ID, out DP);
Console.WriteLine("Result: " + res);
代码似乎有效,因为结果是 "true"。问题是它在结构成员中得到了错误的值,放置了默认值(数字总是 0,布尔值总是 false),即使我之前使用 SetParam(..) 方法(而且我知道那个方法有效,因为当我更改图像格式扫描仪会降低扫描速度)。
我错过了什么?
注意:我没有 .dll 的源代码
已编辑:
一直在尝试进行这些修改:
// At the dll wrapper class
[DllImport(path, EntryPoint = "?GetParameters@@YGHKPAU_DevParam@@@Z")]
public static extern bool GetParameters(int ID, ref IntPtr dParam);
// At main
int size = Marshal.SizeOf(typeof(DevParam));
IntPtr Ptr = Marshal.AllocHGlobal(size);
bool res = Class1.GetParameters(ID, ref Ptr);
Console.WriteLine("Result: " + res);
var test = Marshal.PtrToStructure(Ptr, typeof(DevParam));
// No idea what I'll do here
Marshal.FreeHGlobal(Ptr);
如果我尝试打印 "test",它应该给出一个地址,因为它是一个指针,但它是空的。都不知道如何从结构中提取数据。
有什么想法吗?
已解决!
// At the dll wrapper class
[DllImport(path, EntryPoint = "?GetParameters@@YGHKPAU_DevParam@@@Z")]
public static extern bool GetParameters(int ID, IntPtr dParam);
// At main
int size = Marshal.SizeOf(typeof(DevParam));
IntPtr Ptr = Marshal.AllocHGlobal(size);
bool res = Class1.GetParameters(ID, Ptr);
DevParam test = (DevParam)Marshal.PtrToStructure(Ptr, typeof(DevParam));
// For testing purpoises, previously changed the default values with another method
Console.WriteLine(test.Enable);
Marshal.FreeHGlobal(Ptr);
必须删除 ref 关键字。