如何编组 void* 参数,它可以是接口中的两个结构之一?
How to marshall out void* argument which can be one of two structs from interface?
我有一个非托管接口,我正尝试在 C# 中编组和使用。
还有一个函数我不确定如何正确编组:
IDataInfo :
public IUnknown {
...
STDMETHOD_(BOOL, GetDataPackInfo) (UINT packIndex, void* pPackExtendedInfo) = 0;
...
}
void*
可以是两种不同结构之一:
struct DataExtendedInfoArchive {
WORD Size;
BOOL Archived;
UINT SignalLength;
BYTE Captured;
};
struct DataExtendedInfoStorage {
WORD Size;
FLOAT SignalFreq;
UINT SignalLength;
CHAR Code[4];
};
我是这样用 C# 实现的:
[StructLayout(LayoutKind.Sequential)]
public struct TrackExtendedInfoAudio
{
int Size;
[MarshalAs(UnmanagedType.Bool)]
bool Archived;
uint SignalLength;
byte Captured;
}
[StructLayout(LayoutKind.Sequential)]
public struct TrackExtendedInfoVideo
{
public int Size;
public double SignalFreq;
public uint SignalLength;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
public StringBuilder Code;
}
问题是我不完全理解我将在 void* pPackExtendedInfo
中得到什么以及如何处理它,因此不知道如何为此函数编写正确的封送处理签名。
您可以将 void*
编组为 IntPtr
:
private static extern bool GetDataPackInfo(uint packIndex, [In,Out] IntPtr pPackExtendedInfo);
并使用 Marshal.PtrToStructure
(and Marshal.StructureToPtr
) 方法之一复制结构:
IntPtr p = IntPtr.Zero;
GetDataPackInfo(..., p);
TrackExtendedInfoAudio audioInfo = Marshal.PtrToStructure<TrackExtendedInfoAudio>(p);
或
TrackExtendedInfoVideo videoInfo = Marshal.PtrToStructure<TrackExtendedInfoVideo>(p);
PS。而且我不确定 StringBuilder
是否适合 CHAR Code[4];
.
托管函数签名(减去属性和装饰)应该是:
// make sure that the return is marshalled as UnmanagedTypes.Boolean.
bool GetDataPackInfo(uint packIndex, IntPtr pPackExtendedInfo);
要解压该结构,首先您需要确定您使用的是哪一个。幸运的是,每个的第一个成员是一个大小参数,它将提供关于结构大小的线索。要读取该大小,然后解压缩结构:
IntPtr ptr; // this is the pointer passed to your callback.
int cbSize = Marshal.ReadInt32(ptr, 0);
if (cbSize = Marshal.SizeOf(TrackExtendedInfoAudio))
{
TrackExtendedInfoAudio s = Marshal.PtrToStructure(ptr, typeof(TrackExtendedInfoAudio))
as TrackExtendedInfoAudio;
// Processing...
}
else if (cbSize == Marshal.SizeOf(TrackExtendedInfoVideo))
{
TrackExtendedInfoVideo s = Marshal.PtrToStructure(ptr, typeof(TrackExtendedInfoVideo))
as TrackExtendedInfoVideo;
// Processing...
}
else
{
// unknown struct
}
我有一个非托管接口,我正尝试在 C# 中编组和使用。
还有一个函数我不确定如何正确编组:
IDataInfo :
public IUnknown {
...
STDMETHOD_(BOOL, GetDataPackInfo) (UINT packIndex, void* pPackExtendedInfo) = 0;
...
}
void*
可以是两种不同结构之一:
struct DataExtendedInfoArchive {
WORD Size;
BOOL Archived;
UINT SignalLength;
BYTE Captured;
};
struct DataExtendedInfoStorage {
WORD Size;
FLOAT SignalFreq;
UINT SignalLength;
CHAR Code[4];
};
我是这样用 C# 实现的:
[StructLayout(LayoutKind.Sequential)]
public struct TrackExtendedInfoAudio
{
int Size;
[MarshalAs(UnmanagedType.Bool)]
bool Archived;
uint SignalLength;
byte Captured;
}
[StructLayout(LayoutKind.Sequential)]
public struct TrackExtendedInfoVideo
{
public int Size;
public double SignalFreq;
public uint SignalLength;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
public StringBuilder Code;
}
问题是我不完全理解我将在 void* pPackExtendedInfo
中得到什么以及如何处理它,因此不知道如何为此函数编写正确的封送处理签名。
您可以将 void*
编组为 IntPtr
:
private static extern bool GetDataPackInfo(uint packIndex, [In,Out] IntPtr pPackExtendedInfo);
并使用 Marshal.PtrToStructure
(and Marshal.StructureToPtr
) 方法之一复制结构:
IntPtr p = IntPtr.Zero;
GetDataPackInfo(..., p);
TrackExtendedInfoAudio audioInfo = Marshal.PtrToStructure<TrackExtendedInfoAudio>(p);
或
TrackExtendedInfoVideo videoInfo = Marshal.PtrToStructure<TrackExtendedInfoVideo>(p);
PS。而且我不确定 StringBuilder
是否适合 CHAR Code[4];
.
托管函数签名(减去属性和装饰)应该是:
// make sure that the return is marshalled as UnmanagedTypes.Boolean.
bool GetDataPackInfo(uint packIndex, IntPtr pPackExtendedInfo);
要解压该结构,首先您需要确定您使用的是哪一个。幸运的是,每个的第一个成员是一个大小参数,它将提供关于结构大小的线索。要读取该大小,然后解压缩结构:
IntPtr ptr; // this is the pointer passed to your callback.
int cbSize = Marshal.ReadInt32(ptr, 0);
if (cbSize = Marshal.SizeOf(TrackExtendedInfoAudio))
{
TrackExtendedInfoAudio s = Marshal.PtrToStructure(ptr, typeof(TrackExtendedInfoAudio))
as TrackExtendedInfoAudio;
// Processing...
}
else if (cbSize == Marshal.SizeOf(TrackExtendedInfoVideo))
{
TrackExtendedInfoVideo s = Marshal.PtrToStructure(ptr, typeof(TrackExtendedInfoVideo))
as TrackExtendedInfoVideo;
// Processing...
}
else
{
// unknown struct
}