在使用结构体指针,进行C#和C++的互相调用。边界对齐是一个大问题,因为边界对齐问题,结构体的成员并不是顺序在内存一个挨着一个的排序。

而且在C++中可以使用#pragma pack(n)改变边界对齐的方案,那C#的结构体怎么对应C++的结构体那?(什么是边界对齐,这里不解释,

不懂得可以去看看C++基本编程之类的书好好恶补一下.)

第一:最普通的情况下,C++代码没有使用#pragma pack(n)改变边界对齐,这里C#可以使用两种方法处理,LayoutKind.Explicit 和

LayoutKind.Sequential,建议使用后者,虽然前者是万金油,不过使用起来太累有爱出错。

C++:

1 struct Test1
2 {
3 int test1;
4 char test2;
5 __int64 test3;
6 short test4;
7 };
8
9 Test1 * __stdcall GetTest1()
10 {
11 test1.test1 = 10;
12 test1.test2 = 11;
13 test1.test3 = 12;
14 test1.test4 = 13;
15 return &test1;
16 }

C#:(这里有两种方案,使用LayoutKind.Explicit 和LayoutKind.Sequential,注意一下)

1 [StructLayout(LayoutKind.Explicit)]
2 public struct Test
3 {
4 [FieldOffset(0)]
5 public int test1;
6 [FieldOffset(4)]
7 public char test2;
8 [FieldOffset(8)]
9 public Int64 test3;
10 [FieldOffset(16)]
11 public short test4;
12 }
13
14 [StructLayout(LayoutKind.Sequential)]
15 public struct Test1
16 {
17 public int test1;
18 public char test2;
19 public Int64 test3;
20 public short test4;
21 }
22
23 [DllImport("TestDll")]
24 public static extern IntPtr GetTest1();
25
26 //#################################
27   IntPtr p = GetTest1();
28 Test test = (Test)Marshal.PtrToStructure(p, typeof(Test));
29 Console.WriteLine(test.test1 + test.test2 + test.test3 + test.test4);
30
31 IntPtr p1 = GetTest1(); //Auto pack
32   Test1 test1 = (Test1)Marshal.PtrToStructure(p1, typeof(Test1));
33 Console.WriteLine(test1.test1 + test1.test2 + test1.test3 + test1.test4);

第二:特殊的情况下,C++代码使用#pragma pack(n)改变了边界对齐。这里要使用C#要使用   [StructLayout(LayoutKind.Sequential, Pack = N)] 对齐,否则出错。
C++:

1 #pragma pack(1)
2  struct Test2
3 {
4 int test1;
5 char test2;
6 __int64 test3;
7 short test4;
8 };
9  #pragma pack()
10
11  #pragma pack(2)
12  struct Test3
13 {
14 int test1;
15 char test2;
16 __int64 test3;
17 short test4;
18 };
19  #pragma pack()
20
21
22  #pragma pack(4)
23  struct Test4
24 {
25 int test1;
26 char test2;
27 __int64 test3;
28 short test4;
29 };
30  #pragma pack()

C#:

1 [StructLayout(LayoutKind.Sequential, Pack = 1)]
2 struct Test2
3 {
4 public int test1;
5 public char test2;
6 public Int64 test3;
7 public short test4;
8 }
9
10 [StructLayout(LayoutKind.Sequential, Pack = 2)]
11 struct Test3
12 {
13 public int test1;
14 public char test2;
15 public Int64 test3;
16 public short test4;
17 }
18
19 [StructLayout(LayoutKind.Sequential, Pack = 4)]
20 struct Test4
21 {
22 public int test1;
23 public char test2;
24 public Int64 test3;
25 public short test4;
26 }
27
28
29 [DllImport("TestDll")]
30 public static extern IntPtr GetTest2();
31
32 [DllImport("TestDll")]
33 public static extern IntPtr GetTest3();
34
35 [DllImport("TestDll")]
36 public static extern IntPtr GetTest4();
37
38 //#################################
39   IntPtr p2 = GetTest2(); //pack 1
40   Test2 test2 = (Test2)Marshal.PtrToStructure(p2, typeof(Test2));
41
42 IntPtr p3 = GetTest3(); //pack 2
43   Test3 test3 = (Test3)Marshal.PtrToStructure(p3, typeof(Test3));
44
45 IntPtr p4 = GetTest4(); //pack4
46   Test4 test4 = (Test4)Marshal.PtrToStructure(p4, typeof(Test4));
47
48 Console.WriteLine(test2.test1 + test2.test2 + test2.test3 + test2.test4);
49 Console.WriteLine(test3.test1 + test3.test2 + test3.test3 + test3.test4);
50 Console.WriteLine(test4.test1 + test4.test2 + test4.test3 + test4.test4);

最后总结一下,LayoutKind有3个枚举值。LayoutKind.Auto ,LayoutKind.Explicit 和LayoutKind.Sequential.LayoutKind.Auto或者为使用LayoutKind属性的结构体,

进行P-INVOKE调用会抛出异常,改类型不允许进行P-INVOKE调用,LayoutKind.Sequential在内存中顺序布局,一般情况(上面两种)推荐用这个。LayoutKind.Explicit

只推荐特殊情况使用,因为他会明确指定成员的内存offset,很强大也很繁琐。

下载:下载

转载于:https://www.cnblogs.com/namek/archive/2010/08/26/1808773.html

c#编程指南(十二) 平台调用P-INVOKE完全掌握, 结构体边界对齐和内存布局相关推荐

  1. ffmpeg源码简析(十二)FFMPEG中的主要结构体总结

    FFMPEG中结构体很多.最关键的结构体可以分成以下几类: a) 解协议(http,rtsp,rtmp,mms) AVIOContext,URLProtocol,URLContext主要存储视音频使用 ...

  2. Beej网络编程指南《二》

    Beej网络编程指南<二> 6客户端-服务器背景 这是一个客户机-服务器的世界,宝贝.网络上几乎所有的东西都处理客户机进程与服务器进程之间的对话,反之亦然.以telnet为例.当你用tel ...

  3. 并发编程指南(二)Dispatch Queue

    Dispatch Queues Grand Central Dispatch(GCD)调度队列是执行任务的强大工具. 通过调度队列,您可以相对于调用者异步或同步地执行任意代码块. 您可以使用调度队列执 ...

  4. Python界面编程第十二课:Pyside2 (Qt For Python)布局管理QVBoxLayout 和 QHBoxLayout

    QHBoxLayout用于构造水平框布局对象,QVBoxLayout用于构造垂直框布局对象. 先看完整代码: from PySide2.QtWidgets import QApplication, Q ...

  5. c语言中编程称量十二个小球的质量,c语言题:现有十二个小球,其中一个小球的重量与其... 有12个外观相同的小球,其中11个是标准球,质量完......

    导航:网站首页 > c语言题:现有十二个小球,其中一个小球的重量与其... 有12个外观相同的小球,其中11个是标准球,质量完... c语言题:现有十二个小球,其中一个小球的重量与其... 有1 ...

  6. 【软件开发底层知识修炼】二十五 ABI之函数调用约定二之函数返回值为结构体时的约定

    上一篇文章学习了几种函数调用约定的区别,点击链接查看上一篇文章:[软件开发底层知识修炼]二十四 ABI之函数调用约定 本篇文章继续学习函数调用约定中,关于函数返回值的问题.当函数返回值为结构体时,函数 ...

  7. CorelDRAWX4的C++插件开发(四十)纯C++插件开发(4)继承插件结构体IVGAppPlugin和自动化接口IDispatch

    因为在注册插件的时候,是要传一个名为IDispatch*这样子的一个参数,所以我们可以看到插件在注册的时候默认就是要求这是一个实现了自动化的接口(IDispatch,如下图所示,是后面将要展示的代码, ...

  8. c语言构造体二维数组,怎么才能把结构体里面的二维数组打印出来?

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 萌新一位,学到结构体在做作业,遇到了这个问题.求提示 出现这样的报错:[Error] cannot convert 'char (*)[20]' to ' ...

  9. 欢迎来到Jsp编程课时十二——今天实现的目标是。@1将数据库的数据发送到浏览器。@2利用浏览器实现对数据库的增删改查操作。@3理解MVC三层架构的定义。

    完成项目会有以下的效果. JSP第二十课:Mvc+Mysql+Servlect+Jsp实现在浏览器上对数据库的增删改查. MVC全名是Model View Controller, 是 @@1模型(mo ...

最新文章

  1. 深度分析typedef--定义自己的数据类型
  2. 世界银行拨款2293万美元支持印度并网屋顶太阳能
  3. 210108阶段三进程管理,多进程编程
  4. 按照月的第几周统计_商标评审案件审理情况月报(2020年第11期)
  5. python是用来初始化_python的初始化运行了哪些?
  6. Samba配置文件解析
  7. 已经push的如何回退_如何撤回Git push 到远程分支以后的方法
  8. 计算机智能测试与机电工程学,机电工程学院智能技术创新团队论文被国际计算机视觉顶级会议ICCV录用...
  9. (转)华为面试题算什么,这个背会了外企随便进
  10. hibernate中uuid和native等主键生成策略
  11. matlab无缝拼接两个图_无色差液晶拼接屏研发商参数
  12. 【转载】SI 9000 及阻抗匹配学习笔记(一)
  13. 机器人学相关书籍(长期更新)
  14. Android 上千实例源码分析以及开源分析
  15. 浏览器访问IPv6地址
  16. 如何为服务网格选择入口网关_理解服务网格和API网关之间的差异
  17. 服务器操作系统 份额,2019年6月全球桌面操作系统市场份额数据:Linux占比1.55%...
  18. CTGU实验6_2-创建函数计算图书超期天数
  19. 评点2021-2022年上市的那些Go语言新书
  20. css如何去掉图片里面存在的背景色

热门文章

  1. 斗罗大陆服务器维护,04.28《斗罗大陆:武魂觉醒》停服维护公告(修罗1-7服先行服)...
  2. android hook 模拟点击_手把手讲解 Android Hook-实现无清单启动Activity
  3. access中布局为阶梯怎么设计_access模拟题1 -
  4. android 柱状图_安卓控件 仪表盘控件 柱状图控件 曲线控件 xamarin.android 分类器 瓶子控件 报警控件 水箱控件 进度条控件等...
  5. ObjC学习7-C语言特性
  6. 用GDB调试PHP扩展
  7. Java中在时间戳计算的过程中遇到的数据溢出问题
  8. 可能是迄今为止最好的GitHub代码浏览插件--赞
  9. 一个老程序员的心里话---想创业的技术人员可以看
  10. Ubuntu系统下如何在不重启的情况下永久修改hostname主机名