在C#与C++进行交互时,经常需要相互传值,下面就来谈一谈我在传值时遇到的几个问题:
bool值传递,C#传递bool值到C++中时,传递的并非一个字节,而是4个字节,
[StructLayout(LayoutKind.Sequential, Pack = 1), Serializable]
public class classA
{
public Boolean bShowWindow;
public Booleam bBroadCast;
}
ClassA a = new ClassA()
{
bShowWindow = true,
bBroadCast = true
};
正常来说,传递到C++中时, a.bShowWindow =true , a.bBroadCast = true
才对,但实际上,我多次测试都发现 a.bBroadCast = true,a.bShowWindow = false
(这里true,false与想象中的相反是因为C#内存排布的问题),而并非两个都为true
,
详细查看内存后发现,a.bShowWindow
对应的内存全为0,开始怀疑是变量长度的问题,使用[MarshalAs(UnmanagedType.U1)]
强制 两个成员为1字节后,正确传递值;
[MarshalAs(UnmanagedType.U1)]
public Boolean bShowWindow;
[MarshalAs(UnmanagedType.U1)]
public Boolean bBroadCast;
代码里边,bool值是1个字节的
托管代码转非托管代码时,bool是4个字节的
UnmanagedType Enum
emm,不是很清楚为什么这两个地方bool值的长度是不一样的,在没有查明原因前,先记住这个坑
C#向C++传递 char[]数组时,不能使用 char[] a= new char[11]
这种写法,
需要这样:
public class classA
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string IP;
}
下面这种写法会报错,System.Runtime.InteropServices.SafeArrayTypeMismatchException: Specified array was not of the expected type.
public class classA
{
char[] a= new char[16]
}
---2019-08-07补充
public class classA
{
//这种写法是可以的,但是传递字符串的长度要和 属性中声明的长度保持一致
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
char[] a;
}
--
这个解决方案是来自stackoverflow,这里是传送门
-------2019-08-07-------
C++向C#传递字符串时,使用string类型接收时,遇到’\0’会被截断
上面我是使用的
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string IP;
方式向C++传递字符串,传递时没有问题,但是在C++向C#传递字符串时却出现了问题,C++中传递的可能是这样的"aabbccdd\0\0\0"
,但是在C#端接收时却变成了aabbccdd
,后面的'\0'
被自动截断了,当然,若'\0'
出现在开头,接受到的就是空字符串了;
- 解决方案
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16*128)]
public char[] ipList;
此C#中接受到的ipList
字符串就和C++中原有的字符串一致了
- 上面提到了,使用 char[]
向C++传递,字符串时,会产生异常,这是因为,C#填充字符串时没有给出符合长度的字符串,
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public char[] ipList;
ipList="ab".ToCharArray() //可以正常传递
ipList="a".ToCharArray() //会报长度不符的错误