Golang:使用CGo将C字段导出为外部可见

huangapple go评论89阅读模式
英文:

Golang: Export C fields to be externally visible using CGo

问题

背景:我正在尝试创建一个包,它基本上提供了对我正在使用的C库的Go封装。该包故意非常原始,因为其他几个包依赖于C库的底层功能,我不想复制粘贴大量的Go封装代码。

假设我有一个C结构体,如下所示:

typedef struct {
    uint32_t fizz;
    uint64_t buzz;
} test

在CGo中,我封装了C结构体并创建了新的方法,如下所示:

package test    

type Test C.test

func NewTest() *Test {
    return &Test{1,2}
}

问题是,在包的外部,我无法访问C结构体中的字段:

package main

import "test"

func main() {
    t := test.NewTest()
    _ = t.fizz // 错误!!!未导出的字段名!!!
}

除了为每个字段创建访问器方法之外,是否有其他简单的方法解决这个问题?

英文:

Background: I'm trying to make a package that essentially provides thin Go wrappers around a C library that I'm using. The package is intentionally very raw, since several other packages depend on the low level functionalities of the C library and I don't want to copy-pasta a bunch of Go wrapper code.

Suppose I have a C-struct that looks like:

typedef struct {
    uint32_t fizz;
    uint64_t buzz;
} test

And in CGo, I wrap the C-struct and create new methods as follows:

package test    

type Test C.test

func NewTest() *Test {
    return &Test{1,2}
}

The problem is that outside of the package, I can't access the fields in the C-struct

package main

import "test"

func main() {
    t := test.NewTest()
    _ = t.fizz // ERROR!!! Unexported field name!!
}

Is there any easy way around this (other than create accessor methods for every field)?

答案1

得分: 1

是的,你可以导出C结构体。但是你需要遵循与导出Golang结构体相同的规则。http://golang.org/ref/spec#Exported_identifiers

##main.go##

package main

import "test"

func main() {
    t := test.NewTest()
    println(t.Fizz)
}

##test/test.go##

package test

/*
   #include "test.h"
*/
import "C"

type Test C.test

func NewTest() *Test {
    return &Test{Fizz: 1, Buzz: 2}
}

##test/test.h##

#include <stdint.h>

typedef struct {
    uint32_t Fizz;   // 注意第一个字符是大写的
    uint64_t Buzz;
} test;

如果由于某种原因无法修改C结构体中的字段名称,则需要创建一个新的C结构体,其布局与原结构体完全相同,但标识符为大写。

英文:

Yes, you can export C structs. But you'll need to follow the same rules for exporting a C struct as you would a Golang struct. http://golang.org/ref/spec#Exported_identifiers

##main.go##

package main

import &quot;test&quot;

func main() {
    t := test.NewTest()
	println(t.Fizz)
}

##test/test.go##

package test

/*
   #include &quot;test.h&quot;
*/
import &quot;C&quot;

type Test C.test

func NewTest() *Test {
	return &amp;Test{Fizz: 1, Buzz: 2}
}

##test/test.h##

#include &lt;stdint.h&gt;

typedef struct {
    uint32_t Fizz;   // notice that the first character is upper case
    uint64_t Buzz;
} test;

If for whatever reason you are unable to modify the field names in the C struct, then you will need to create a new C struct that matches the exact layout, but with the Uppercase identifiers.

huangapple
  • 本文由 发表于 2014年8月9日 17:31:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/25217132.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定