C# 为什么编组后,数组中只有一个元素包含值? 我从C代码中调用C++函数。而且我使用的是编组,但是当从C++代码返回时,在我的C代码中,只有一个元素填充了这个数组。
C# 为什么编组后,数组中只有一个元素包含值? 我从C代码中调用C++函数。而且我使用的是编组,但是当从C++代码返回时,在我的C代码中,只有一个元素填充了这个数组。,c#,c++,pinvoke,C#,C++,Pinvoke,我的C++结构:< /P> typedef struct DEV_SUB_STATE_ITEM_s { char err_text[NAME_MAX_LENGTH]; uint32_t state; char obj_name[NAME_MAX_LENGTH]; char name[NAME_MAX_LENGTH]; } DEV_SUB_STATE_ITEM_t; C#中的我的结构: 我的C++函数原型: int COMSpClient::GetSubSlotList (UINT32 obj_
我的C++结构:< /P>
typedef struct DEV_SUB_STATE_ITEM_s
{
char err_text[NAME_MAX_LENGTH];
uint32_t state;
char obj_name[NAME_MAX_LENGTH];
char name[NAME_MAX_LENGTH];
} DEV_SUB_STATE_ITEM_t;
C#中的我的结构:
我的C++函数原型:
int COMSpClient::GetSubSlotList (UINT32 obj_rid, DEV_SUB_STATE_ITEM_t** subSlotItems);
我的C#函数原型:
我在C#中的用法:
这是一个稍微笨拙的封送函数。非托管代码分配数组并将指向数组的指针返回给调用方。因此,签名中存在双指针。不能使用p/invoke自动封送 您需要使用一个
IntPtr
,作为out
参数传递,然后自己进行剩余的编组
[DllImport(...)]
public static extern int GetSubSlotList(
IntPtr p_hHandle,
uint obj_rid,
out IntPtr sub_slot_items
);
此时,sub_slot_items
指向数组的第一个元素。然后需要使用Marshal.PtrToStructure
读取每个项目,并在执行过程中增加点数
您可能需要回调非托管代码,要求它释放内存
当然,这很混乱。如果您可以控制接口,更好的设计是让调用方分配数组。代码如下所示:
int COMSpClient::GetSubSlotList(
UINT32 obj_rid,
DEV_SUB_STATE_ITEM_t subSlotItems[]
);
您可能还希望传递数组的长度,除非双方都知道它的其他原因
在C端,代码是:
[DllImport(...)]
public static extern int GetSubSlotList(
IntPtr p_hHandle,
uint obj_rid,
[Out] DEVICE_Sub_State_Item[] sub_slot_items
);
编组到字符串比最初看起来要烦人得多。将字符串封送到固定字节缓冲区,然后像这样构造字符串可能更容易:
public unsafe struct DEVICE_Sub_State_Item
{
public fixed byte err_text[50];
public UInt32 state;
public fixed byte obj_name[50];
public fixed byte name[50];
public string ErrorText
{
get
{
byte[] buffer = new byte[50];
fixed (byte* b = err_text)
Marshal.Copy(new IntPtr(b), buffer, 0, buffer.Length);
return Encoding.UTF8.GetString(buffer);
}
}
}
实际错误文本将作为指针保留在结构中,只有在调用其上的ErrorText
属性时,才会正确读取并转换为字符串
如果您决定这样做,则需要在项目的构建选项下启用不安全代码。但我将在c#中使用[out]参数,因此我可以使用**子脚本项。因为数组指针?抱歉,我不理解这个注释。我在C++中使用了参数子SuxStLoWiTes项,但是C++代码中没有使用输出参数,只是在您的解决方案上使用数组。İ是吗?函数名中的单词“list”很麻烦,看起来它实际上并没有返回列表。如果它返回一个数组,那么基本问题是:客户机代码如何知道数组中有多少个元素?pinvoke marshaller当然不知道,它只能返回一个元素。我确信它会返回一个列表。然后结构应该包含一个字段,该字段是指向列表中下一个元素的指针。没有。C++ C++代码,显示了这个函数如何被调用。是的,但是这个函数正在返回一个数组,它是Struts数组。所以下一个元素不需要指针。我解决了我的问题。每个人都可以在以下链接中找到此解决方案:
int COMSpClient::GetSubSlotList(
UINT32 obj_rid,
DEV_SUB_STATE_ITEM_t subSlotItems[]
);
[DllImport(...)]
public static extern int GetSubSlotList(
IntPtr p_hHandle,
uint obj_rid,
[Out] DEVICE_Sub_State_Item[] sub_slot_items
);
public unsafe struct DEVICE_Sub_State_Item
{
public fixed byte err_text[50];
public UInt32 state;
public fixed byte obj_name[50];
public fixed byte name[50];
public string ErrorText
{
get
{
byte[] buffer = new byte[50];
fixed (byte* b = err_text)
Marshal.Copy(new IntPtr(b), buffer, 0, buffer.Length);
return Encoding.UTF8.GetString(buffer);
}
}
}