Golang与DLL交互
2017-12-09 13:30
155 查看
Golang与DLL交互
在系统级编程中,经常需要使用C/C++来编写模块给Go调用,目前官方支持这种调用,但是需要CGO做支撑。这里研究了Golang与DLL进行数据交换的几种方式,(重点是:指针,结构体,回掉函数)并做以测试。
依赖条件:
C接口形式的DLL(这里使用了VS2015编写)
CGO依赖的GCC(这里使用Qt5.9自带的Minigw)
1. DLL代码
#include "stdafx.h" #include <stdio.h> #ifndef TM_ROBOT_API #define TM_ROBOT_API extern "C" __declspec(dllexport) #else #define TM_ROBOT_API extern "C" __declspec(dllimport) #endif TM_ROBOT_API void fun1(int* pVal) { char buff[128]; sprintf(buff, "fun1, val: %d -> 999\n", *pVal); OutputDebugStringA(buff); *pVal = 999; } struct MyStruct { int nVal1; float nVal2; }; typedef void(*CB_MY)(float nVal, float fVal); TM_ROBOT_API void fun2(MyStruct* pVal) { char buff[128]; sprintf(buff, "fun2, val: 1->%d, 2->%.4f -> 1,2\n", pVal->nVal1, pVal->nVal2); OutputDebugStringA(buff); pVal->nVal1 = 1; pVal->nVal2 = 2.2; } TM_ROBOT_API void fun3(CB_MY pFun) { char buff[128]; sprintf(buff, "fun3, val: %08X -> call it 10s\n", pFun); OutputDebugStringA(buff); for (int i=80;i<100;i++) { pFun(i*3.3, i*1.1); Sleep(10); } }
注意,这里的调用约定为
extern "C" __declspec(dllexport)。
2. Golang代码
package main /* // 依赖GCC typedef struct _MyStruct { int nVal1; float nVal2; }MyStruct; */ import "C" import ( "fmt" "syscall" "unsafe" ) func cb_my(val1 float32, val2 float32) int32 { fmt.Println("cb_my:", val1, val2) return 0 } func main() { Handle := syscall.NewLazyDLL("gocTest.dll") Fun3 := Handle.NewProc("fun3") Fun2 := Handle.NewProc("fun2") Fun1 := Handle.NewProc("fun1") var aa int32 = 10 // var aa C.int = 10 Fun1.Call(uintptr(unsafe.Pointer(&aa))) fmt.Println("########", aa) var arg1 C.MyStruct // 使用Go的Struct会有问题 arg1.nVal1 = 11 arg1.nVal2 = 22.22 Fun2.Call(uintptr(unsafe.Pointer(&arg1))) fmt.Println("************", arg1) var fn = syscall.NewCallbackCDecl(cb_my) // 注意调用约定 Fun3.Call(fn) fmt.Println("============") }
3. 总结
fun1做简单的测试就能通过,如果时float等其他类型,尽量使用CGO模块类型。fun2如果使用Golang的结构体,除了int32之外的参数都有问题,需要CGO模块类型。
fun3特别注意NewCallbackCDecl/NewCallback与回掉函数的约定,否则会出很多异常。
其他高阶混合编程,这里不做涉及。
参考
https://studygolang.com/articles/1424http://lib.csdn.net/article/go/33766
类型转换对照表:
char --> C.char --> byte signed char --> C.schar --> int8 unsigned char --> C.uchar --> uint8 short int --> C.short --> int16 short unsigned int --> C.ushort --> uint16 int --> C.int --> int unsigned int --> C.uint --> uint32 long int --> C.long --> int32 or int64 long unsigned int --> C.ulong --> uint32 or uint64 long long int --> C.longlong --> int64 long long unsigned int --> C.ulonglong --> uint64 float --> C.float --> float32 double --> C.double --> float64 wchar_t --> C.wchar_t --> void * -> unsafe.Pointer
相关文章推荐
- golang与C交互:cgo
- MFC的DLL中调用函数指针与主程序交互
- 在C#应用程序与DLL交互中使用消息
- 在C#应用程序与DLL交互中使用消息
- [MATLAB]XXX塔扩展公式DLL与MATLAB交互
- D与C#的交互:C#调用D的dll
- Golang1.7中的TCP交互封装.
- golang调用c++dll获取mac地址
- Go实战--golang获取Windows屏幕分辨率(golang如何调用dll)
- golang表单提交与服务器的交互
- 使用golang和docker守护进程交互
- VC.dll相关及其C#交互
- 用ajax.dll来做一个异步数据的交互例子大家分享
- golang 获取exe、dll、apk 版本号
- 使用SWIG桥接Golang和Windows DLL
- golang调用c++dll 获取mac地址,用户名,内存大小
- 利用回调函数实现DLL与Qt主程序的数据交互,进一步实现对Qt主程序中的信号触发
- Golang通过syscall调用windows dll方法
- Golang下通过syscall调用win32的dll实现mifare card读写
- 使用python的内置ctypes模块与c、c++写的dll进行交互