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
将main.go编译成动态链接库,在命令行中执行如下操作:
go build -buildmode=c-archive
go build 生成了两个文件:godll.a godll.h
再执行gcc -m32 -shared -o godll.dll godll.def godll.a -static -lwinmm -lWs2_32
(需要安装 TDM-GCC-32)
编译后生成godll.dll
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
第二阶段在C++工程中调用godll.dll
创建名为callgo的vs 2010工程,将godll.h加入到工程,新建main.cpp的源文件:
#include<Windows.h>
#include<stdio.h>
#include"godll.h"
typedefGoInt32 (*funcPtrAdd)(GoInt32 p0, GoInt32 p1);
intmain(){
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);
return0;
}
将godll.h中的三行注释掉
//typedef __SIZE_TYPE__ GoUintptr;
typedeffloatGoFloat32;
typedefdoubleGoFloat64;
//typedef float _Complex GoComplex64;
//typedef double _Complex GoComplex128;
编译运行,结果如下图:
注意事项:
main.go中 import "C" 这一行一定要有,否则gcc编译时会报符号未定义的错误: