golang调用c++dll获取mac地址

转自:https://golangtc.com/t/5a0556b34ce40d3bf47f606f

功能

c++实现获取主机的的内存大小,系统用户名,mac地址和硬盘序列号,然后封装成dll给go调用,并提供go调用的接口。github传送门
GIT 地址https://github.com/easyAation/go-mac

运行截图:

c++部分:

go语言获取mac地址这些不太方便,于是就思考可不可以调用c++封装的dll。这个demo用cgo来实现go对c++代码调用。其中c++所爆露的接口都是void的,所需信息全部由指针做形参来获得,用为不知道怎么用go获取c++返回的std::string,所以就思考用传入指针的方式来获取想要的值,试了后发现是可以的。

c++代码

 
 
//simple.h:/*go查询主机硬盘序列号,内存大小,用户名,mac地址qq:1034552569 欢迎大家一起交流学习 */#ifndef SIMPLE_H_INCLUDED#define#ifdef __cplusplus EXPORT extern "C" __declspec (dllexport)#else EXPORT __declspec #endif // __cplusplus#include<windows.h><string><stdio.h><winsock2.h><iphlpapi.h><algorithm><iostream>#pragma commentlib,"iphlpapi.lib") __declspec) void get_Disk_number(); get_mac_address(char **macAdress); get_user_namename get_mem_size_size get_disk_serial_numbernumber);// SIMPLE_H_INCLUDED

 
 //simple.cpp"simple.h"){ VolumeInfo[100]; DWORD VolNameSize=;VolSerialNumberVolMaxComponentLengthVolFileSystemFlagsFileSystemNameBufferFileSystemNameSizeGetVolumeInformation("c:\\"&); sprintf(*number "%d"// return VolSerialNumber;} str1024 DWORD dwsize = GetUserNamestr &dwsize strcpyname ); MEMORYSTATUS stMem {0}; stMem.dwLength sizeofGlobalMemoryStatus(&stMem_size "%d"dwTotalPhys/(*));// return stMem.dwTotalPhys / (1024 * 1024);//有mac地址就返回第一个 , 没有的话就返回空字符串。int i  ret unsignedlong size  PIP_ADAPTER_INFO pIpAdapterInfo new IP_ADAPTER_INFO();GetAdaptersInfopIpAdapterInfosizeifERROR_BUFFER_OVERFLOW == retdelete pIpAdapterInfo pIpAdapterInfo PIP_ADAPTER_INFO BYTE[} std::string sbool flag falseERROR_SUCCESS if// 每个网卡对应一个链表结点,只要第一个fori <->AddressLength i++)AddressLength-1"%02X-"Addressi]); s +=else"%02X"true//std::cout<<s<<std::endl; NULLflagmacAdress c_str());""}

ps:需要注意的是,如果这个代码编译不过,请检查一下你是否缺少了iphlpapi.lib这个动态链接库。

go部分:

我在go调用dll的时候遇到了一个很关于编码的问题,因为go语言的编码格式和c/c++是不同的,所以会出现汉字乱码的情况,这样传系统用户名的时候就麻烦了。通过一下代码发现:

//c++ demo[]"连"forstrlenstr printf"%d "]+256);

运行结果为: 193 172。

//go demovar ss "连"data []bytessfmt.Printlndata)

运行结果:[232 191 158 ]。

分析:

可以看到存储汉字的时候c++底层用了两个字节,而go用了三个字节,所以要解决这个问题就要进行编码转换。这里我用到了go中的一个库github.com/axgle/mahonia,它可以很方便的进行编码转换。

go代码


  
  
  • package main */import"fmt""github.com/axgle/mahonia"//用于将gbk编码转化成go的utf-8编码"log""syscall""unsafe"func init() fmt"------------------------------------------" handle err := syscallLoadDLL"Algorithm.dll"!=nilerrError()) logFatal"init() faied." errhandleHandleName"------------函数加载成功------------------"}//返回操作系统当前的用户名func Get_ser_namestring errorFindProc"get_user_name""get_user_name 不存在\n"return err str make([]C.charCall((uintptr)(unsafePointer))) data byteGoString])) * 因为c++使用的编码格式与go不相符,会出现中文乱码问题 * 所以要进行转换 */ enc mahoniaNewDecoder"GBK" _ cdata _ encTranslate name cdata[:]) namenil//获得主机内存大小 , 返回stringGet_mem_size"get_mem_size""get_mem_size 不存在"])),0)"> * 获取机器mac地址,如果有多个则返回第一个Get_mac_address"get_mac_address""get_mac_address 不存在"Get_disk_serial_numbere get_disk_serial_num"get_disk_serial_number""get_disk_serial_num 不存在"func main"name(gdk): " size"mems size: " address"address: " disk_number"disk_number: "}

    ps:

    还有大家一个问题需要注意,如果go获取dll失败,很可能是因为你的go是64位的而dll是32位的。大家可以直接用我上面的c++代码编译成dll文件给go用,也可以用我已经编译好的dll用。

    相关文章

    程序目录结构 简单实现,用户登录后返回一个jwt的token,下次请求带上token请求用户信息接口并返回信息...
    本篇博客的主要内容是用go写一个简单的Proof-of-Work共识机制,不涉及到网络通信环节,只是一个本地的简...
    简介 默克尔树(MerkleTree)是一种典型的二叉树结构,其主要特点为: 最下面的叶节点包含存储数据或其...
    接下来学习并发编程, 并发编程是go语言最有特色的地方, go对并发编程是原生支持. goroutine是go中最近本...
    先普及一下, 什么是广度优先搜索 广度优先搜索类似于树的层次遍历。从图中的某一顶点出发,遍历每一个顶...
    第一天: 接口的定义和实现 第二天: 一. go语言是面向接口编程. 在学习继承的时候说过, go语言只有封装,...