C#调用C语言的API时一般把void *指针转换成IntPtr,但这经常远远不够的。在C语言中void *是个万金油,尤其是一些老的c语言程序,所有的参数就一个void*指针,里面包罗万象,然后在程序中来一个switch,甚至多个switch来处理不同的参数。最近笔者就碰到了这个问题,不得不来研究一下怎么把void *指针转换成IntPtr。

1.void *指针到IntPtr的简单转化。

c语言函数原型:

int SetConfig(int type, void *p);

这里假设p的所传递的参数式是结构体A:

struct A           

{

    wchar_t osdbuffer[100];            

    unsigned short ix;                     

    unsigned short iy;                     

};

 那么在C#中原型可以定义如下:

int SetConfig(int type, IntPtr p);

结构体A

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]

        public struct A {

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]

            public string osdbuffer;       

            public ushort ix;                       //显示坐标x

            public ushort iy;                       //显示坐标y

        }

  注意这里的CharSet,它由c中wchar_t决定的,如果c程序编译时使用Unicode,这里就用CharSet.Unicode,否则使用CharSet.Ansi。关于字符串的编码问题如果不懂可以去网上查一下。至于怎么知道C语言是用Unicode还是Ansi编译,我是经过调用它的API测试出来的,调用成功了就说明他的编码和我的调用代码一致。

  这里还有一个很重要的问题,那就是内存在编译时的分配问题。一般默认情况下,内存的分配是4byte的整数倍,在这里我省略了,但为了便于理解,补充一下。结构体A完整一点的定义:(注意Pack的值)

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode,Pack = 4)]

        public struct A {

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]

            public string osdbuffer;       

            public ushort ix;                       //显示坐标x

            public ushort iy;                       //显示坐标y

        }

c语言是用的是非托管代码,c#使用的是托管代码,c#的调用代码如下:

    A s_a = new A();int lenght = Marshal.SizeOf(s_a);IntPtr pA= Marshal.AllocHGlobal(lenght);Marshal.StructureToPtr(s_a, pA, true);int type = 1;int ret = SetConfig( type, pA);Marshal.FreeHGlobal(pA);

2.void *指针到IntPtr的复杂转化。

在这里结构体A变得复杂一点,如果它内部包含一个指向另一个结构体B的指针

struct A
{wchar_t osdbuffer[100];            unsigned short ix;            unsigned short iy;、B *pB;
};
struct B
{wchar_t title[20];
};

在C#中你要做的也就稍微复杂一点,也就是说你不但要为A分配内存,也要为B分配内存

  B s_b = new B();//赋值省略int lenght1 = Marshal.SizeOf(s_b);IntPtr pB= Marshal.AllocHGlobal(lenght1);Marshal.StructureToPtr(s_b, pB, true);A s_a = new A();s_a.pB = pB;//其他赋值//int lenght2 = Marshal.SizeOf(s_a);IntPtr pA= Marshal.AllocHGlobal(lenght2);Marshal.StructureToPtr(s_a, pA, true);int type = 1; int ret = SetConfig( type, pA);Marshal.FreeHGlobal(pB);Marshal.FreeHGlobal(pA);

万变不离其宗,只要掌握了原理,不管void *指针传递的参数有多么复杂,都可以搞定。

Marshal在C#中的应用(void *指针到IntPtr的转化)相关推荐

  1. C++ void指针(void *)

    void* 是一种特殊的指针类型,可用于存放任意对象的地址.一个 void* 指针存放着一个地址,这一点和其他指针类似. 在介绍 void 指针前,简单说一下 void 关键字使用规则: 如果函数没有 ...

  2. C++ void指针(void*)简介

    void* 是一种特殊的指针类型,可用于存放任意对象的地址.一个 void* 指针存放着一个地址,这一点和其他指针类似. 在介绍 void 指针前,简单说一下 void 关键字使用规则: 如果函数没有 ...

  3. c++中的void指针和const指针

    在c++中可以声明指向void类型的指针,指向void类型的指针称为void指针,此外,在声明指针时,还可以用关键字const进行修饰,用关键字const修饰的指针称为const指针. 1.void指 ...

  4. c语言中的void指针,C程序中void指针的概念

    到目前为止,我对void指针的轻描淡写如下. 当使用关键字void声明指针变量时,它将成为通用指针变量.任何数据类型(char,int,float等)的任何变量的地址都可以分配给void指针变量. m ...

  5. C++中void和void*指针的含义 (指针类型的含义)

    转载自:http://blog.csdn.net/lee_shuai 指针有两个属性:指向变量/对象的地址和长度,但是指针只存储地址,长度则取决于指针的类型:编译器根据指针的类型从指针指向的地址向后寻 ...

  6. c语言 万能函数指针,C/C++编程笔记:C语言精华解析之void *指针,指针中的万能指针...

    什么是万能指针? 万能指针其实就是void *类型的指针,而void *指针一般被称为通用指针或叫泛指针.它是C语言关于纯粹地址的一种约定.当某个指针是void型指针时,所指向的对象不属于任何类型. ...

  7. 指针中NULL(空指针)和void指针

    1:NULL指针 NULL指针一般用在初始化一个存储类型,这个NULL指针不能用于存放数据类型和访问(你用get()得不到一个具体值,但是对于一个指针变量,我们必须要将这个指针的指向说明,要么将这个指 ...

  8. C/C++语言void及void指针深层探索。C中void是什么意思? 为什么有时可用可不用?

    C/C++语言void及void指针深层探索.C中void是什么意思? 为什么有时可用可不用? 1.概述 许多初学者对C/C++语言中的void及void指针类型不甚理解,因此在使用上出现了一些错误. ...

  9. C++中的空指针和void * 指针

    空指针(null pointer) 空指针不指向任何对象,在使用一个指针前首先要判断是否为空. 用法: int *ptr1=nullptr; //等价于int *ptr1=0; int *ptr2=0 ...

最新文章

  1. 2020年涨薪26-30%,能实现吗?18%数据科学家是这么期待的
  2. ICCV2017 | 一文详解GAN之父Ian Goodfellow 演讲《生成对抗网络的原理与应用》(附完整PPT)
  3. jetbrains 旗下所有工具 pycharm clion goland 配置导出及导入
  4. python 访问 zookeeper
  5. 数据库-优化-数据库系统配置优化-配置文件优化
  6. python返回unicode_我们如何从python中的字形id获取unicode?
  7. 数据库SQL语言从入门到精通--Part 4--SQL语言中的模式、基本表、视图
  8. itil 容量管理流程_探索ITIL和DevOps的边界
  9. [MM9]复制格式的快捷操作
  10. php处理ubb代码,过滤UBB代码的php类
  11. 网络请求 get 请求时, 如果参数中的字符带有+号
  12. python turtle画房子详细解释_Python turtle 绘图入门必知必会
  13. 回顾jvisualvm安装插件简单操作
  14. 【图像超分辨(SR)】通俗直观彻底理解双线性插值、双三次插值及其作用
  15. java 导出word 带图片
  16. 2021年清北等重点高校都有哪些冬令营?最全汇总看这里!
  17. 电脑点击我的计算机无法打开,双击我的电脑打不开怎么办
  18. 【Pytorch官方教程】从零开始自己搭建RNN1 - 字母级RNN的分类任务
  19. Saliency map (fixation map) 生成热点图-python实现
  20. TO B革命 读书笔记整理

热门文章

  1. 复旦大学计算机科学院夏令营,2020年复旦大学计算机科学技术学院夏令营接收推免生条件...
  2. html连在一起的选择器,请问关于css选择器的问题:两个类选择器连在一起是什么意思?...
  3. 节约里程法java代码_患者,男,70岁,有多年排尿困难,呈淋漓状,近2年来双侧腹股沟区出现半年圆形肿块,站立时明显,平卧后消失,体检时压迫内环肿块仍出现,诊断为...
  4. c++string替换指定位置字符_Lua 字符串
  5. 会自学的四足机器人,3.5个小时学会走路!
  6. JAVA子类是球父类是圆_java的父类和子类,这是矛盾...
  7. oracle 赋值到cmd,CMD操作oracle数据导库过程图解
  8. break后面的语句还执行吗_【自学C#】|| 笔记 5 条件语句if、switch
  9. 什么中文版软件可以操作mysql_一款软件,几乎可以操作~所有的~“数据库”,太牛逼了!...
  10. 牛客小白月赛12 F 华华开始学信息学 (分块+树状数组)