C 呼叫Go方法的字串傳遞問題及解決方案

2022-09-25 06:45:14 字數 2067 閱讀 1819

摘要:c++呼叫go方法時,字串引數的記憶體管理需要由go側進行深度值拷貝。

現象在乙個app技術專案中,子程序按請求載入go的servicemodule,將需要拉起的servicemodule資訊傳遞給go的loader,存在c++呼叫go方法,傳遞字串的場景。

方案驗證時,發現有奇怪的將std::string物件的內容傳遞給go方法後,在go方法協程中取到的值與預期不一致。

經過一段時間的分析和驗證,終於理解問題產生的原因並給出解決方案,現分享如下。

背景知識

原理及解釋

通過**示例方式解釋具體現象及原因,詳見注釋

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) _gostring_;

//typedef _gostring_ gostring;

return ;

}

int main()

pause();

}go側**:

package main

import "c"

import (

"fmt"

"time"

)

func printingo(p0 string, p1 string, p2 string)

//export loadmodule

func loadmodule(name string, version string, location string) int

go側**通過-buildmode=c-shared的方式生成libgoloader.so及libgoloader.h供c++編譯執行使用

go build -o libgoloawww.cppcns.comder.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:     &n程式設計客棧bsp;  p���  netconftemplateservice size 38, p2:/tmp/udsgateway-netconftemplateservice size 38

結論在c++**中,任何對成員p的char*指標的操作,都將直接影響到go中的string物件的值。

只有通過單獨的記憶體空間開闢,進行獨立記憶體管理,才可以避免c++中的指標操作對go的影響。

ps:不在c++中進行記憶體申請釋放的原因是c++無法感知go中何時才能真的已經沒有物件引用,無法找到合適的時間點進行記憶體釋放。

C 呼叫Dll 傳遞字串指標引數

最近用c 寫乙個小軟體,要呼叫vc寫的dll,傳遞引數給dll,由於是非託管 所以呼叫起來有點麻煩,要把引數轉換成非託管 的指標引數,然後再傳遞給dll using system.runtime.interopservices 操作dll的類空間 class cgicomindex marshal....

go字串拼接方法

go 語言中的字串是唯讀的 拼接方式 這種方式是我在寫golang經常用的方式,go語言用 拼接,php使用.拼接,不過由於golang中的字串是不可變的型別,因此用 連線會產生乙個新的字串對效率有影響。go語言中文文件 www.topgoer.com func main sprintf函式 s1 ...

c函式傳遞字串

把具有相同型別的若干變數按有序的形式組織起來,這些按序排列的同類資料元素的集合稱為陣列。按陣列元素的型別不同,陣列又可分為數值陣列 字元陣列 指標陣列 結構陣列等各種類別,因此,字元陣列是陣列的一種。字元陣列實際上是一系列字元的集合,也就是字串 string 由此可得 在函式中傳遞乙個字串與傳遞乙個...