Cgo | 使用libevent库实现一个定时器
使用libevent库作为例子
下载 & 编译 & 安装libevent
$ git clone https://github.com.cnpmjs.org/libevent/libevent.git
$ cd libevent && mkdir build && cd build
$ cmake ..
$ make
libevent实现的定时器
// main.cpp
#include "event.h"
struct event ev;
struct timeval tv;
void time_cb(evutil_socket_t fd, short event, void *argc)
{
printf("timer wakeup\n");
event_add(&ev, &tv); // reschedule timer
}
int main()
{
struct event_base *base = event_base_new();
tv.tv_sec = 2;
tv.tv_usec = 0;
evtimer_set(&ev, time_cb, NULL);
event_base_set(base, &ev);
event_add(&ev, &tv);
event_base_dispatch(base);
event_base_free(base);
}
go调用libevent实现定时器
把编译好的头文件和库文件放到go工程里
/go_libevent
├── libevent
├──├── include
├──├── lib
├── main.go
main.go
package main
/*
#cgo CFLAGS: -I ${SRCDIR}/libevent/include
#cgo LDFLAGS: -L ${SRCDIR}/libevent/lib -levent -levent_core -levent_extra -lcrypto -lssl -lpthread
#include "event.h"
#include "event2/event.h"
typedef void(*cb)(evutil_socket_t, short, void *);
struct event evg;
struct timeval tvg;
struct event* getEventPtr() {
return &evg;
}
struct timeval* getTvPtr() {
tvg.tv_sec = 1;
tvg.tv_usec = 0;
return &tvg;
}
void timer_cb(evutil_socket_t fd, short event , void* argc) {
struct timeval tv;
tv.tv_sec = 2;
tv.tv_usec = 0;
printf("timer wakeup\n");
struct event* ev = (struct event*)argc;
event_add(ev, &tv); // reschedule timer
}
void ev_set_timer(struct event* evt, cb c)
{
evtimer_set(evt, c, (void*)evt);
}
*/
import "C"
import (
"fmt"
"unsafe"
)
func main() {
fmt.Printf("asdfafad\n")
var pev *C.struct_event = C.getEventPtr()
var ptv *C.struct_timeval = C.getTvPtr()
var base *C.struct_event_base
base = C.event_base_new() //*C.struct_event_base
var pbase *C.struct_event_base = (*C.struct_event_base)(unsafe.Pointer(base))
C.ev_set_timer(pev, (C.cb)(unsafe.Pointer(C.timer_cb)))
C.event_base_set(pbase, pev)
C.event_add(pev, ptv)
C.event_base_dispatch(pbase)
C.event_base_free(pbase)
}
知识点总结
cogo调用libevent库的struct
调用libevent库的 struct event:
C.struct_event
函数指针
typedef void(*cb)(evutil_socket_t, short, void *);
调用cgo宏功能
libevent 中 有个宏函数 evtimer_set
#define evtimer_set(ev, cb, arg) event_set((ev), -1, 0, (cb), (arg))
cgo直接调用 C.evtimer_set
会报错
could not determine kind of name for C.evtimer_set
解决办法是封装一下
void ev_set_timer(struct event* ev, cb c)
{
evtimer_set(ev, c,ev1);
}
然后调用方式为:
C.ev_set_timer()
Go和C互相调用指针
参考链接:https://blog.csdn.net/weixin_34055787/article/details/88883037
参考链接:https://chai2010.cn/advanced-go-programming-book/ch2-cgo/ch2-07-memory.html
Go调用C Code时,Go传递给C Code的Go指针所指的Go Memory中不能包含任何指向Go Memory的Pointer。
C调用的Go函数不能返回指向Go分配的内存的指针。
--完--
- 原文作者: 留白
- 原文链接: https://zfunnily.github.io/2020/11/cgo%E4%BD%BF%E7%94%A8libevent%E5%BA%93%E5%AE%9E%E7%8E%B0%E4%B8%80%E4%B8%AA%E5%AE%9A%E6%97%B6%E5%99%A8/
- 更新时间:2024-04-16 01:01:05
- 本文声明:转载请标记原文作者及链接