通过一个例子演示golang调用C语言动态链接库中的函数

news/2024/12/21 22:07:45/

本例提供了cgo调用C函数的示例,也演示了如何将C函数打印内容保存到golang的变量中

目录和源码

  • 目录结构
admin@hpc-1:~/go/my_stdout$ tree
.
├── include
│   ├── mylibrary.c
│   └── mylibrary.h
├── lib
└── main.go2 directories, 3 files
admin@hpc-1:~/go/my_stdout$ 
  • include目录下放C的源码和头文件
admin@hpc-1:~/go/my_stdout$ cat include/mylibrary.c
#include <stdio.h>void writeToStdout() {printf("Hello from C!\n");
}
admin@hpc-1:~/go/my_stdout$ 
admin@hpc-1:~/go/my_stdout$ cat include/mylibrary.h
#ifndef MYLIBRARY_H
#define MYLIBRARY_Hvoid writeToStdout();#endif
admin@hpc-1:~/go/my_stdout$ 
  • golang的源码
admin@hpc-1:~/go/my_stdout$ cat main.go 
package main/*
#cgo CFLAGS: -I./include
#cgo LDFLAGS: -L${SRCDIR}/lib -lmyprint -Wl,-rpath=${SRCDIR}/lib 
#include "mylibrary.h"
#include <stdio.h>
*/
import "C"import ("syscall""bytes""log""fmt""io""os"
)func main() {// 克隆 Stdout 到 origStdout.origStdout, err := syscall.Dup(syscall.Stdout)if err != nil {log.Fatal(err)}// 创建管道reader, writer, err := os.Pipe()if err != nil {log.Fatal(err)}// 此后stdout将会写到writerif err = syscall.Dup2(int(writer.Fd()), syscall.Stdout); err != nil {log.Fatal(err)}// 启动背景 goroutine 收集输出out := make(chan []byte)go func() {var b bytes.Bufferio.Copy(&b, reader)out <- b.Bytes()}()// 调用C函数打印C.writeToStdout()// 一些清理工作C.fflush(nil)writer.Close()syscall.Close(syscall.Stdout)// 导出outputrecord := <-out// Restore original Stdout.syscall.Dup2(origStdout, syscall.Stdout)syscall.Close(origStdout)fmt.Println("Captured:", string(record))
}
admin@hpc-1:~/go/my_stdout$ 

编译和运行

  • 首先编译出C的lib,放到./lib目录下
admin@hpc-1:~/go/my_stdout$ gcc -shared -o ./lib/libmyprint.so include/mylibrary.c
admin@hpc-1:~/go/my_stdout$ 
admin@hpc-1:~/go/my_stdout$ ls -lt ./lib/
total 16
-rwxrwxr-x 1 centec centec 16208 2-р сар  27 07:29 libmyprint.so
admin@hpc-1:~/go/my_stdout$ 
  • 运行golang程序,Captured:后面就是获取的C函数打印的显示内容
admin@hpc-1:~/go/my_stdout$ go run main.go 
Captured: Hello from C!admin@hpc-1:~/go/my_stdout$ 

一些说明

  • Go 语言提供了 cgo 工具,用于在 Go 代码中调用 C 代码或让 C 代码调用 Go 代码。cgo 允许在 Go 代码中使用 C 函数、类型和变量,并提供了一种在两种语言之间进行交互的机制。
    • import "C"上面紧挨的被注释的部分,就是和C有关的信息
    • #cgo CFLAGS: -I./include指定C源码和头文件所在目录
    • -L${SRCDIR}/lib指定C编程的lib文件所在目录
    • -lmyprint其中-l的后面,是lib文件名(‘libmyprint.so’)去掉开头的’lib’后最后的’.so’之后的部分
    • -rpath=${SRCDIR}/lib指定了程序运行时候,到哪里去找lib文件,也就是说运行该程序的地方,一定要有用到的.so文件
    • 接下来的两个#include就是标准的C语言预处理指令
  • syscall.Dup2 函数用于复制文件描述符(file descriptor)到指定的目标文件描述符。它使得目标文件描述符成为源文件描述符的副本,两个文件描述符指向同一个底层文件或资源
  • os.Pipe() 函数用于创建一个管道(Pipe),它提供了在同一程序内部的两个不同 goroutine 之间进行进程间通信(IPC)的机制

http://www.ppmy.cn/news/1365050.html

相关文章

Android 框架设计模板

不同项目在使用该模板时多少会有出入&#xff0c;应以项目实际情况作为依据。 &#xff08;该文档可以 .md 格式存放于项目根目录&#xff0c;或编写到readme 中&#xff09; 项目描述 涉及如下方面 项目背景 &#xff08;可引用项目立项书&#xff09;项目需求 &#xff08…

【kubernetes】关于k8s集群的声明式管理资源

目录 一、声明式管理方法 二、资源配置清单管理 1、导出资源配置清单 2、修改资源配置清单并应用 2.1离线修改 2.2在线修改 三、通过资源配置清单创建资源对象 获取K8S资源配置清单文件模板&#xff1f; 关于配置清单常见的字段 方案一&#xff1a;手写yaml配置文件 …

QT C++实践|超详细数据库的连接和增删改查操作|附源码

0&#xff1a;前言 &#x1faa7; 什么情况需要数据库? 1 大规模的数据需要处理&#xff08;比如上千上万的数据量&#xff09;2 需要把数据信息存储起来&#xff0c;无论是本地还是服务上&#xff0c;而不是断电后数据信息就消失了。 如果不是上面的原因化&#xff0c;一般…

学习JAVA的第四天(基础)

目录 方法 方法的定义 方法的调用 参数 注意事项 方法的重载 练习 面向对象 类和对象 定义类的注意事项 封装 private关键字 this关键字 构造方法 标准的Javabean类 创建一个对象时&#xff0c;虚拟机做了什么&#xff1f; 方法 方法含义&#xff1a;方法是程序…

Node.js+vue校内二手物品交易系统tdv06-vscode前后端分离

二手物品交易系统采用B/S架构&#xff0c;数据库是MySQL。网站的搭建与开发采用了先进的nodejs进行编写&#xff0c;使用了vue框架。该系统从三个对象&#xff1a;由管理员和用户、店铺来对系统进行设计构建。主要功能包括&#xff1a;个人信息修改&#xff0c;对用户、店铺、二…

【面试题】在浏览器地址栏输入URL后会发生什么

1. 地址栏输入后的本地操作 当我们在浏览器的地址栏中&#xff0c;输入xxx内容后&#xff0c;浏览器的进程首先会判断输入的内容&#xff1a; 如果是普通的字符&#xff0c;那浏览器会使用默认的搜索引擎去对于输入的xxx生成URL。如若输入的是网址&#xff0c;那浏览器会拼接…

golang使用gorm操作mysql1

1.mysql连接配置 package daoimport ("fmt""gorm.io/driver/mysql""gorm.io/gorm""gorm.io/gorm/logger" )var DB *gorm.DB// 连接数据库&#xff0c;启动服务的时候&#xff0c;init方法就会执行 func init() {username : "roo…

binwalk安装记录和burpsuite安装记录

我的虚拟机环境是Ubuntu20.04 python有2.7的和3.8的 [[#binwalk|binwalk]] [[#binwalk#pip|pip]][[#binwalk#安装 sasquatch|安装 sasquatch]][[#binwalk#安装 jefferson|安装 jefferson]][[#binwalk#安装 ubi_reader|安装 ubi_reader]][[#binwalk#安装 yaffshiv|安装 yaffshi…