字符[] 数组在 C# 中等效
char[] array equivalent in c#
我有一个 C++ 结构,它有如下所示的 char[20],它是打包的。
#pragma pack(push, temp_aion_packed, 1)
struct temp
{
char x[20];
char y[20];
};
#pragma pack(pop, temp_aion_packed)
现在我如何在 C# 中编写此结构,以便两者相同。 我用 C# 写过这样的
[DataContract]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1),Serializable]
public class temp
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public string x;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public string y;
}
下面是 C# 中的 pinvoke 声明
[DllImport("rmsCAPI.dll", CallingConvention = CallingConvention.StdCall, ExactSpelling = true, EntryPoint = "OrderRequirement")]
public static extern int OrderRequirement(ref temp tmp);
将此结构作为参数调用的 C++ 函数
long __stdcall OrderRequirement(struct temp *tmp)
{
string p="";
string q="";
p=temp->x;
q=temp->y;
char buff[2048];
sprintf(buff,"p: %sn q: %sn x: %sn y: %sn",p,q,temp->x,temp->y);
}
但是当我在 C# 中这样做时,当我在 C# 中为它们分配值时,它会在 C++ 中为我提供垃圾数据。任何人都可以协助。
谢谢大家对上述问题的帮助,但现在我遇到了一个新问题,它是这个问题的扩展,我在下面详细介绍了所有内容。
我在 C++ 中的结构
#pragma pack(push, temp_aion_packed, 1)
struct temp
{
long req;
struct type m_type;
short id;
char x[20];
char y[20];
};
#pragma pack(pop, temp_aion_packed)
#pragma pack(push, type_aion_packed, 1)
struct type
{
short i;
};
#pragma pack(pop, type_aion_packed)
我已经编写了这样的等效 C# 结构
[DataContract]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1),Serializable]
public struct temp
{
[DataMember]
public long req;
[DataMember]
[MarshalAs(UnmanagedType.Struct)]
public type m_type;
[DataMember]
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public string x;
[DataMember]
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public string y;
}
[DataContract]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1),Serializable]
public struct type
{
[DataMember]
public short i;
}
下面是我的 C# 拼音
[DllImport("rmsCAPI.dll", CallingConvention = CallingConvention.StdCall, ExactSpelling = true, EntryPoint = "OrderRequirement")]
public static extern int OrderRequirement(ref temp tmp);
下面是我的 C++ 方法,它将结构调用为参数
long __stdcall OrderRequirement(struct temp *tmp)
{
char buff[2048];
sprintf(buff,"req: %ld n id: %d n x: %sn",tmp->req,tmp->id,tmp->x);
}
现在我遇到的问题是因为我在结构 temp 中声明了结构变量m_type(结构"类型"),之前声明的变量(long req)在我的 C++ 程序中打印正常,但之后声明的变量没有给我任何输出。所以我认为 c# 中的结构声明搞砸了,我无法弄清楚,所以任何人都可以帮忙。
您在 C# 中将结构声明为类。这很好,但这意味着该类型的任何变量都已经是引用。所以你不需要经过ref
.当你通过 ref 传递一个类时,你最终会传递一个指向对象的指针。这是一个太多的间接级别。
因此,C# 代码中的 P/invoke 应如下所示:
public static extern int OrderRequirement(temp tmp);
修复它的另一种方法是将ref
保留在函数声明中,但将temp
类型声明为struct
而不是class
。这是因为struct
是一种值类型。类型为结构的变量是值而不是引用。
这两种解决方案都有效,这取决于您的选择。
您的C++代码中还有另一个问题。
sprintf(buff,"p: %sn q: %sn x: %sn y: %sn",p,q,temp->x,temp->y);
您正在传递 p
和 q
,它们属于 std::string
类型printf
,并期望%s
格式字符串来打印它们。这是一个错误。您需要在字符串上调用c_str()
。喜欢这个:
sprintf(
buff,
"p: %sn q: %sn x: %sn y: %sn",
p.c_str(),q.c_str(),temp->x,temp->y
);
更新的问题在于,Windows C++ 中的长度为 32 位,C# 中的长度为 64 位。您需要在 C# 中将其声明为 int
。你完全错过了id
领域。
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1),Serializable]
public struct temp
{
[DataMember]
public int req;
[DataMember]
public type m_type;
[DataMember]
public short id;
[DataMember]
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public string x;
[DataMember]
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public string y;
}
- 指向指向字符数组的指针数组的指针
- 比较字符数组
- 如何使用Crypto++并为RSA返回可打印的字节/字符数组
- 使用无符号字符数组有效存储内存
- 按字符值访问int数组
- 错误:字符数组的初始值设定项太多
- 对字符数组中的元素执行逐位操作
- C++,在int数组中输入字符串或字符会输出0,而不是ascii或error
- C++ 无法在字符数组中使用 for 循环打印字母模式
- 如何在 C++ 中从文件中读取字符数组(带有一些空格)
- 移动二维数组中的字符
- C++ 传递二维字符数组
- 无法在 C++ 中输入字符数组
- C++ 带结构的数组字符
- 数组字符包含量超出预期
- 读取文件并添加到数组字符
- 如何在Qt中更改或替换数组字符
- 为什么编译器不在参数中传递数组字符 *arr[] 的大小?
- 井字棋数组字符错误
- 分割数组字符