使用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分配的内存的指针。

--完--