当前位置: 首页 > news >正文

C#与C++互操作时的数据类型对应

C#和C++在互操作时,会涉及到数据类型对应的问题,如果数据类型用得不对,就会得不到想要的结果,严重的情况下,可能还会导致程序崩溃。这里做一下相关知识点的总结。

说明:

1. 表格第一列是Visual C++中的数据类型,第二列是标准C中的数据类型

2. 表格第三列括号中显示的是别名(关键字)。

3. 关于使用string还是StringBuilder,可以参考P/Invoke各种总结(三、与字符串交互char*,wchar_t*) - zhaotianff - 博客园

VC++Ansi CC#(CTS)说明
VOIDvoidSystem.Void(void)void类型,代表函数无返回值。在C++里函数无参数也可以传入void,在C#里不这么做。
HANDLEvoid *System.IntPtr or System.UIntPtr长度:32位(32位系统), 64位(64位系统)
BYTEunsigned charSystem.Byte(byte)长度:8位
SHORTshortSystem.Int16(short)长度:16位
WORDunsigned shortSystem.UInt16(ushort)长度:16 位
INTintSystem.Int32(int)长度:32 位
UINTunsigned intSystem.UInt32(uint)长度:32 位
LONGlongSystem.Int32(int)长度:32 位
BOOLlongSystem.Boolean(bool) or System.Int32(int)长度:32 位
DWORDunsigned longSystem.UInt32(uint)长度:32 位
ULONGunsigned longSystem.UInt32(uint)长度:32 位
CHARcharSystem.Char(char)字符集:ANSI(多字节)
WCHARwchar_tSystem.Char(char)字符集:Unicode(宽字符)
LPSTRchar *System.String(string) or System.Text.StringBuilder字符集:ANSI(多字节)
LPCSTRconst char *System.String(string) or System.Text.StringBuilder字符集:ANSI(多字节)
LPWSTRwchar_t *System.String(string) or System.Text.StringBuilder字符集:Unicode(宽字符)
LPCWSTRconst wchar_t *System.String(string) or System.Text.StringBuilder字符集:Unicode(宽字符)
FLOATfloatSystem.Single(float)长度:32 位
DOUBLEdoubleSystem.Double(double)长度:64 位

4. 如果启用了“允许不安全代码”,可以使用指针类型来代替System.IntPtr or System.UIntPtr

一般情况下,推荐使用System.IntPtr or System.UIntPtr类,但是如果需要进行指针偏移,就一定要用指针类型,而不是System.IntPtr or System.UIntPtr。

下面的示例代码将会说明第4点。

一、使用IntPtr的情况

使用C++创建共享内存并写入数据(示例代码,仅供参考)

 1     RECT rect{ 100,100,100,100 };2     auto len = sizeof(rect);3 4     HANDLE m_handle = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_EXECUTE_READWRITE, 0, MemorySize, "HelloWorld");5     if (m_handle != NULL)6     {7         PVOID m_pView = MapViewOfFile(m_handle, FILE_MAP_ALL_ACCESS, 0, 0, MemorySize);8         if (m_pView != NULL)9         {
10             memcpy_s(m_pView, MemorySize, (void *)&rect, len);        
11 
12             //程序退出时的资源释放操作
13             //.......
14         }
15     }

使用C#读出

 1             IntPtr withoutOffsetPtr = OpenFileMapping(FILE_MAP_READ, false, "HelloWorld");2             IntPtr mapView = MapViewOfFile(withoutOffsetPtr, FILE_MAP_READ, 0, 0, MemorySize);3             Rect rect = new Rect();4             var size = Marshal.SizeOf(rect);5             IntPtr ptr = Marshal.AllocHGlobal(size);       //往IntPtr里拷贝数据需要提前分配空间,否则会报错6             byte[] buffer = new byte[size];7             Marshal.Copy(mapView, buffer, 0, size);        //先拷贝到字节数组8             Marshal.Copy(buffer, 0, ptr, size);            //再拷贝到IntPtr9             var obj = Marshal.PtrToStructure(ptr, typeof(Rect));  //将IntPtr转换成结构体
10             rect = (Rect)obj;
11 
12             Console.WriteLine($"Rect:left={rect.left},top={rect.top},right={rect.right},bottom={rect.bottom}");

复制代码

二、使用指针的情况

使用C++创建共享内存并写入数据

复制代码

 1     RECT rect{ 10,10,10,10 };2     POINT point{ 3,3 };3     auto len = sizeof(rect);4 5     HANDLE m_handle = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_EXECUTE_READWRITE, 0, MemorySize, "HelloWorld2");6     if (m_handle != NULL)7     {8         PVOID m_pView = MapViewOfFile(m_handle, FILE_MAP_ALL_ACCESS, 0, 0, MemorySize);9         if (m_pView != NULL)
10         {
11             //先写入rect
12             memcpy_s(m_pView, MemorySize,(void *)&rect, len);
13 
14             char* p = (char *)m_pView;
15             p = p + len;
16             m_pView = (void *)p;
17 
18             //再写入Point
19             memcpy_s(m_pView, MemorySize,(void *)&point, sizeof(point));
20             
21             //程序退出时的资源释放操作
22             //.......
23         }
24     }

使用C#读出(由于在写入Point数据时,指针的位置已经不是当初映射出来的起点了,要偏移,就需要使用指针)

 1             //这一部分操作跟上面函数是一样的2             IntPtr withoutOffsetPtr = OpenFileMapping(FILE_MAP_READ, false, "HelloWorld2");3             IntPtr mapView = MapViewOfFile(withoutOffsetPtr, FILE_MAP_READ, 0, 0, MemorySize);4             Rect rect = new Rect();5             var size = Marshal.SizeOf(rect);6             IntPtr ptr = Marshal.AllocHGlobal(size);7             byte[] buffer = new byte[size];8             Marshal.Copy(mapView, buffer, 0, size);9             Marshal.Copy(buffer, 0, ptr, size);
10             var obj = Marshal.PtrToStructure(ptr, typeof(Rect));
11             rect = (Rect)obj;
12 
13             Console.WriteLine($"Rect:left={rect.left},top={rect.top},right={rect.right},bottom={rect.bottom}");
14 
15             //使用指针
16             unsafe
17             {
18                 byte* b = (byte*)mapView;
19                 b += size;
20                 mapView = (IntPtr)b;
21             }
22 
23             //读取Point结构的值
24             Point point = new Point();
25             size = Marshal.SizeOf(point);
26             ptr = Marshal.AllocHGlobal(size);
27             buffer = new byte[size];
28             Marshal.Copy(mapView, buffer, 0, size);
29             Marshal.Copy(buffer, 0, ptr, size);
30             obj = Marshal.PtrToStructure(ptr, typeof(Point));
31             point = (Point)obj;
32 
33             Console.WriteLine($"Point:x={point.x},y={point.y}");

 示例代码


http://www.mrgr.cn/news/60771.html

相关文章:

  • Java-I/O框架04:对象流、序列化、反序列化及注意事项
  • 智慧停车场导航系统架构及反向寻车系统解决方案
  • PH47代码框架功能速查
  • 关于ETL的两种架构(ETL架构和ELT架构)
  • OOP特性 多态
  • 【Docker】Dockerfile 用于组装镜像的指令都有啥?
  • 00 嵌入式知识-目录篇
  • 以通俗易懂的仓库来讲解JVM内存模型
  • C++ 中的可调用对象
  • 一文学会Matrix类的用法
  • 循环神经网络(Recurrent Neural Network,RNN)
  • 4个硬盘数据修复攻略:让你的数据失而复得。
  • 同一个Service内部调用开启事务
  • Python多语双峰分布
  • 练习LabVIEW第二十四题
  • Unity Job System详解(3)——NativeArray源码分析
  • 100种算法【Python版】第21篇——Wilson算法
  • Java Lock CountDownLatch 总结
  • 李宇皓现身第十届“文荣奖”,allblack造型帅气绅士引关注
  • 加强版 第一节图像二值化定义
  • 四、常量指针其他
  • 信创认证(信创人才考评证书)的含金量?到底有多少?
  • 【Flask】三、Flask 常见项目架构
  • IPV6扩展头部
  • SQL进阶技巧:Hive如何进行更新和删除操作?
  • 自修室预约系统|基于java和小程序的自修室预约系统设计与实现(源码+数据库+文档)