作者:电信学院团总支沈天宇 | 来源:互联网 | 2023-05-19 14:48
C/C++调用Golang 一
(开发环境:
- 操作系统: windows 7 32位操作系统
- C++: visual studio 2010
- Golang:go version go1.9 windows/386 TDM-GCC-32)
用一个简单的例子演示如何在C++中调用golang程序。用golang编写一个简单的函数,编译成动态链接库,然后在C++中调用该go函数。
第一阶段 将Golang代码编译成动态链接库 (涉及2个文件 main.go和godll.def)
Golang : main.go 一个简单的Add函数
package main
import "C"
//export Add
func Add(a, b int32) int32 {
return a + b
}
func main() {}
为动态链接库指定导出符号,创建godll.def
EXPORTS
Add
![](https://www.#.com/imgs/7/8/1/0/92/8d9e9752f3f56b5d1ad6fbaf4568a95e.jpe)
![](https://www.#.com/imgs/4/6/3/6/60/139b14b6d06b05c79aa3baa127bcdcfa.jpe)
将main.go编译成动态链接库,在命令行中执行如下操作:
go build -buildmode=c-archive
![](https://www.#.com/imgs/1/3/4/1/2/2cb7720764712be833b111d87f510a85.jpe)
go build 生成了两个文件:godll.a godll.h
![](https://www.#.com/imgs/8/9/1/5/54/874b260ff7258fdf277a35958a81ff76.jpe)
再执行 gcc -m32 -shared -o godll.dll godll.def godll.a -static -lwinmm -lWs2_32
![](https://www.#.com/imgs/1/6/1/6/12/6b979ab3df7abf7ad55bc9220789ff49.jpe)
(需要安装 TDM-GCC-32)
编译后生成 godll.dll
![](https://www.#.com/imgs/0/5/7/2/74/c605455738d199cb3158544f013bc0a8.jpe)
godll.h和godll.dll是C++工程需要的,godll.h的内容如下:
/* Created by "go tool cgo" - DO NOT EDIT. */
/* package _/Y_/godll */
/* Start of preamble from import "C" comments. */
/* End of preamble from import "C" comments. */
/* Start of boilerplate cgo prologue. */
#line 1 "cgo-gcc-export-header-prolog"
#ifndef GO_CGO_PROLOGUE_H
#define GO_CGO_PROLOGUE_H
typedef signed char GoInt8;
typedef unsigned char GoUint8;
typedef short GoInt16;
typedef unsigned short GoUint16;
typedef int GoInt32;
typedef unsigned int GoUint32;
typedef long long GoInt64;
typedef unsigned long long GoUint64;
typedef GoInt32 GoInt;
typedef GoUint32 GoUint;
typedef __SIZE_TYPE__ GoUintptr;
typedef float GoFloat32;
typedef double GoFloat64;
typedef float _Complex GoComplex64;
typedef double _Complex GoComplex128;
/*
static assertion to make sure the file is being used on architecture
at least with matching size of GoInt.
*/
typedef char _check_for_32_bit_pointer_matching_GoInt[sizeof(void*)==32/8 ? 1:-1];
typedef struct { const char *p; GoInt n; } GoString;
typedef void *GoMap;
typedef void *GoChan;
typedef struct { void *t; void *v; } GoInterface;
typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;
#endif
/* End of boilerplate cgo prologue. */
#ifdef __cplusplus
extern "C" {
#endif
extern GoInt32 Add(GoInt32 p0, GoInt32 p1);
#ifdef __cplusplus
}
#endif
extern GoInt32 Add(GoInt32 p0, GoInt32 p1); 是导出函数的签名。
用depends22_x86 查看 godll.dll
![](https://www.#.com/imgs/8/5/8/6/40/3ef39063b2fa4381558acc51644270ee.jpe)
第二阶段 在C++工程中调用godll.dll
创建名为callgo的vs 2010工程,将godll.h加入到工程,新建main.cpp的源文件:
#include
#include
#include "godll.h"
typedef GoInt32 (*funcPtrAdd)(GoInt32 p0, GoInt32 p1);
int main(){
HMODULE h = LoadLibraryA("godll.dll");
if (NULL == h || INVALID_HANDLE_VALUE == h)
{
return -1;
}
funcPtrAdd pfAdd = (funcPtrAdd)GetProcAddress(h,"Add");
if (pfAdd)
{
GoInt32 result = pfAdd(5,4);
printf("Add(5,4) = %d",result);
}
FreeLibrary(h);
return 0;
}
将godll.h中的三行注释掉
//typedef __SIZE_TYPE__ GoUintptr;
typedef float GoFloat32;
typedef double GoFloat64;
//typedef float _Complex GoComplex64;
//typedef double _Complex GoComplex128;
![](https://www.#.com/imgs/7/5/4/6/94/d5f1166ac493abbd4d996806507e891f.jpe)
编译运行,结果如下图:
![](https://www.#.com/imgs/2/4/1/1/8/65657e0bb15ac5354bdb05d41f6b31ec.jpe)
注意事项:
main.go中 import "C" 这一行一定要有,否则gcc编译时会报符号未定义的错误:
![](https://www.#.com/imgs/6/9/0/3/71/4b2423bf47299a0ffa9b250687a3dfc2.jpe)