分类 报考指南 政策.报名 培训辅导 综合指导 证书.动态 准考证.成绩

2012年软考程序员辅导:C语言封送结构体数组

 

在使用第三方的非托管API时,我们经常会遇到参数为指针或指针的指针这种情况,

  一般我们会用IntPtr指向我们需要传递的参数地址;

  但是当遇到这种一个导出函数时,我们如何正确的使用IntPtr呢,

   extern “C” __declspec(dllexport) int GetClass(Class pClass[50]) ;

  由于这种情况也经常可能遇到,所以我制作了2个示例程序来演示下如何处理这种非托管函数的调用!

  首先创建一个C++ 的DLL 设置一个如上的导出函数

   #include #include typedef struct Student { char name[20];int age;double scores[32];}Student;typedef struct Class { int number;Student students[126];}Class;extern “C” __declspec(dllexport) int GetClass(Class pClass[50])

   { for(int i=0;i<50;i++)

   { pClass[i].number=i;for(int j=0;j<126;j++)

   { memset(pClass[i].students[j].name,0,20);sprintf(pClass[i].students[j].name,“name_%d_%d”,i,j);pClass[i].students[j].age=j%2==0?15:20;} return 0;}上面DLL 的导出函数要求传递的参数为它自定义的Class结构体数组, 那么我们在C#调用它时也要自定义对应的结构体了,

  我们可以定义为如下:

   [StructLayout(LayoutKind.Sequential)] struct Student { [MarshalAs(UnmanagedType.ByValTStr,SizeConst=20)] public string name;public int age;[MarshalAs(UnmanagedType.ByValArray,SizeConst=32)] public double[] scores;} [StructLayout(LayoutKind.Sequential)] struct Class { public int number;[MarshalAs(UnmanagedType.ByValArray,SizeConst=126)] public Student[] students;}需要注意的是,这2个结构体中的数组大小一定要跟C++中的限定一样大小哦,接下来如何使用这个API来正确的获取数据呢,大多数人可能想到像这样的处理方式

   Class myclass = new Class();IntPtr ptr=Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Class)));GetClass(ptr);Marshal.FreeHGlobal(ptr);没错,这样的处理是没问题的,但是我们的API的参数是Class数组,这种处理方式只是传递一个Class结构体参数,所以这种方式在这里就不太合适了,!

  那大家就想到先Class[] myclass = new Class[MaxClass]; 然后在用Marshal.AllocHGlobal 来获取myclass 数据的指针,

  其实这样也是错的, 因为 Class结构中包含了,不能直接封送的Student结构,所以无论如何上面的想法是错误的!

  那要怎么办呢,其实很简单,就是先分配一段非托管内存,并调用API后,再将非托管内容数据读取到托管结构体数据中!

  示例C语言封送结构体数组演示代码如下

   1 static void Main(string[] args)

   2 {

   3 int size = Marshal.SizeOf(typeof(Class)) * 50;

   4 byte[] bytes = new byte[size];

   5 IntPtr pBuff = Marshal.AllocHGlobal(size);

   6 Class[] pClass = new Class[50];

   7 GetClass(pBuff);

   8 for (int i = 0; i < 50; i++)

   9 {

   10 IntPtr pPonitor = new IntPtr(pBuff.ToInt64() + Marshal.SizeOf(typeof(Class)) * i);

   11 pClass[i] = (Class)Marshal.PtrToStructure(pPonitor, typeof(Class));

   12 }

   13 Marshal.FreeHGlobal(pBuff);

   14 Console.ReadLine();

   15 }有兴趣的不妨自己测试一下C语言封送结构体数组,看看输出结果是否正确!


   >>学课在线网课试听.报名        >>学课在线智能题库.模拟做题       >>直播课程       >>录播课程

课程名称
课程免费试听
课程名称
课程免费试听
课程名称
课程免费试听
初级会计师

一级建造师

执业药师

中级会计师

二级建造师

护士资格证

注册会计师

一级造价工程师

健康管理师

经济师考试

监理工程师

考研辅导课

银行从业

安全工程师

自考课程

基金从业

一级消防工程师

心理咨询师

企业人力资源管理师

法律职业资格考试

公共营养师

社会工作者

消防设施操作员

保育员

教师资格证

成人高考

育婴师

公务员培训

文职培训

英语四六级

计算机软考
养老护理员
税务师培训

房产经纪人
咨询工程师

其它课程>>



重要提醒!!内容中联系方式并非本站联系方式,报名咨询的学员请与下面最新联系方式联系我们咨询报名-以免损失!
>>长期招聘兼职招生代理人员,项目合作,团报优惠咨询,有意者请联系我们 >>咨询:13312524700(可加微信)。

昆明学历中心:◆咨询电话:0871-65385921、13312528471 赖老师、钱老师(微信报名:17787865775)点击这里给我发消息


云南地州中心:◆咨询电话:0871-65385921、17787865775 冯老师、 王老师(微信报名:17787865775)点击这里给我发消息


总部报名地址: ◆昆明市-五华区教场东路莲花财富中心10楼;网课试听:ke.xuekaocn.cn   点击这里立即咨询我们



地州分校:   大理分校   丽江分校   迪庆分校   怒江分校   红河分校   临沧分校   玉溪分校   文山分校   保山分校   德宏分校   昭通分校   普洱分校   版纳分校 【各地州学员请加老师微信咨询报名,电话(微信):133-1252-4700】;2021年云南省成人高考>>立即报名



职业技能考证:心理咨询师、健康管理师、茶艺师等更多>◆咨询电话:133 1252 4700(微信)点击这里咨询我们  

公考培训咨询:◆国考云南省考公务员/事业单位面授培训,咨询电话:133 1252 4700 (微信)点击这里立即咨询我们






温馨提示:因考试政策、内容不断变化与调整,学课在线网提供的以上信息仅供参考,如有异议,请考生以权威部门公布的内容为准!

免责声明:以上内容仅代表原创者观点,其内容未经本站证实,学课在线网对以上内容的真实性、完整性不作任何保证或承诺,转载目的在于传递更多信息,由此产生的后果与学课在线网无关;如以上转载内容不慎侵犯了您的权益,请联系我们QQ:1536696595,我们将会及时处理。




网友评论