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

本例提供了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.mzph.cn/news/707713.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

产品老化试验目的、用途

什么是老化试验&#xff1f; 老化试验是通过模拟产品在使用过程中的老化情况&#xff0c;来评估产品在长期使用后的性能和可靠性。这种测试可以帮助制造商了解产品的寿命和耐久性&#xff0c;以及产品在不同环境条件下的表现。 模拟量采集/老化房采集软件 为什么需要进行老化试…

智慧公厕:让城市更智慧、更环保

在现代社会&#xff0c;智慧公厕作为城市管理的重要一环&#xff0c;是智慧城市的重要组成部分&#xff0c;其建设的价值十出突出&#xff0c;是公共厕所信息化升级改造的核心方案。如智慧公厕源头厂家广州中期科技有限公司&#xff0c;所自主研发的智慧公厕整体解决方案&#…

【HarmonyOS】鸿蒙开发之Video组件——第3.7章

Video组件内VideoOptions属性简介 src&#xff1a;设置视频地址。currentProgressRate&#xff1a;设置视频播放倍速&#xff0c;参数说明如下&#xff1a; number|string&#xff1a;只支持 0.75 &#xff0c; 1.0 &#xff0c; 1.25 &#xff0c; 1.75 &#xff0c; 2.0 。P…

安装 docker 可视化工具 portainer

portainer 官方网站 https://www.portainer.io/ 一、portainer 介绍 Portainer是一款开源的容器管理平台&#xff0c;它提供了一个直观易用的Web界面&#xff0c;帮助用户管理Docker容器集群、镜像、卷等资源。Portainer 支持多种 Docker 环境&#xff0c;包括本地Docker、Sw…

智能手表的革命性突破:TRIZ理论引领未来穿戴技术!

在科技日新月异的今天&#xff0c;智能手表已经从单纯的计时工具转变为集健康监测、信息通讯、娱乐休闲等多功能于一体的智能穿戴设备。而基于TRIZ理论的智能手表更是在这一变革中扮演着引领者的角色。TRIZ&#xff0c;即发明问题解决理论&#xff0c;是一套系统的创新方法学&a…

vue实现文件上传的功能

随着Web应用的发展&#xff0c;文件上传功能已经变得越来越常见。vue是一种流行的JavaScript框架&#xff0c;提供了便捷的方式来构建现代化的Web应用程序。在vue中&#xff0c;可以通过使用vue的Upload组件来实现文件上传功能。以下介绍如何使用vue来实现文件上传功能。 首先…

单例模式:饿汉式、懒汉式;线程安全的单例模式创建的6种方式

单例模式 单例模式Singleton是一种创建型模式&#xff0c;指某个采用Singleton单例模式&#xff0c;则这个类在同一个 JVM上&#xff0c;只能产生一个实例供外部访问&#xff0c;并且仅提供一个全局的访问方式。 懒汉式 懒汉式线程不安全 public class Singleton1 {privat…

迭代器模式(Iterator Pattern)

定义 迭代器模式&#xff08;Iterator Pattern&#xff09;是一种行为型设计模式&#xff0c;它提供了一种方法来顺序访问聚合对象中的各个元素&#xff0c;而不需要暴露该对象的内部表示。迭代器模式使得客户端代码能够独立于聚合对象的具体实现进行遍历操作。 在迭代器模式…

使用vue把一周的时间划分为可以选择多个阶段

提示:使用vue把一周的时间划分为可以选择多个阶段段(亲测有效) 一、直接复制以下代码 代码如下(示例): <template><div class="byted-weektime" @mousedown="dian" @mousemove="yi" @mouseup="li"><div class=&q…

连不上网的解决办法集--持续更新

连不上网的解决办法集–持续更新 1、有网卡&#xff0c;但网卡驱动失效 背景&#xff1a;有网络驱动但是依旧连不上网&#xff0c;只有inteV6有值&#xff0c;inte 没有值&#xff08;正常应该有个ipv4的信息&#xff09; 判断原因&#xff1a;可能是之前格式化磁盘驱动的时…

【iOS ARKit】协作Session

使用 ARWorldMap&#xff0c;能解决使用者再次进入同一物理空间时的AR 场景恢复问题&#xff0c;也能在多人之间共桌AR 体验&#xff0c;但这种共享并不是实时的&#xff0c;在载入ARWorldMap 后&#xff0c;设备新检测到的环境信息和使用者所做操作不会实时共享&#xff0c;即…

【MATLAB】 小波分解信号分解+FFT傅里叶频谱变换组合算法

有意向获取代码&#xff0c;请转文末观看代码获取方式~ 展示出图效果 1 小波分解算法 小波分解算法是一种数学方法&#xff0c;用于将信号分解为不同频率的小波成分。这种算法基于小波函数&#xff0c;可以用于信号处理、图像压缩和数据压缩等领域。小波分解算法的基本思想是…

nginx的nginx.conf的基本配置方法

#定义Nginx运行的用户和用户组 user www www; #nginx进程数&#xff0c;建议设置为等于CPU总核心数。 worker_processes 8; #全局错误日志定义类型&#xff0c;[ debug | info | notice | warn | error | crit ] error_log /var/log/nginx/error.log info; #进程文件 pi…

LeetCode59. 螺旋矩阵 II(C++)

LeetCode59. 螺旋矩阵 II 题目链接代码 题目链接 https://leetcode.cn/problems/spiral-matrix-ii/ 代码 class Solution { public:vector<vector<int>> generateMatrix(int n) {vector<vector<int>> res(n, vector<int>(n, 0));int startx …

数据结构:栈和队列与栈实现队列(C语言版)

目录 前言 1.栈 1.1 栈的概念及结构 1.2 栈的底层数据结构选择 1.2 数据结构设计代码&#xff08;栈的实现&#xff09; 1.3 接口函数实现代码 &#xff08;1&#xff09;初始化栈 &#xff08;2&#xff09;销毁栈 &#xff08;3&#xff09;压栈 &#xff08;4&…

代码随想录算法训练营第27天—贪心算法01 | ● 理论基础 ● 455.分发饼干 ● 376. 摆动序列 ● 53. 最大子序和

理论基础 https://programmercarl.com/%E8%B4%AA%E5%BF%83%E7%AE%97%E6%B3%95%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html 贪心算法的本质&#xff1a;由局部最优推到全局最优贪心算法的套路&#xff1a;无固定套路 455.分发饼干 https://programmercarl.com/0455.%E5%88%8…

前端面试题(一)

1、说一下vue生命周期 什么是生命周期 Vue 实例从创建到销毁的过程就是生命周期。从开始创建&#xff0c;初始化数据&#xff0c;编译模板&#xff0c;挂载 Dom 到渲染&#xff0c;更新到渲染&#xff0c;销毁等一系列过程&#xff0c;称之为生命周期。 Vue生命周期共有8个阶…

【毕业设计推荐】基于MATLAB的水果分级系统设计与实现

一、课题介绍 现在商业行为中&#xff0c;在水果出厂前都需要进行质量检测&#xff0c;需要将不同等级的水果进行分级包装&#xff0c;以保证商业利益最大化。可是传统方法都是依靠人工进行检测&#xff0c;效率低下&#xff0c;主观成分大&#xff0c;并不能很好客观地评价出货…

流畅的Python(十四)-可迭代对象、迭代器和生成器

一、核心要义 1. 使用iter内置函数处理可迭代对象的方式 2. 如何使用Python实现经典的迭代器模式 3. 生成器函数工作原理 4. 使用生成器函数或生成器表达式代替经典的迭代器 5. 使用yield from语句合并生成器 二、代码示例 1、遍历单词序列回顾 #!/usr/bin/env python …

电脑WiFi共享给电脑的网口,另一终端可通过该网口进行上网。可用于wireshark抓设备终端的包。

1、点击WinR&#xff0c;弹出命令框&#xff0c;输入services.msc 2、选中“Internet Connection Sharing”这个服务右键&#xff0c;点击属性打开&#xff0c;启动类型选择“自动”&#xff0c;确定保存 3、点击WinR&#xff0c;弹出命令框&#xff0c;输入regedit 4、找到路径…