英文:
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 "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; // 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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论