如何将指向 C# 结构的指针传递给 C 中的方法
how to pass a pointer to C# struct to a method in C
我想在 C# 中使用 C++ DLL。我正在使用 [DllImport]
来调用该方法。我在将结构传递给方法时遇到问题。
我有一个 C 结构:
typedef struct
{
DWORD TopPoint;
DWORD EndPoint;
WORD dwCount;
MYFUNC_NUMERIC11 *pGetData;
} MYFUNC_BUFFERNORMAL;
MYFUNC_NYMERIC11
是另一个结构。
typedef struct
{
BYTE Sign; // Sign ("±")
BYTE Integer[3]; // 3-digit integer (no zero suppression)
BYTE Period; // Decimal point (".")
BYTE Decimal[6]; // 6-digit decimal number
} MYFUNC_NUMERIC11;
我已经编写了一个 C# 结构来模仿这个。
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public unsafe struct MYFUNC_BUFFERNORMAL
{
public uint TopPoint;
public uint EndPoint;
public ushort Count;
public IntPtr pGetData;
}
指向结构的指针是方法中的参数。 C# 函数是:
[DllImport("MYFUNC_DLL.dll", EntryPoint = "MYFUNC_GetData", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall, ThrowOnUnmappableChar = true)]
public static extern int MYFUNC_GetData(IntPtr myfuncHandle, UInt32 dwIO, ref IntPtr pBufferNormal, Byte bccFlg);
这是C:
中的方法
MYFUNC_STATUS MYFUNC_GetData(MYFUNC_HANDLE myfuncHandle, DWORD dwOut, MYFUNC_BUFFERNORMAL *pBufferNormal , BYTE bccFlg)
return 类型被强制转换为一个枚举,它有一个解释。结构参数无效。我尝试过使用Marshal.AllocHGlobal(...)
分配内存,但参数仍然无效,即编译期间没有错误,但值returned不正确。
我在这上面花了好几个小时,仍然不知道该怎么做。已经存在很多类似的问题,比如这里:How do I convert c struct from dll to C# or here: How to pass C# array to C++ and return it back to C# with additional items?,但不知何故,我仍然没有想出办法。
像这样的东西应该可以工作,至少对于数组中的一个元素(它是一个数组吗?)。对于数组,您将必须分配 sizeof * count
个元素,并在其偏移处编组 (StructureToPtr) 每个元素。
var num = new MYFUNC_NUMERIC11();
num.Integer = new byte[] { 1, 2, 3 };
num.Decimal = new byte[] { 4, 5, 6, 7, 8, 9 };
num.Sign = 10;
num.Period = 11;
var buffer = new MYFUNC_BUFFERNORMAL();
buffer.Count = 1234;
buffer.EndPoint = 5678;
buffer.TopPoint = 9;
buffer.pGetData = Marshal.AllocCoTaskMem(Marshal.SizeOf(num));
try
{
Marshal.StructureToPtr(num, buffer.pGetData, false);
MYFUNC_GetData(Whatever, 0, ref buffer, 0);
}
finally
{
Marshal.FreeCoTaskMem(buffer.pGetData);
}
有了这些定义。
[StructLayout(LayoutKind.Sequential)]
public struct MYFUNC_BUFFERNORMAL
{
public uint TopPoint;
public uint EndPoint;
public ushort Count;
public IntPtr pGetData;
}
[StructLayout(LayoutKind.Sequential)]
public struct MYFUNC_NUMERIC11
{
public byte Sign;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] Integer;
public byte Period;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
public byte[] Decimal;
}
// check calling convention
[DllImport(@"MYFUNC_DLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern MYFUNC_STATUS MYFUNC_GetData(IntPtr myfuncHandle, uint dwIO, ref MYFUNC_BUFFERNORMAL pBufferNormal, byte bccFlg);
我想在 C# 中使用 C++ DLL。我正在使用 [DllImport]
来调用该方法。我在将结构传递给方法时遇到问题。
我有一个 C 结构:
typedef struct
{
DWORD TopPoint;
DWORD EndPoint;
WORD dwCount;
MYFUNC_NUMERIC11 *pGetData;
} MYFUNC_BUFFERNORMAL;
MYFUNC_NYMERIC11
是另一个结构。
typedef struct
{
BYTE Sign; // Sign ("±")
BYTE Integer[3]; // 3-digit integer (no zero suppression)
BYTE Period; // Decimal point (".")
BYTE Decimal[6]; // 6-digit decimal number
} MYFUNC_NUMERIC11;
我已经编写了一个 C# 结构来模仿这个。
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public unsafe struct MYFUNC_BUFFERNORMAL
{
public uint TopPoint;
public uint EndPoint;
public ushort Count;
public IntPtr pGetData;
}
指向结构的指针是方法中的参数。 C# 函数是:
[DllImport("MYFUNC_DLL.dll", EntryPoint = "MYFUNC_GetData", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall, ThrowOnUnmappableChar = true)]
public static extern int MYFUNC_GetData(IntPtr myfuncHandle, UInt32 dwIO, ref IntPtr pBufferNormal, Byte bccFlg);
这是C:
中的方法MYFUNC_STATUS MYFUNC_GetData(MYFUNC_HANDLE myfuncHandle, DWORD dwOut, MYFUNC_BUFFERNORMAL *pBufferNormal , BYTE bccFlg)
return 类型被强制转换为一个枚举,它有一个解释。结构参数无效。我尝试过使用Marshal.AllocHGlobal(...)
分配内存,但参数仍然无效,即编译期间没有错误,但值returned不正确。
我在这上面花了好几个小时,仍然不知道该怎么做。已经存在很多类似的问题,比如这里:How do I convert c struct from dll to C# or here: How to pass C# array to C++ and return it back to C# with additional items?,但不知何故,我仍然没有想出办法。
像这样的东西应该可以工作,至少对于数组中的一个元素(它是一个数组吗?)。对于数组,您将必须分配 sizeof * count
个元素,并在其偏移处编组 (StructureToPtr) 每个元素。
var num = new MYFUNC_NUMERIC11();
num.Integer = new byte[] { 1, 2, 3 };
num.Decimal = new byte[] { 4, 5, 6, 7, 8, 9 };
num.Sign = 10;
num.Period = 11;
var buffer = new MYFUNC_BUFFERNORMAL();
buffer.Count = 1234;
buffer.EndPoint = 5678;
buffer.TopPoint = 9;
buffer.pGetData = Marshal.AllocCoTaskMem(Marshal.SizeOf(num));
try
{
Marshal.StructureToPtr(num, buffer.pGetData, false);
MYFUNC_GetData(Whatever, 0, ref buffer, 0);
}
finally
{
Marshal.FreeCoTaskMem(buffer.pGetData);
}
有了这些定义。
[StructLayout(LayoutKind.Sequential)]
public struct MYFUNC_BUFFERNORMAL
{
public uint TopPoint;
public uint EndPoint;
public ushort Count;
public IntPtr pGetData;
}
[StructLayout(LayoutKind.Sequential)]
public struct MYFUNC_NUMERIC11
{
public byte Sign;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] Integer;
public byte Period;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
public byte[] Decimal;
}
// check calling convention
[DllImport(@"MYFUNC_DLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern MYFUNC_STATUS MYFUNC_GetData(IntPtr myfuncHandle, uint dwIO, ref MYFUNC_BUFFERNORMAL pBufferNormal, byte bccFlg);