最近楼主学习了go语言,发现确实很方便,而且运行速度也不慢,官方自带的库也很好用,但是就是没有图形界面,所以就想使用C++写gui,然后网络什么的调用golang,于是开始尝试使用C++调用golang的dll
楼主系统是win10 64位的,使用MINGW编译C++,gcc版本64位的4.8.2,golang版本是64位的1.10.1,如果生成dll有问题可以升级下go版本
首先写一个main.go文件,包含json解析,http请求等C++写起来麻烦的方法,main函数中测试了golang结构体内存布局,发现和c++是一样的
详细我在注释里面都有写
package main // import "C" import ( "encoding/json" "fmt" "github.com/axgle/mahonia" "unsafe" "net/http" "strings" "io/ioutil" ) //export Sum func Sum(a int, b int) int { //最简单的计算和 return a + b } //export Show func Show(str string) { //显示传入的字符串 fmt.Print(str) } //export ToNewGBKCStr func ToNewGBKCStr(str string, c **C.char) { //生成gbk字符串 enc := mahonia.NewEncoder("GBK") output := enc.ConvertString(str) *c = C.CString(output) } //export HttpGet func HttpGet(url string,c **C.char){//http请求 //生成client 参数为默认 client := &http.Client{} //提交请求 reqest, err := http.NewRequest("GET", url, strings.NewReader("")) reqest.Header.Set("Content-Type", "application/x-www-form-urlencoded") if err != nil { fmt.Println(err) return } //处理返回结果 response, err := client.Do(reqest) if err != nil { fmt.Println(err) return } buf,err:=ioutil.ReadAll(response.Body) if err != nil { fmt.Println(err) return } retstr:=string(buf) ToNewGBKCStr(retstr,c) } //export SetMyPoint func SetMyPoint(p uintptr) { //修改传入的结构体 mp := (*MyPoint)(unsafe.Pointer(p)) //将指针p强制转换为MyPoint类型 mp.Name = "名称:" + mp.Name mp.X = 1 + mp.X mp.Y = 2 + mp.Y } //export JsonToMyPoint func JsonToMyPoint(str string, p uintptr) { mp := (*MyPoint)(unsafe.Pointer(p)) json.Unmarshal([]byte(str), mp) } type MyPoint struct { Name string `json:"name"` X int `json:"x"` Y int `json:"y"` } func main() { //测试golang结构体内存布局 mp := MyPoint{Name: "测试", X: 1, Y: 2} p := uintptr(unsafe.Pointer(&mp)) //强制转换为指针 name := *(*string)(unsafe.Pointer(p)) //将指针强制转换为string fmt.Println(name) //64位系统上string占16字节,前8字节是字符串的起始地址,后8字节为字符串占的字节数 p += unsafe.Sizeof(string("")) x := *(*int)(unsafe.Pointer(p)) //将指针强制转换为int fmt.Println(x) p += unsafe.Sizeof(int(0)) //64位系统上int占8字节 y := *(*int)(unsafe.Pointer(p)) fmt.Println(y) }
然后在这个文件目录下新建一个bat文件,输入
@echo off set filepath=%1 set dllpath=%~dp1%~n1.dll IF NOT EXIST "%filepath%" ( goto err ) ELSE ( goto make ) :err echo 文件不存在! set/p exepath=请拖拽文件这里或输入文件路径然后按下回车 IF NOT EXIST "%filepath%" ( goto err ) ELSE ( goto make ) :make echo 编译 %~nx1 -^> %~n1.dll call go build -ldflags "-s -w" -buildmode=c-shared -o "%dllpath%" "%filepath%" echo 编译完成!按下回车关闭窗口 :end pause
把main.go文件拖上去就会自动生成main.dll和main.h
接下来编写一个mian.cpp来调用这些函数
#include <stdio.h> #include <malloc.h> #include <string.h> #include "main.h" struct MyPoint{//类型和顺序必须和go中的MyPoint对应 GoString Name; long long X; long long Y; }; void dump(char *d, size_t len, const char* file) { FILE *fp = nullptr; fopen_s(&fp, file, "w+b"); fwrite(d, sizeof(char), len, fp); fclose(fp); } void test(){ printf("Sum(1,2)=%d\n",Sum(1,2)); const char* str="测试字符串\n"; GoString gstr{str,(ptrdiff_t)strlen(str)};//就是go中的string类型 Show(gstr); //char* cgstr = (char*)malloc(gstr.n + 1); //if (!cgstr) { /* handle allocation failure */ } //memcpy(cgstr, gstr.p, gstr.n); //cgstr[gstr.n] = '\0'; //dump(cgstr,gstr.n,"1.txt");//dump出来用notepad++打发现是utf-8编码 //free(cgstr); MyPoint mp{gstr,0,0}; SetMyPoint((GoUintptr)&mp); printf("%d,%d\n",mp.X,mp.Y); char* pname=nullptr; ToNewGBKCStr(mp.Name,&pname); printf("%s\n",pname); free(pname); pname=nullptr; } void testhttp(){ const char* str="http://www.baidu.com"; GoString gstr{str,(ptrdiff_t)strlen(str)}; char* res=nullptr; HttpGet(gstr,&res); printf("%s\n",res); free(res); res=nullptr; } void testjson(){ const char* str=R"_TWT_({"name":"来自json的点","x":100,"y":200})_TWT_";//C++11中的raw string,防止转义 GoString gstr{str,(ptrdiff_t)strlen(str)}; MyPoint mp; JsonToMyPoint(gstr,(GoUintptr)&mp); char* pname=nullptr; ToNewGBKCStr(mp.Name,&pname); printf("%s,%d,%d\n",pname,mp.X,mp.Y); free(pname); pname=nullptr; } int main(){ testhttp(); test(); testjson(); getchar(); return 0; }再编写一个bat,输入以下内容
call g++ -c main.cpp -o main.o -g -std=c++11 call g++ main.o main.dll -o 1.exe -g -std=c++11 call 1.exe pause
双击即可一键编译运行
所有文件下载:https://github.com/sleepinging/StudyGolang/tree/master/Test/win32/DllTest
转载请注明出处:https://blog.csdn.net/rtduq/article/details/80340461