Go语言中CGO的使用例子
部门产品业务功能采用Golang开发,但是有些功能是用c写的,比如说net-snmp,bfd协议等等,像这些如果使用GO语言重编的话,既有实现的复杂度也需要相当长的时间,好在GO语言提供了CGO机制,使得能够在go代码中直接调用C的库函数,大大提高了效率,减少了重复开发工作,此外还支持在C语言中调用GO函数,这一点还是蛮强大的。
1. Go语言调用C函数例子:
package main//
// 引用的C头文件需要在注释中声明,紧接着注释需要有import "C",且这一行和注释之间不能有空格
///*
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>void myprint(char* s) {printf("%s\n", s);
}*/
import "C"import ("fmt""unsafe"
)func main() {//使用C.CString创建的字符串需要手动释放。cs := C.CString("Hello World\n")C.myprint(cs)C.free(unsafe.Pointer(cs))fmt.Println("call C.sleep for 3s")C.sleep(3)return
}
运行:
2. Go语言调用C库函数:
hello.c
#include <stdio.h>
void hello()
{printf("hello world\n");
}
hello.h
#ifndef HELLO_H
#define HELLO_Hvoid hello(void);
#endif
编译:
gcc -c hello.c
ar -cru libhello.a hello.o
package main//使用#cgo定义库路径/*
#cgo CFLAGS: -I .
#cgo LDFLAGS: -L . -lhello
#include "hello.h"
*/
import "C"func main() {C.hello()
}
运行:
3. Go语言导出函数给C语言使用:
main.go
package main//
//#include <stdio.h>
//int add(int a, int b);
//
import "C"import ("fmt"
)//当使用export的时候,在同一个文件中就不能再定义其它的c函数了,不然会报错。
//使用export导出函数给c语言调用。//export GoAdd
func GoAdd(a, b int) int {return a + b
}func main() {a := C.add(1, 2)fmt.Printf("C.add(1,2) return %d\n", a)
}
cfunc.go
package main//
//int GoAdd(int a, int b);
//
//int add(int a, int b)
//{
// return GoAdd(a,b);
//}
//
import "C"
运行:
4. Go语言导出函数指针给c语言使用:
还有一种使用方式,这种是我使用比较多的。就是传递函数指针,因为GO函数无法取址,因此需要写个中间函数做个转换操作,例子如下:
clibrary.c
#include <stdio.h>#include "clibrary.h"//参数是函数指针
void some_c_func(callback_fcn callback)
{int arg = 2;printf("C.some_c_func(): calling callback with arg = %d\n", arg);int response = callback(2);printf("C.some_c_func(): callback responded with %d\n", response);
}
clibrary.h
#ifndef CLIBRARY_H
#define CLIBRARY_H
//定义函数指针
typedef int (*callback_fcn)(int);
void some_c_func(callback_fcn);
#endif
Go code:
package main/*
#cgo CFLAGS: -I .
#cgo LDFLAGS: -L . -lclibrary#include "clibrary.h"int callOnMeGo_cgo(int in); // 声明
*/
import "C"import ("fmt""unsafe"
)//export callOnMeGo
func callOnMeGo(in int) int {return in + 1
}func main() {fmt.Printf("Go.main(): calling C function with callback to us\n")//使用unsafe.Pointer转换C.some_c_func((C.callback_fcn)(unsafe.Pointer(C.callOnMeGo_cgo)))
}
中间函数:
package main/*#include <stdio.h>
int callOnMeGo(int);// The gateway function
int callOnMeGo_cgo(int in)
{printf("C.callOnMeGo_cgo(): called with arg = %d\n", in);//调用GO函数return callOnMeGo(in);
}
*/
import "C"
运行:
开发注意事项:
1. 在注释和import”C”之间不能有空行
2. 使用C.CString函数转换GoString为CString时要手动释放该字符串。
3. CGO不支持使用变参的函数,例如printf,如果要使用的话,可以写个包裹函数m'yprintf,使用传参的方式调用。
4. Go支持使用//export导出函数给C使用,但是有一点需要注意就是不能在export导出的同一个文件里定义c函数,不然会出现
multiple definition of "xxx"编译错误,如果函数非常tiny的话,还有一个方法是使用static inline 来声明该函数,如下:
package gocallbackimport ("fmt""sync"
)/*
extern void go_callback_int(int foo, int p1);// normally you will have to define function or variables
// in another separate C file to avoid the multiple definition
// errors, however, using "static inline" is a nice workaround
// for simple functions like this one.
static inline void CallMyFunction(int foo) {go_callback_int(foo, 5);
}
*/
import "C"
参考资料:
1. https://github.com/golang/go/wiki/cgo
Go语言中CGO的使用例子相关推荐
- c语言用while循环实现n,c语言while循环例子 C语言中while(n)是什么意思
含义:While 循环会在指定条件为真时循环 在C语言中,while 和do while的死循环例子 一般在运行循环语句的时候,会保证判断条件一直在做改变,所以在某个时刻导致条件为假而退出循环. 如: ...
- c语言中return语句例子,C语言 return 语句-嗨客网
C语言return语句教程 在 如果 return 语句使用在普通的 C语言return语句详解 语法 void fun(){ //do something return; } 说明 使用 retur ...
- c语言中dfs算法不定起点问题,dfs算法(dfs算法例子)
有哪位大侠知道请告知 首先选定图的类别(有向图.无向图),再选定图的存储结构,根据输入的顶点或者. 根据已有的邻接矩阵或邻接表用递归方法编写深度优先搜索遍历算法,并输出遍历结. 要求思路!谢谢! 深度 ...
- 关于C语言中的malloc和free函数的用法
一.malloc()和free()的基本概念以及基本用法: 1.函数原型及说明: void *malloc(long NumBytes):该函数分配了NumBytes个字节,并返回了指向这块内存的指针 ...
- c语言中的if语句_If ... C中的其他语句解释
c语言中的if语句 Conditional code flow is the ability to change the way a piece of code behaves based on ce ...
- C语言中的scanf()函数介绍
1.scanf函数:读取从键盘输入的数据 在C语言中,有多个函数可以从键盘获得用户输入: scanf():和 printf() 类似,scanf() 可以输入多种类型的数据 getchar().get ...
- c语言中 char怎样用,C语言中char*和char[]用法区别分析
C语言中char*和char[]用法区别分析 本文实例分析了C语言中char* 和 char []的区别.分享给大家供大家参考之用.具体分析如下: 一般来说,很多人会觉得这两个定义效果一样,其实差别很 ...
- C语言中static的作用及C语言中使用静态函数有何好处
转自:http://www.jb51.net/article/74830.htm 在C语言中,static的作用有三条:一是隐藏功能,二是保持持久性功能,三是默认初始化为0. 在C语言中,static ...
- linux strcpy 用法,由Linux中管道的buffer,浅谈C语言中char类型字符串拷贝使用strcpy()和=赋值符号的区别...
今天在写父子进程用两个单向管道通信时,出现了错误: Segmentation fault (core dumped) 打开core文件发现: 附上源码: 1 #include 2 #include 3 ...
最新文章
- 【智力题】国际象棋问题
- 少儿编程150讲轻松学Scratch(二)-制作过马路小游戏
- 设计师喜欢收集各种各样的笔刷来喽,不必倾家倾产就能像创造出令人惊叹的设计。
- python ansible模块_Python之——Ansible常用模块及API,pythonansibleapi
- perl socket初步
- OpenWHO课程 Introduction to COVID-19: methods for detection, prevention, response and control 小抄
- 8款超级好用的3D建模软件上下篇
- 【Python打卡2019】20190421之52周存钱挑战
- socket网络通信实现与优化
- hdu 4899 Hero meet devil
- Methyltetrazine-PEG8-DBCO,甲基四嗪--八聚乙二醇-二苯并环辛炔
- 用vue-pdf包实现pdf文件预览,支持分页
- Unity制作一套自定义选择题试卷
- c++ 编译DLL和使用DLL
- 文件服务器维修,中国直辖市服务器维修及数据恢复.docx
- S32K系列S32K144学习笔记——UART2
- ICPC Latin American Regional Contests 2019 K.Know your Aliens菜鸡版
- URL(获取指定网址里的图片)
- Artifact XXXwar exploded Artifact is being deployed, please wait...(已解决)
- AI 写文献回顾,好使吗?