ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
[TOC] ## 使用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 } void timerr() { 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分配的内存的指针。