C/C++调用Golang 一

(开发环境:

  1. 操作系统: windows 7 32位操作系统
  2. C++: visual studio 2010
  3. 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"

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;

编译运行,结果如下图:

注意事项:

main.go中  import "C" 这一行一定要有,否则gcc编译时会报符号未定义的错误:

时间: 2025-01-02 15:17:38

C/C++调用Golang 一的相关文章

C/C++调用Golang 二

C/C++调用Golang 二 <C/C++调用Golang 一>简单介绍了C/C++调用Golang的方法步骤,只涉及一个简单的函数调用.本文总结具体项目中的使用场景,将介绍三种较复杂的调用方式:一,C++向golang传入复杂结构体:二,C++向golang传入回调函数,在golang中调用C++函数:三,C++调用golang函数,返回复杂的结构体. (本文后面涉及三个例子,省略了编译步骤,仅展示关键代码.具体操作步骤参考<C/C++调用Golang 一>) 一 C++向go

(转)使用Thrift0.9.1实现跨语言调用Golang、Php、Python、Java

问题导读:什么是Thrift?Thrift的官方网站在哪里?Golang.Java.Python.PHP之间如何通过Thrift实现跨语言调用? 一.什么是Thrift Thrift是一种可伸缩的跨语言服务的发展软件框架.它结合了功能强大的软件堆栈的代码生成引擎,以建设服务. Thrift是facebook开发的,07年4月开放源代码,08年5月进入apache孵化器.创造Thrift是为了解决facebook系统中各系统间大数据量的传 输通信以及系统之间语言环境不同需要跨平台的特性.所以thr

electron/nodejs实现调用golang函数

https://www.jianshu.com/p/a3be0d206d4c 思路 golang 支持编译成c shared library, 也就是系统中常见的.so(windows下是dll)后缀的动态链接库文件. c++可以调用动态链接库,所以基本思路是golang开发主要功能, c++开发插件包装golang函数,实现中转调用 对于类型问题, 为了方便处理, 暴露的golang函数统一接受并返回字符串, 需要传的参数都经过json编码, 返回值亦然. 这里实现了3种调用方式, 同步调用,

GoLang入门4-编译应用mymath测试

上面我们已经建立了自己的应用包mymath,如何进行编译安装呢?有两种方式可以进行安装 1.只要进入对应的应用包目录,然后执行go install,就可以安装了 2.在任意的目录执行如下代码go install mymath 安装完之后,我们可以进入如下目录 在任意目录运行 go install mymath  如下,则说明 编译安装包成功! mymath.a 就是编译后的包 这个.a文件是应用包,那么我们如何进行调用呢? 接下来我们新建一个应用程序来调用 GoLang入门4-编译应用mymat

GoLang入门5-调试我们自己写的包mymath

接下来我们新建一个应用程序来调用我们的mymath包 新建应用包mathapp 先到 GOPATH 下的 src目录下 输入命令  mkdir mathapp 进入 f盘下 mygo目录下 src--> mathapp目录下 新建一个txt 文本文件 输入以下代码 package main import ( "mymath" "fmt" ) func main() { fmt.Printf("Hello, world. Sqrt(2) = %v\n&

PHP与Golang如何通信?

最近遇到的一个场景:php项目中需要使用一个第三方的功能(结巴分词),而github上面恰好有一个用Golang写好的类库.那么问题就来了,要如何实现不同语言之间的通信呢? 常规的方案: 用Golang写一个http/TCP服务,php通过http/TCP与Golang通信 将Golang经过较多封装,做为php扩展. PHP通过系统命令,调取Golang的可执行文件 存在的问题: http请求,网络I/O将会消耗大量时间 需要封装大量代码 PHP每调取一次Golang程序,就需要一次初始化,时

docker的cli的call执行流程

平常我们输入一个命令,比如docker info,就是使用cli向daemon发送一次http请求,返回一些容器相关的参数 输入docker info的时候,如果daemon不是在后台运行,会有  INFO[0007] GET /v1.19/info 输出,GET相当于HTTP中的GET/POST中的method GET, v1.19相当于版本号,info就是命令的name咯 接下来我们分析源码: serverResp, err := cli.call("GET", "/co

sync.Map源码分析

sync.Map源码分析 背景 众所周知,go普通的map是不支持并发的,换而言之,不是线程(goroutine)安全的.博主是从golang 1.4开始使用的,那时候map的并发读是没有支持,但是并发写会出现脏数据.golang 1.6之后,并发地读写会直接panic: fatal error: concurrent map read and map write package main func main() { m := make(map[int]int) go func() { for

Go语言开发(二十)、GoStub测试框架

Go语言开发(二十).GoStub测试框架 一.GoStub简介 GoStub是一款轻量级的单元测试框架,接口友好,可以对全局变量.函数或过程进行打桩.GoStub安装:go get github.com/prashantv/gostub 二.GoStub常用方法 gostub用于在测试时打桩变量,一旦测试运行时,重置原来的值. type Stubs struct { // stubs is a map from the variable pointer (being stubbed) to t