• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

(转)C#调用DLL时参数问题的一点心得

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

C#导入DLL时,参数怎么定义是一个比较头痛的问题。特别是指针类型的参数,关于此问题本人有点不成熟的经验。

      以 GetComputerName这个函数为例。

     函数原型如下

BOOL GetComputerName(
  LPTSTR lpBuffer,
  LPDWORD lpnSize
);

这个lpBuffer就是下个string型的指针,其实无论是什么类型的指针,对于Windows来说都是一个32位的无符号的整数,也就是一个内在地址,函数之所以使用指针就是要向指针所指向的内存空间写入数据。

我们用C#调用时也要给它传递一个指针,还要对应一块分配的空间 。

下面是代码:

 Marshal.PtrToStringAnsi(p);

            Console.WriteLine(str);

 

其实和C++在调用的本质是一样的,都要分配空间并将空间的地址传给函数

。只是C#是运行在托管环境,所以对空间的分配的数据的读取都要特殊处理。

 

还是更简单的方法,就是用StringBuilder。本质上还是和上面一样的,只不过是C#替你做了得多工作。

 lpnSize);

对于结构体也是一样,以

BOOL GetVersionEx(
  LPOSVERSIONINFO lpVersionInformation
);

typedef struct _OSVERSIONINFO{
  DWORD dwOSVersionInfoSize;
  DWORD dwMajorVersion;
  DWORD dwMinorVersion;
  DWORD dwBuildNumber;
  DWORD dwPlatformId;
  TCHAR szCSDVersion[128];
} OSVERSIONINFO;

为例说明一下。

参数是一个结构体的指针,函数会填充结构体的各个字段,其实就是向这块内存空间的不同位置写入不同的数据。

 

)));

 

根据结构体的定义有5个DWORD和一个128位的CHAR数组,所以要给这个结构体分配148位空间。结构体的第一个字段这是个结构体的大小,我们用 Marshal.WriteInt32(pv, 148);写入结构体的大小(这也是Windows API在使用结构体的一个特点,就是大部分结构体在传给函数填充前要指定其大小。),然后执行函数。

如果函数正常返回,就可以根据结构体的定义从相应的位置读出数据。

Marshal.ReadInt32(pv, 4);读取第二个整数也就是MajorVersion,Marshal.ReadInt32(pv, 12);第四个是BuildNumber,Marshal.PtrToStringAnsi((IntPtr)(pv.ToInt32() + 20));五个整数之后是CSDVersion。

写上面的内容只是想分析一下机理,如果学习过汇编就很好理解了。

下面是通常的做法:

 

);

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
C#设计模式总结发布时间:2022-07-18
下一篇:
python和C#DES加密发布时间:2022-07-18
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap