什么是系统调用

  了解syscall包之前先了解下什么是系统调用。系统调用是程序向操作系统内核请求服务的过程,通常包含硬件相关的服务(例如访问硬盘),创建新进程等。系统调用提供了一个进程和操作系统之间的接口。

fmt中的syscall

  最常见的关于syscall的使用是在fmt.Println中,具体代码的大家可以一步步往下看怎么调用的,这里使用了系统的syscall.Stdout

func Println(a ...interface{}) (n int, err error) {return Fprintln(os.Stdout, a...)
}Stdout = NewFile(uintptr(syscall.Stdout), "/dev/stdout")

Go调用dll库

  dll是windows动态库,go去调用动态库使用的是syscall标准库,一般dll库会提供两个固定函数,申请内存和释放内存,先申请完内存再执行业务逻辑的函数,执行完后释放内存。

dll, err := syscall.LoadDLL("scan.dll")
//根据名称从dll中查找proc
MemoryStream_Get = dll.FindProc("AllocateMemory")
MemoryStream_Get.Call()

  主要就是三步:LoadDLL加载dll文件名,然后用FindProc判断查找调用的dll库函数名,然后Call进行调用。整体的调用方式还是比较简单。

  LoadDLL会返回一个结构体DLL,注意Handle是一个uinptr类型(uintptr 是 Go 内置类型,表示无符号整数,可存储一个完整的地址,常用于指针运算),也就是会返回方法的地址值,后面的传参和解析通过结合只 unsafe.Pointer 类型转换成 uintptr 类型,做完加减法后,转换成 unsafe.Pointer,通过 * 操作,取值或者修改值都可以。

type DLL struct {Name   stringHandle Handle
}

调用dll如何传参

  Proc的Call()方法是可接收多个uintptr的所以在传参的试试需要将参数转为uintptr

func (p *Proc) Call(a ...uintptr) (r1, r2 uintptr, lastErr error) {

  传递整型参数,将整型转为uintptr

func IntToPtr(n int) uintptr {return uintptr(n)
}

  传递字符串参数,将字符串转为uintptr,但是这里使用到了unsafe.Pointer,它是可以指向任意类型的指针,而syscall.StringBytePtr是将string转为 *btye指针。进而一步步转为uintptr

func StringToUintPtr(val string) uintptr {return uintptr(unsafe.Pointer(syscall.StringBytePtr(val)))
}

接收dll库中返回值

  读取调用库的返回值其实真正涉及到指针偏移的计算。因为uintptr指向的实际的整型地址值(申请内存方法会返回),我们可以根据返回的比如字符串在内存中长度来进行计算,比如长度是length(业务函数:GetDeviceInfo会返回),mem是实际调用dll库后返回的uintptr。因为调用dll库一般是返回char,所以这里转为byte即可。

type MemoryStream struct {handle    uintptr //空间地址值lenHandle uintptr //数据长度
}
//获取设备信息 m.handle是申请内存的地址
func (m *MemoryStream) GetDeviceInfo() (result string) {pd, _, _ := GetDeviceInfo.Call(m.handle)m.lenHandle = pdresult = string(m.Bytes())return result
}
//返回内存的数据内容byte[]
func (m *MemoryStream) Bytes() []byte {buffer := new(bytes.Buffer)length := m.Size()mem := m.Memory()if length == 0 {return []byte{}}//根据长度,unsafe.Pointer进行指针运算for i := int64(0); i < length; i++ {buffer.WriteByte(*(*byte)(unsafe.Pointer(mem + uintptr(i)))) //byte是uint8, sizeof长度是1}return buffer.Bytes()
}

总结

  syscall库支持对dll库的调用,当然它的功能很强大,可以实现很多我们没有接触过的业务场景。调用的方式比较清晰,但是设计到传参和解析返回值的时候需要用到unsafe.Pointer和uintpre之间的转换、dll库返回的char强制转换为byte,这一块有点逻辑转换。下次专门做个笔记记录下指针、uintptr、unsafe.Pointer之间的使用。

Go标准库syscall调用dll相关推荐

  1. Golang标准库-syscall(什么是系统调用/Go 语言中的系统调用)

    文章目录 一.什么是系统调用 二.Golang标准库-syscall 1. syscall无处不在 2. syscall demo举例: go版本的strace Strace go版本的strace ...

  2. Python使用标准库subprocess调用外部程序

    Python标准库subprocess中提供了很多调用外部程序创建子进程的对象,本文重点演示Popen对象的stdin和stdout属性的用法. 假设有一个程序externProgram.py,内容如 ...

  3. java 动态库_java调用dll动态库文件的一般总结

    前一段时间,在项目需求中,需要调用一下第三方的动态库文件,下面是本人一些尝试的经历. 首先需要明白的是,在java中是不能直接调用动态库文件的,因为动态库文件是使用c或是c++编写的,作为一种跨   ...

  4. VS2013环境生成和调用DLL动态链接库

    创建动态库方法: 创建动态库是生成 .dll .lib 两个个文件 文件 -> 新建 -> 项目 -> win32控制台应用程序 项目名称:DLLGenerator 应用程序类型:D ...

  5. labview如何加载库_LabVIEW如何方便地调用DLL文件

    转自:http://bbs.elecfans.com/jishu_469502_1_1.html LabVIEW调用DLL文件 LabVIEW支持通过调用DLL文件的方式与其它编程语言混合使用.比如, ...

  6. 易语言 标准c 动态库,易语言Dll动态库的开发

    一.关于易语言DLL 易语言Dll动态库的开发是编程当中和其他语言开发进行交互必不可少的方法之一,从易语言3.6版开始,已经能够支持对DLL动态链接库的开发, 编译出的DLL是标准的DLL,和其他编程 ...

  7. c 汇编语言用标准函数代替,调用C标准库的exit函数

    在上一篇文章中,实现了对大于号(>)的处理,那么对if表达式的编译也就是信手拈来的事了,不解释太多.在本篇中,将会讲述一下如何产生可以调用来自于C语言标准库的exit(3)函数的汇编代码. 在C ...

  8. C++程序设计之可调用对象与标准库function

    C++程序设计之可调用对象与标准库function,来源于C++ Primer(第五版)-- 14.8.3..在头文件<functional>中定义. 源代码如下: #include &l ...

  9. delphi 调用dll 整形返回值_VS2015 编写C++ DLL库及C++、 C#、python 调用

    VS2015生成c++dll C++ 程序调用 dll C# 程序调用 dll 1. VS2015 生成C++dll 可以有两种方法 通过_declspec(dllexport) extern &qu ...

最新文章

  1. typescript 入门例子 Hello world——ts就是一个宿主机语言
  2. oracle和SQLserver数据库中select into 的区别
  3. ADO.NET Entity Framework -Code Fisrt 开篇(一)
  4. 联想拯救者y空间兑换代码_锐祥贴片Y电容进入联想手机快充供应链,性能获世界500强认可...
  5. WPF ComboBox 使用 ResourceBinding 动态绑定资源键并支持语言切换
  6. stl标准模板库_C ++标准模板库(STL)中的array :: fill()
  7. 简陋版C语言仿真通讯录之动态内存开辟版本
  8. GDB调试程序(二)
  9. 开源程序识别图像像素点_开源浏览器扩展程序,可放大图像
  10. BraftEditor:插入图片删除后在服务器将图片同步删除
  11. 有没有五金产品展开计算机软件,拆单软件功能介绍
  12. OpManager如何解除五大网络丢包隐患?
  13. Quartz时间表达式详解
  14. 微信自动回复 html 点击文字,【微信开发】公众号自动回复文字和图文链接(示例代码)...
  15. 关于金仓数据库的java连接问题
  16. 机器学习之手写字体(digits)识别——利用sklearn实现
  17. 《中华颂》朗诵比赛准备
  18. 代码健壮性的几点思考
  19. !和!!的区别和用法
  20. 英雄联盟无法开始第二局(已解决,亲测有效)

热门文章

  1. 区块链入门者的五本必读书籍
  2. Mac安装brew 及安装报错的解决办法【已解决】
  3. 关于MNN中图像预处理
  4. oracle导入指定字符集入,EXP/IMP 与 字符集、导入导出等
  5. android混淆那些坑
  6. 【Apollo配置中心】Apollo环境配置
  7. 【OpenCV】HSV颜色识别-HSV基本颜色分量范围
  8. 数据库表的映射与java类映射处理
  9. 发布《区块链创新与知识产权发展白皮书》
  10. linux h3c 802.1客户端,OH3C 的安装及使用 H3C 802.1x Client for OpenWrt