文档章节

C调用Golang动态库时的坑与个人解决方法

WangRichard
 WangRichard
发布于 2015/12/29 16:57
字数 595
阅读 180
收藏 2
点赞 0
评论 0

      项目需求,复用了一段之前写过的Go代码,利用Go 1.5的新功能导出了一个可以给C语言使用的动态库。由于目前Go的结构体还不支持直接导出到C,因此使用了interface{}作为过渡。结构体以及导出函数定义如下

type Handler struct{
    stream *Stream
    p      *Parser
}

//export NewHandler
func NewHandler() interface{}{
    return Handler{
      //成员变量初始化
    }
}

//export Func1
func Func1(handler interface{}){
  if h, ok := handler.(Handler);ok{
      //访问stream成员
      foo1(h.stream)
  }
}

//export Func2
func Func2(handler interface{}){
  if h, ok := handler.(Handler);ok{
      //访问stream成员
      foo2(h.stream)
  }
}

      按照如上写法,在C代码中依次调用,在执行Func1时还算ok,但是在执行到Func2时,则报了h.stream内存地址非法的错误,暂时还不明白stream在哪被gc了,还望各位赐教。

      另外,如下代码则没问题。

//export NewHandler
func NewHandler() interface{}{
    return &Handler{
      //成员变量初始化
    }
}

//export Func1
func Func1(handler interface{}){
  if h, ok := handler.(*Handler);ok{
      //访问stream成员
      foo1(h.stream)
  }
}

//export Func2
func Func2(handler interface{}){
  if h, ok := handler.(*Handler);ok{
      //访问stream成员
      foo2(h.stream)
  }
}

更新1: 2015.12.30 测试结果表明,改为指针也不能有效解决该问题,仍然会出现内存地址非法情况,看来是Go里面的对象导出给C使用后,gc对该对象的跟踪出了问题,导致在C里边还在使用该对象时却被Go里边回收了。

更新2: 由于是被Go内部gc,考虑在Go代码增加一对象池防止对象被gc,另外考虑到给不熟悉Go的使用C的童鞋,此处返回unsafe.Pointer代替之前的interface{},更改后的逻辑如下

var(
 	obj_pool = map[unsafe.Pointer]*Handler{}
	lock     = make(chan bool, 1)
)

type Handler struct{
    stream *Stream
    p      *Parser
}

//export NewHandler
func NewHandler() unsafe.Pointer{
    p:= &Handler{
      //成员变量初始化
    }
    lock <- true
    defer func() { <-lock }()
    obj_pool[unsafe.Pointer(p)] = p
    return unsafe.Pointer(p)    
}

//其他导出函数...
//......

//export ReleaseHandler
func ReleaseHandler(handler unsafe.Pointer){
     lock <- true
     defer func() { <-lock }()
     if _, ok := obj_pool[handler]; ok {
	 delete(obj_pool, handler)
     }
}

      增加对象池后,之前的Go导出对象被gc的问题基本上已经没看到了,相当于变相在Go里面增加对象引用以防止被gc。此外,为了防止资源泄露,采用对象池的方法处理后,自然需要添加一个释放对象的逻辑,于是增加ReleaseHandler方法。

© 著作权归作者所有

共有 人打赏支持
WangRichard
粉丝 4
博文 9
码字总数 11049
作品 0
东城
其他
golang的调用shell的库--go-sh

go-sh是一个golang的调用shell的库。 使用linux的人都知道shell脚本有它难以取代的优势,用2个词形容就是,简单、粗暴。但是shell有不少的坑,很容易就写的换个机器就不能使了。golang的优势...

go-skyblue ⋅ 2014/02/09 ⋅ 3

go笔记1-helloWorld

有一次听一个沙龙技术演讲,讲师说go是互联网时代的c,听了详细介绍以后感觉很赞,尤其是并行层面真正在语言层面上做了控制及特殊的内存管理机制等。。。 好吧,下面上先上helloWorld代码。(...

老范的自留地 ⋅ 2012/10/29 ⋅ 3

使用 golang 实现类似 pthread_barrier_t 语义的 barrier 对象

看到golang标准库sync package WaitGroup 类型, 本以为是golang 版本的 barrier 对象实现,看到文档给出的使用示例: var wg sync.WaitGroup var urls = []string{ "http://www.golang.org/"...

yujian0231 ⋅ 2015/01/18 ⋅ 0

golang基础-防忘指北

一 坑 1. 用自带的 json 库序列化 strut 变量时,只有那些首字母大写的变量才会被序列化,这意味着在go的世界里,所有的json属性名都是大写开头...这真的不是bug吗...(ps : 已经找到大写转小...

GameKing ⋅ 2016/03/19 ⋅ 0

go学习笔记0-helloWorld

有一次听一个沙龙技术演讲,讲师说go是互联网时代的c,听了详细介绍以后感觉很赞,尤其是并行层面真正在语言层面上做了控制及特殊的内存管理机制等。。。 好吧,下面上先上helloWorld代码。(...

老范的自留地 ⋅ 2014/06/01 ⋅ 0

Go和汇编联合编程

上篇讲了怎么利用iso c和golang联合开发。这里讲下怎么利用汇编程序开发基本类库,然后提供给golang语言调用。 为什么有了golang语言还要说汇编程序,这是因为在现在golang提供的库还是不全的...

曾赛 ⋅ 2010/06/04 ⋅ 0

Linux静态库和动态库的编写和使用

库从本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行。库分静态库和动态库两种。 1 静态库和动态库的区别1.1. 静态函数库(1)静态函数库的名字一般是lib[name].a(2)利用静态函...

hnxymjj ⋅ 2013/09/08 ⋅ 0

次时代Java编程(一):Java里的协程

什么是协程(coroutine) 这东西其实有很多名词,比如有的人喜欢称为纤程(Fiber),或者绿色线程(GreenThread)。其实最直观的解释可以定义为线程的线程。有点拗口,但本质上就是这样。 我们先回...

力谱宿云 ⋅ 2016/05/25 ⋅ 0

Windows 下GCC编译C程序调用Golang静态库和C动态库

编译golang 静态库 package main import ( "C" "fmt") //export Foofunc Foo(a, b int) int { return a + b} //export Barfunc Bar() { fmt.Println("Hello, I'm LiLei.")} func main() { }......

hotkit ⋅ 02/06 ⋅ 0

go语言文件汇总

归并排序及go语言实现 堆排序算法及go语言实现 Go语言基础学习(一)变量 【Leetcode】:Counting Bits问题 in Go语言 基于go语言的心跳响应 【Leetcode】:Single Number III问题 in Go语言 ...

d_watson ⋅ 2016/04/15 ⋅ 2

没有更多内容

加载失败,请刷新页面

加载更多

下一页

20.zip压缩 tar打包 打包并压缩

6月25日任务 6.5 zip压缩工具 6.6 tar打包 6.7 打包并压缩 6.5 zip压缩工具: zip支持压缩目录 zip压缩完之后原来的文件不删除 不同的文件内容其实压缩的效果不一样 文件内有很多重复的用xz压...

王鑫linux ⋅ 13分钟前 ⋅ 0

double类型数据保留四位小数的另一种思路

来源:透析公式处理,有时候数据有很长的小数位,有的时候由在四位以内,如果用一般的处理方法,那么不足四位的小树会补充0到第四位,这样子有点画蛇添足的感觉,不太好看。所以要根据小数的...

young_chen ⋅ 20分钟前 ⋅ 0

Python 优化 回溯下降算法

使用sympy构造表达式,实现回溯下降算法 画出函数图像,先使用暴力搜索,找到最小值约为2.5左右 然后选定初始点,开始进行回溯搜索,下降方向为负梯度方向 下降的误差与步数大致呈现下面的状...

阿豪boy ⋅ 24分钟前 ⋅ 0

Django配置163邮箱出现 authentication failed(535)错误解决方法

最近用Django写某网站,当配置163邮箱设置完成后,出现535错误即:smtplib.SMTPAuthenticationError: (535, b'Error: authentication failed') Django初始配置邮箱设置 EMAIL_HOST = "smtp.1...

陈墨轩_CJX ⋅ 26分钟前 ⋅ 0

用接口模拟可伸缩枚举(34)

1、枚举的可伸缩性最后证明都不是什么好点子 扩展类型的元素是基本类型实例,基本类型的实例却不是扩展类型的元素,很混乱 目前还没有很好的方法来枚举基本类型的所有元素,及其扩展 可伸缩性...

职业搬砖20年 ⋅ 29分钟前 ⋅ 0

Ubuntu18.04 IDEA快捷键无法使用

IDEA默认的回退到上一视图的快捷键是Ctrl + Alt + Left,在ubuntu中这个快捷键被占用了,在16.04中可以在界面中取消这个快捷键,但是18.04就看不到了,可以使用以下命令解决 gsettings set ...

Iceberg_XTY ⋅ 34分钟前 ⋅ 0

如何解决s权限位引发postfix及crontab异常

一、问题现象 业务反馈某台应用服务器,普通用户使用mutt程序发送邮件时,提示“postdrop warning: mail_queue_enter: create file maildrop/713410.6065: Permission denied”,而且普通用法...

问题终结者 ⋅ 46分钟前 ⋅ 0

Unable to load database on disk

由于磁盘空间满了以后,导致zookeeper异常退出,清理磁盘空间后,zk启动报错,信息如下: 2018-06-25 17:18:46,904 INFO org.apache.zookeeper.server.quorum.QuorumPeerConfig: Reading co...

刀锋 ⋅ 今天 ⋅ 0

css3 box-sizing:border-box 实现div一行多列

<!DOCTYPE html><html><head><style> div.container{ background:green; padding:10px 10px;}div.box{box-sizing:border-box;-moz-box-sizing:border-box; /* Fir......

qimh ⋅ 今天 ⋅ 0

Homebrew简介和基本使用

一、Homebrew是什么 Homebrew是一款Mac OS平台下的软件包管理工具,拥有安装、卸载、更新、查看、搜索等很多实用的功能。简单的一条指令,就可以实现包管理,而不用你关心各种依赖和文件路径...

说回答 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部