189 8069 5689

C++中怎么调用Golang方法

C++中怎么调用Golang方法,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

创新互联是一家集网站建设,堆龙德庆企业网站建设,堆龙德庆品牌网站建设,网站定制,堆龙德庆网站建设报价,网络营销,网络优化,堆龙德庆网站推广为一体的创新建站企业,帮助传统企业提升企业形象加强企业竞争力。可充分满足这一群体相比中小企业更为丰富、高端、多元的互联网需求。同时我们时刻保持专业、时尚、前沿,时刻以成就客户成长自我,坚持不断学习、思考、沉淀、净化自己,让我们为更多的企业打造出实用型网站。


现象

在一个APP技术项目中,子进程按请求加载Go的ServiceModule,将需要拉起的ServiceModule信息传递给Go的Loader,存在C++调用Go方法,传递字符串的场景。

方案验证时,发现有奇怪的将std::string对象的内容传递给Go方法后,在Go方法协程中取到的值与预期不一致。

经过一段时间的分析和验证,终于理解问题产生的原因并给出解决方案,现分享如下。

背景知识

  1. Go有自己的内存回收GC机制,通过make等申请的内存不需要手动释放。

  2. C++中为std::string变量赋值新字符串后,.c_str()和.size()的结果会联动变化,尤其是.c_str()指向的地址也有可能变化。

  3. go build -buildmode=c-shared .生成的.h头文件中定义了C++中Go的变量类型的定义映射关系,比如GoString、GoInt等。其中GoString实际是一个结构体,包含一个字符指针和一个字符长度。

原理及解释

通过代码示例方式解释具体现象及原因,详见注释

C++侧代码:

	//
	// Created by w00526151 on 2020/11/5.
	//
	 
	#include 
	#include 
	#include 
	#include "libgoloader.h"
	 
	/**
	 * 构造GoString结构体对象
	 * @param p
	 * @param n
	 * @return
	 */
	GoString buildGoString(const char* p, size_t n){
	    //typedef struct { const char *p; ptrdiff_t n; } _GoString_;
	    //typedef _GoString_ GoString;
	    return {p, static_cast(n)};
	}
	 
	int main(){
	    std::cout<<"test send string to go in C++"<

Go侧代码:

	package main
	 
	import "C"
	import (
	    "fmt"
	    "time"
	)
	 
	func printInGo(p0 string, p1 string, p2 string){
	    time.Sleep(10 * time.Second)
	    fmt.Printf("in go function, p0:%s size %d, p1:%s size %d, p2:%s size %d", p0, len(p0), p1, len(p1), p2, len(p2))
	}
	 
	//export LoadModule
	func LoadModule(name string, version string, location string) int {
	    //通过make的方式,新构建一段内存来存放从C++处传入的字符串,深度拷贝防止C++中修改影响Go
	    tmp3rdParam := make([]byte, len(location))
	    copy(tmp3rdParam, location)
	    new3rdParam := string(tmp3rdParam)
	    fmt.Println("in go loadModule,first param is",name,"second param is",version, "third param is", new3rdParam)
	    go printInGo(name, version, new3rdParam);
	    return 0
	}

Go侧代码通过-buildmode=c-shared的方式生成libgoloader.so及libgoloader.h供C++编译运行使用

	go build -o libgoloader.so -buildmode=c-shared .

程序执行结果:

	test send string to go in C++
	in C++ tmpStr: 0x7fffe1fb93f0, tmpStr: /tmp/udsgateway-netconftemplateservice, tmpStr.size:38 
	# 将C++的指针传给Go,一开始打印都是OK的
	in go loadModule,first param is /tmp/udsgateway-netconftemplateservice second param is /tmp/udsgateway-netconftemplateservice third param is /tmp/udsgateway-netconftemplateservice
	# 在C++中,将指针指向的内容修改,或者删掉指针
	in C++ change tmpStr and delete newStrPtr, new tmpStr: 0x7fffe1fb93f0, tmpStr: new string, tmpStr.size:10 
	# 在Go中,参数1、参数2对应的Go string变量都受到了影响,参数3由于做了深度拷贝,没有受到影响。
	in go function, p0:new string eway-netconftemplateservice size 38, p1:        p���  netconftemplateservice size 38, p2:/tmp/udsgateway-netconftemplateservice size 38

关于C++中怎么调用Golang方法问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注创新互联行业资讯频道了解更多相关知识。


本文名称:C++中怎么调用Golang方法
文章地址:http://cdxtjz.cn/article/ppoppj.html

其他资讯