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

      项目需求,复用了一段之前写过的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方法。

转载于:https://my.oschina.net/BiaoLei/blog/552925

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值