typedef struct pt_input_bir
{
PT_BYTE byForm;
union {
PT_BIR *pBIR; ///< Used when byForm = PT_FULLBIR_INPUT */
PT_LONG lSlotNr; ///< Used when byForm = PT_SLOT_INPUT */
PT_BYTE abyReserved[20]; /** For future use */
} InputBIR;
} PT_INPUT_BIR
typedef struct pt_bir {
PT_BIR_HEADER Header;
PT_BYTE Data[1];
} PT_BIR
typedef struct pt_bir_header {
PT_DWORD Length;
PT_BYTE HeaderVersion;
PT_BYTE Type;
PT_WORD FormatOwner;
PT_WORD FormatID;
PT_CHAR Quality;
PT_BYTE Purpose;
PT_DWORD FactorsMask;
} PT_BIR_HEADER
,C函数是
PT_STATUS StoreFinger (
IN PT_CONNECTION hConnection,
IN PT_INPUT_BIR *pTemplate,
OUT PT_LONG *plSlotNr
)
现在我需要在C#中为上面的C函数做包装。
我应如何编组PT_INPUT_BIR *结构,以及在返回此函数后如何解组?
请帮我解决这个问题。
/ **********************关于这个问题的更多细节****************** ******** /
C结构和功能在上面定义。请参考那里。
C#Struct:
对于C#struct声明,我为一个C结构提供了两个结构。 bcz one用于设置值,另一个id用于传递给c函数。
C# app struct:
[StructLayout(LayoutKind.Sequential)]//for app
public struct FPINPUTBIR
{
public byte byForm;
public InputBIRType InputBIR;
}
[StructLayout(LayoutKind.Sequential)] // here when i use explicit it throws exception so i removed it.
public struct InputBIRType
{
// [FieldOffset(0)]
public FPBIR pBIR;
//[FieldOffset(0)]
public int lSlotNr;
//[FieldOffset(0)]
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
public byte[] abyReserved;
}
C# wrapper struct:
[StructLayout(LayoutKind.Sequential)]
public struct FP_INPUTBIR
{
public byte byForm;
public IntPtr mIPBIR;
}
[StructLayout(LayoutKind.Explicit, Size = 20, CharSet = CharSet.Ansi)]
public struct Input_BIRType
{
[FieldOffset(0)]
public IntPtr mBIR;
[FieldOffset(0)]
public int lSlotNr;
//[FieldOffset(8)]
//[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
//public byte[] abyReserved;
}
最后我会在调用C fun()
之前将C#app结构中的值复制到包装结构中2a)C#App Side Code是:
//here mAppMemory is already known value
FPINPUTBIR lfipdata = new FPINPUTBIR();
FPDATA lfpdata = new FPDATA();
lfipdata.byForm = (byte)eFPVerifyBy.FULLBIR_INPUT;
lfipdata.InputBIR = new InputBIRType();
lfipdata.InputBIR.abyReserved = new byte[20];
lfipdata.InputBIR.pBIR.Data = new byte[mAppMemory[listBox2.SelectedIndex].Header.Length];
Array.Copy(mAppMemory[listBox2.SelectedIndex].Data, lfipdata.InputBIR.pBIR.Data, mAppMemory[listBox2.SelectedIndex].Header.Length);
lfipdata.InputBIR.pBIR.Header = mAppMemory[listBox2.SelectedIndex].Header;
Verify(ref lfipdata); //calling from C# APP side to C# wrapper
C#包装方:
public int Verify(ref FPINPUTBIR apStoredTemplate )
{
// i passed the args (apStoredTemplate ) but throws exception struct mismatch with C struct.
//here i don't know what should i do.
CDLL.StoreFinger(..,ref apStoredTemplate,.. ); //pls refer the C function above
}
问题:
感谢。
答案 0 :(得分:0)
您只需要对PT_BIR
上一个问题中使用的内容进行一点扩展。在那里,我们将可变长度结构编组为byte[]
。您可以使用相同的代码生成字节数组,但我不会重新访问它。
接下来你需要工会。那就是:
[StructLayout(LayoutKind.Explicit, Size = 20)]
public struct PT_INPUT_BIR_UNION
{
[FieldOffset(0)]
public IntPtr pBIR;
[FieldOffset(0)]
public int lSlotNr; // I'm guessing what PT_LONG is
}
无需声明联盟的保留部分。尺寸照顾到这一点。
然后PT_INPUT_BIR
是
[StructLayout(LayoutKind.Sequential)]
public struct PT_INPUT_BIR
{
Byte byForm;
PT_INPUT_BIR_UNION InputBirUnion;
}
然后,您需要使用GCHandle
来固定PT_BIR
字节数组。让我们保持与该问题相同的命名,并假设PT_BIR
保存在名为byte[]
的{{1}}变量中。
data
当您声明GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
try
{
PT_INPUT_BIR inputBir;
inputBir.byForm := ...;
inputBir.InputBirUnion.pBIR = handle.AddrOfPinnedObject();
// now call StoreFinger passing ref inputBir
}
finally
{
handle.Free();
}
时,StoreFinger
参数应声明为PT_BIR*
。