使用 Go 语言构建 C 库

CGO is an official builtin feature of Go, it enables the creation of Go packages that reference to C libraries. But it isn’t just that, it is achievable in the opposite direction, too. It enables creation of C libraries from Go packages so that C code can reference to Go, which is mind-blowing.

CGO 不但可以使 Go 包访问 C 库,还可以通过 Go 包创建 C 库,进而使 C/C++ 程序可调用 Go 语言程序。

1.How to

1.1.Build Go package as C shared library (or shared object)

Every Go main package can be built as a C shared library.

任何 Go main 包都可以创建 C 库。

go build -buildmode=c-shared -o <c-lib>.so

Executing above command builds target Go main package and all of its dependencies as a single C shared library, which can be distributed, installed and linked to every C application and applications in other programming languages that can reference C shared libraries (C++, Python, Javascript, etc).

以上命令可以创建共享库,该共享库可以被 C、C++、Python、Javascript 等语言访问。

Note: Output C shared libraries should be named in standard form lib*.so.

1.2.Generate C header and export Go functions as C functions

Building a Go main package as C shared library doesn’t automatically neither generate C header nor expose any Go function as C symbol. Developers have to explicitly indicate which Go functions to be exposed.

To export a Go function as a C symbol:

  • The function must belong to main package.
  • The Go code file containing the function has to import “C”.
  • Add comment //export FuncName on top of the Go function.
  • The function signature must not include neither Go struct nor* Go interface nor Go array nor variadic argument.

上述命令不会生成 C 头文件并导出符号。若想导出符号并自动生成头文件需要满足以下条件:

  • 要导出的函数必须属于 main 包;
  • Go 源码文件包含 import “C”
  • 在要导出的函数使用 //export FuncName 注释;
  • 不能使用 Go struct、Go interface、Go arra、以及可变参数。

2.Example

package main

import "C"

import (
    "math/rand"
    "time"
)

//export cgoCurrentMillis
func cgoCurrentMillis() C.long {
    return C.long(time.Now().Unix())
}

//export cgoSeed
func cgoSeed(m C.long) {
    rand.Seed(int64(m))
}

//export cgoRandom
func cgoRandom(m C.int) C.int {
    return C.int(rand.Intn(int(m)))
}

func main() {}

Building above Go main package generates a C header file <output>.h along with a C shared object <output>.so.

构建以上示例将自动产生头文件和共享库。

// Other stuff.

extern long int cgoCurrentMillis();
extern void cgoSeed(long int p0);
extern int cgoRandom(int p0);

cgoCurrentMilli, cgoSeed and cgoRandom are exposed as C symbols in <output>.so, too.

Now, every C application can include the generated C header, link to the output C shared library and use exposed C symbols.

#include <stdio.h>

int main() {
    cgoSeed(cgoCurrentMillis());

    printf("Hello World from C!\n");
    printf("cgoRandom() -> %d\n", cgoRandom(256));
    return 0;
}

编译方法如下:

gcc main.c -l<c-lib> -o <exe-file>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
根据提供的引用内容,没有直接提到如何使用Go语言构建图书管理系统。但是,我们可以通过以下步骤来构建一个基本的图书管理系统: 1. 首先,我们需要选择一个适合的Go Web框架,例如Gin或Echo。这些框架可以帮助我们快速构建Web应用程序。 2. 接下来,我们需要设计数据模式并创建数据。我们可以使用MySQL或PostgreSQL等关系型数据,也可以使用MongoDB等NoSQL数据。 3. 然后,我们需要编写Go代码来连接数据并执行CRUD操作。我们可以使用ORM,例如GORM或XORM,来简化数据操作。 4. 接下来,我们需要编写API来处理HTTP请求。我们可以使用框架提供的路由功能来定义API路由,并使用中间件来处理身份验证、日志记录等功能。 5. 最后,我们需要编写前端代码来呈现数据。我们可以使用Vue.js或React等JavaScript框架来构建前端应用程序。 以下是一个简单的示例代码,用于演示如何使用Gin框架和GORM构建图书管理系统: ```go package main import ( "github.com/gin-gonic/gin" "gorm.io/driver/mysql" "gorm.io/gorm" ) type Book struct { gorm.Model Title string Author string } func main() { // 连接数据 dsn := "user:password@tcp(127.0.0.1:3306)/database?charset=utf8mb4&parseTime=True&loc=Local" db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) if err != nil { panic("failed to connect database") } // 自动迁移模式 db.AutoMigrate(&Book{}) // 创建路由 r := gin.Default() // 添加书籍 r.POST("/books", func(c *gin.Context) { var book Book if err := c.ShouldBindJSON(&book); err != nil { c.JSON(400, gin.H{"error": err.Error()}) return } db.Create(&book) c.JSON(200, book) }) // 获取所有书籍 r.GET("/books", func(c *gin.Context) { var books []Book db.Find(&books) c.JSON(200, books) }) // 获取单个书籍 r.GET("/books/:id", func(c *gin.Context) { var book Book if err := db.First(&book, c.Param("id")).Error; err != nil { c.JSON(404, gin.H{"error": "Record not found"}) return } c.JSON(200, book) }) // 更新书籍 r.PUT("/books/:id", func(c *gin.Context) { var book Book if err := db.First(&book, c.Param("id")).Error; err != nil { c.JSON(404, gin.H{"error": "Record not found"}) return } if err := c.ShouldBindJSON(&book); err != nil { c.JSON(400, gin.H{"error": err.Error()}) return } db.Save(&book) c.JSON(200, book) }) // 删除书籍 r.DELETE("/books/:id", func(c *gin.Context) { var book Book if err := db.First(&book, c.Param("id")).Error; err != nil { c.JSON(404, gin.H{"error": "Record not found"}) return } db.Delete(&book) c.JSON(200, gin.H{"message": "Record deleted"}) }) // 启动服务器 r.Run(":8080") } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lionchan187

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值