c# - 如何将指向 C# 结构的指针传递给 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)
返回类型被强制转换为具有解释的枚举。结构参数无效。我尝试使用 分配内存Marshal.AllocHGlobal(...)
,但参数仍然无效,即编译时没有错误但返回的值不正确。
我在这上面花了好几个小时,仍然不知道该怎么做。已经存在很多类似的问题,例如: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);
推荐阅读
- python - 使用 Python haver 和 R distHaversine 计算距离时的结果差异
- c++ - 在 C++ 中将日志值更改为整数时得到错误答案
- date - odoo13 bad sheded on delivery order 和我在确认销售订单前 13 天收到的报价请求
- r - RStudio 会话无法重新启动或终止
- python - Python转置/堆叠多列
- javascript - 为什么我的重启按钮不起作用?(井字游戏)
- qt - 用鼠标滚动文本 像触摸屏一样单击并按住
- r - mgcv GAM:`by`参数中有多个变量(平滑变化超过1个因子)
- java - Spring Boot Thin Jar gradle 插件不适用于 gradle 7.1
- python - Pandas 数据框按索引选择行,按名称选择列