Go调用DLL
来源:互联网 发布:java识别屏幕数字 编辑:程序博客网 时间:2024/06/11 05:48
Go的标准包syscall提供了调用DLL所需的API。本例用到的API如下(仅列出重要部分):
// LoadDLL 和 MustLoadDLL 根据DLL名字 name 来加载DLL,返回值为 syscall.DLL 结构体指针。// LoadDLL 返回 error 表示错误。MustLoadDLL 错误时调用 panicfunc LoadDLL(name string) (*DLL, error)func MustLoadDLL(name string) *DLL// syscall.DLL 结构体表示 DLL 抽象type DLL struct { // ...}// FindProc 和 MustFindProc 根据函数名字 name 加载 DLL 中的函数// 返回值为 syscall.Proc 结构体指针。// FindProc 返回 eror 表示错误。MustFindProc 错误时调用 panicfunc (d *DLL) FindProc(name string) (proc *Proc, err error)func (d *DLL) MustFindProc(name string) *Proc// syscall.Proc 结构体表示 DLL 中的函数type Proc struct { // ...}// Call 方法调用 syscall.Proc 表示的函数,参数为 uintptr 切片,返回值为 r1, r2 和 error// C 函数只能有一个返回值,因此r2用不到。// error表示错误,该错误永远不为nil,它是由GetLastError()构成的func (p *Proc) Call(a ...uintptr) (r1, r2 uintptr, lastErr error)// 将字符串转换为byte指针func StringBytePtr(s string) *byte
下面是一个完整的例子:
首先实现一个DLL,定义了两个函数,一个从Go接收参数,一个返回参数给Go:
// test.h#ifndef TEST_H#define TEST_H#ifdef TEST_DLL_EXPORT#define TEST_API __declspec(dllexport)#else#define TEST_API __declspec(dllimport)#endifTEST_API void greet(char *name);TEST_API char *name();#endif
// test.c#define TEST_DLL_EXPORT#include "test.h"#include <stdio.h>#include <stdlib.h>#include <string.h>void greet(char *name){ printf("Hello, %s!\n", name);}char *name(){ char buf[] = "Gopher"; char *n = malloc(strlen(buf) + 1); strcpy(n, buf); n[strlen(buf)] = '\0'; return n;}
下面是Go调用DLL的代码:
package mainimport ( "fmt" "syscall" "unsafe")func main() { dll := syscall.MustLoadDLL("test.dll") procGreet := dll.MustFindProc("greet") procGreet.Call(uintptr(unsafe.Pointer(syscall.StringBytePtr("Cynhard")))) procName := dll.MustFindProc("name") r, _, _ := procName.Call() // 获取C返回的指针。 // 注意C返回的r为char*,对应的Go类型为*byte p := (*byte)(unsafe.Pointer(r)) // 定义一个[]byte切片,用来存储C返回的字符串 data := make([]byte, 0) // 遍历C返回的char指针,直到 '\0' 为止 for *p != 0 { data = append(data, *p) // 将得到的byte追加到末尾 r += unsafe.Sizeof(byte(0)) // 移动指针,指向下一个char p = (*byte)(unsafe.Pointer(r)) // 获取指针的值,此时指针已经指向下一个char } name := string(data) // 将data转换为字符串 fmt.Printf("Hello, %s!\n", name)}
注意从C中返回的指针是由malloc动态分配的,Go中不会对此指针进行引用计数,不会被垃圾回收,因此会造成内存泄漏。解决方法是在DLL中提供释放资源的接口,在Go中调用此接口。
注:本例中用到的低级编程知识请见:Go低级编程
阅读全文
1 0
- Go调用DLL
- Go中调用dll示例
- go调用动态链接库dll/so
- GO语言调用DLL,填平所有的坑,最详尽攻略
- dll调用
- 调用DLL
- 调用DLL
- DLL调用
- DLL调用
- dll调用
- 调用DLL
- 调用dll
- 调用dll
- DLL调用
- dll调用
- Dll调用
- .dll调用
- 释放DLL 调用DLL
- Swing组件继承关系
- 页面添加自动排序序号
- 数据结构_栈
- 小程序 三种方法 页面跳转
- opacity、visibility、display对比分析
- Go调用DLL
- 事物的有关设置
- JAVA的一次编译,到处运行,你知道多少?
- 不怕被病毒勒索!用内网穿透软件花生壳组建私有云
- Html基础
- 浏览器相关(3)
- 关于Gson泛型解析的解决方案。
- Linux多线程Pthread学习小结
- Android-第三方框架-GreenDao(一)