feat(c/libuv/demo): Add libuv demo echo_server
refactor(c/libuv): Adjust comments and file names to accommodate merge
This commit is contained in:
109
_demo/libuv/echo_server.go
Normal file
109
_demo/libuv/echo_server.go
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/libuv"
|
||||||
|
"github.com/goplus/llgo/c/net"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
var DEFAULT_PORT c.Int = 8080
|
||||||
|
var DEFAULT_BACKLOG c.Int = 128
|
||||||
|
|
||||||
|
var loop *libuv.Loop
|
||||||
|
|
||||||
|
type WriteReq struct {
|
||||||
|
req libuv.Write
|
||||||
|
buf libuv.Buf
|
||||||
|
}
|
||||||
|
|
||||||
|
func FreeWriteReq(req *libuv.Write) {
|
||||||
|
wr := (*WriteReq)(c.Pointer(req))
|
||||||
|
c.Free(c.Pointer(wr.buf.Base))
|
||||||
|
c.Free(c.Pointer(wr))
|
||||||
|
}
|
||||||
|
|
||||||
|
func AllocBuffer(handle *libuv.Handle, suggestedSize uintptr, buf *libuv.Buf) {
|
||||||
|
buf.Base = (*c.Char)(c.Malloc(suggestedSize))
|
||||||
|
buf.Len = suggestedSize
|
||||||
|
}
|
||||||
|
|
||||||
|
func EchoWrite(req *libuv.Write, status c.Int) {
|
||||||
|
if status != 0 {
|
||||||
|
c.Fprintf(c.Stderr, c.Str("write error: %s\n"), libuv.Strerror(status))
|
||||||
|
}
|
||||||
|
defer FreeWriteReq(req)
|
||||||
|
}
|
||||||
|
|
||||||
|
func EchoRead(client *libuv.Stream, nread c.Long, buf *libuv.Buf) {
|
||||||
|
if nread > 0 {
|
||||||
|
req := (*WriteReq)(c.Malloc(unsafe.Sizeof(WriteReq{})))
|
||||||
|
if req == nil {
|
||||||
|
c.Fprintf(c.Stderr, c.Str("Failed to allocate memory for write request\n"))
|
||||||
|
defer c.Free(c.Pointer(buf.Base))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.buf = libuv.InitBuf(buf.Base, c.Uint(nread))
|
||||||
|
(*libuv.Write)(c.Pointer(req)).Write(client, []libuv.Buf{req.buf}, 1, EchoWrite)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if nread < 0 {
|
||||||
|
if (libuv.Errno)(nread) != libuv.EOF {
|
||||||
|
c.Fprintf(c.Stderr, c.Str("Read error: %s\n"), libuv.Strerror(c.Int(nread)))
|
||||||
|
}
|
||||||
|
(*libuv.Handle)(client).Close(nil)
|
||||||
|
}
|
||||||
|
if buf.Base != nil {
|
||||||
|
c.Free(c.Pointer(buf.Base))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func OnNewConnection(server *libuv.Stream, status c.Int) {
|
||||||
|
if status < 0 {
|
||||||
|
c.Fprintf(c.Stderr, c.Str("New connection error: %s\n"), libuv.Strerror(status))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
client := (*libuv.Tcp)(c.Malloc(unsafe.Sizeof(libuv.Tcp{})))
|
||||||
|
|
||||||
|
if client == nil {
|
||||||
|
c.Fprintf(c.Stderr, c.Str("Failed to allocate memory for client\n"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if libuv.InitTcp(loop, client) < 0 {
|
||||||
|
c.Fprintf(c.Stderr, c.Str("Failed to initialize client\n"))
|
||||||
|
c.Free(c.Pointer(client))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if server.Accept((*libuv.Stream)(client)) == 0 {
|
||||||
|
(*libuv.Stream)(client).StartRead(AllocBuffer, EchoRead)
|
||||||
|
} else {
|
||||||
|
(*libuv.Handle)(client).Close(nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Initialize the default event loop
|
||||||
|
loop = libuv.DefaultLoop()
|
||||||
|
|
||||||
|
// Initialize a TCP server
|
||||||
|
var server libuv.Tcp
|
||||||
|
libuv.InitTcp(loop, &server)
|
||||||
|
|
||||||
|
// Set up the address to bind the server to
|
||||||
|
var addr net.SockaddrIn
|
||||||
|
libuv.Ip4Addr(c.Str("0.0.0.0"), DEFAULT_PORT, &addr)
|
||||||
|
|
||||||
|
// Bind the server to the specified address and port
|
||||||
|
(&server).Bind((*net.SockAddr)(c.Pointer(&addr)), 0)
|
||||||
|
res := (*libuv.Stream)(&server).Listen(DEFAULT_BACKLOG, OnNewConnection)
|
||||||
|
if res != 0 {
|
||||||
|
c.Fprintf(c.Stderr, c.Str("Listen error: %s\n"), libuv.Strerror(res))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start listening for incoming connections
|
||||||
|
loop.Run(libuv.RUN_DEFAULT)
|
||||||
|
}
|
||||||
109
c/libuv/_demo/echo_server/echo_server.go
Normal file
109
c/libuv/_demo/echo_server/echo_server.go
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/libuv"
|
||||||
|
"github.com/goplus/llgo/c/net"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
var DEFAULT_PORT c.Int = 8080
|
||||||
|
var DEFAULT_BACKLOG c.Int = 128
|
||||||
|
|
||||||
|
var loop *libuv.Loop
|
||||||
|
|
||||||
|
type WriteReq struct {
|
||||||
|
req libuv.Write
|
||||||
|
buf libuv.Buf
|
||||||
|
}
|
||||||
|
|
||||||
|
func FreeWriteReq(req *libuv.Write) {
|
||||||
|
wr := (*WriteReq)(c.Pointer(req))
|
||||||
|
c.Free(c.Pointer(wr.buf.Base))
|
||||||
|
c.Free(c.Pointer(wr))
|
||||||
|
}
|
||||||
|
|
||||||
|
func AllocBuffer(handle *libuv.Handle, suggestedSize uintptr, buf *libuv.Buf) {
|
||||||
|
buf.Base = (*c.Char)(c.Malloc(suggestedSize))
|
||||||
|
buf.Len = suggestedSize
|
||||||
|
}
|
||||||
|
|
||||||
|
func EchoWrite(req *libuv.Write, status c.Int) {
|
||||||
|
if status != 0 {
|
||||||
|
c.Fprintf(c.Stderr, c.Str("write error: %s\n"), libuv.Strerror(status))
|
||||||
|
}
|
||||||
|
defer FreeWriteReq(req)
|
||||||
|
}
|
||||||
|
|
||||||
|
func EchoRead(client *libuv.Stream, nread c.Long, buf *libuv.Buf) {
|
||||||
|
if nread > 0 {
|
||||||
|
req := (*WriteReq)(c.Malloc(unsafe.Sizeof(WriteReq{})))
|
||||||
|
if req == nil {
|
||||||
|
c.Fprintf(c.Stderr, c.Str("Failed to allocate memory for write request\n"))
|
||||||
|
defer c.Free(c.Pointer(buf.Base))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.buf = libuv.InitBuf(buf.Base, c.Uint(nread))
|
||||||
|
(*libuv.Write)(c.Pointer(req)).Write(client, []libuv.Buf{req.buf}, 1, EchoWrite)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if nread < 0 {
|
||||||
|
if (libuv.Errno)(nread) != libuv.EOF {
|
||||||
|
c.Fprintf(c.Stderr, c.Str("Read error: %s\n"), libuv.Strerror(c.Int(nread)))
|
||||||
|
}
|
||||||
|
(*libuv.Handle)(client).Close(nil)
|
||||||
|
}
|
||||||
|
if buf.Base != nil {
|
||||||
|
c.Free(c.Pointer(buf.Base))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func OnNewConnection(server *libuv.Stream, status c.Int) {
|
||||||
|
if status < 0 {
|
||||||
|
c.Fprintf(c.Stderr, c.Str("New connection error: %s\n"), libuv.Strerror(status))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
client := (*libuv.Tcp)(c.Malloc(unsafe.Sizeof(libuv.Tcp{})))
|
||||||
|
|
||||||
|
if client == nil {
|
||||||
|
c.Fprintf(c.Stderr, c.Str("Failed to allocate memory for client\n"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if libuv.InitTcp(loop, client) < 0 {
|
||||||
|
c.Fprintf(c.Stderr, c.Str("Failed to initialize client\n"))
|
||||||
|
c.Free(c.Pointer(client))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if server.Accept((*libuv.Stream)(client)) == 0 {
|
||||||
|
(*libuv.Stream)(client).StartRead(AllocBuffer, EchoRead)
|
||||||
|
} else {
|
||||||
|
(*libuv.Handle)(client).Close(nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Initialize the default event loop
|
||||||
|
loop = libuv.DefaultLoop()
|
||||||
|
|
||||||
|
// Initialize a TCP server
|
||||||
|
var server libuv.Tcp
|
||||||
|
libuv.InitTcp(loop, &server)
|
||||||
|
|
||||||
|
// Set up the address to bind the server to
|
||||||
|
var addr net.SockaddrIn
|
||||||
|
libuv.Ip4Addr(c.Str("0.0.0.0"), DEFAULT_PORT, &addr)
|
||||||
|
|
||||||
|
// Bind the server to the specified address and port
|
||||||
|
(&server).Bind((*net.SockAddr)(c.Pointer(&addr)), 0)
|
||||||
|
res := (*libuv.Stream)(&server).Listen(DEFAULT_BACKLOG, OnNewConnection)
|
||||||
|
if res != 0 {
|
||||||
|
c.Fprintf(c.Stderr, c.Str("Listen error: %s\n"), libuv.Strerror(res))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start listening for incoming connections
|
||||||
|
loop.Run(libuv.RUN_DEFAULT)
|
||||||
|
}
|
||||||
@@ -93,93 +93,6 @@ const (
|
|||||||
ERRNO_MAX
|
ERRNO_MAX
|
||||||
)
|
)
|
||||||
|
|
||||||
//var errnoDescriptions = map[Errno]string{
|
|
||||||
// E2BIG: "argument list too long",
|
|
||||||
// EACCES: "permission denied",
|
|
||||||
// EADDRINUSE: "address already in use",
|
|
||||||
// EADDRNOTAVAIL: "address not available",
|
|
||||||
// EAFNOSUPPORT: "address family not supported",
|
|
||||||
// EAGAIN: "resource temporarily unavailable",
|
|
||||||
// EAI_ADDRFAMILY: "address family not supported",
|
|
||||||
// EAI_AGAIN: "temporary failure",
|
|
||||||
// EAI_BADFLAGS: "bad ai_flags value",
|
|
||||||
// EAI_BADHINTS: "invalid value for hints",
|
|
||||||
// EAI_CANCELED: "request canceled",
|
|
||||||
// EAI_FAIL: "permanent failure",
|
|
||||||
// EAI_FAMILY: "ai_family not supported",
|
|
||||||
// EAI_MEMORY: "out of memory",
|
|
||||||
// EAI_NODATA: "no address",
|
|
||||||
// EAI_NONAME: "unknown node or service",
|
|
||||||
// EAI_OVERFLOW: "argument buffer overflow",
|
|
||||||
// EAI_PROTOCOL: "resolved protocol is unknown",
|
|
||||||
// EAI_SERVICE: "service not available for socket type",
|
|
||||||
// EAI_SOCKTYPE: "socket type not supported",
|
|
||||||
// EALREADY: "connection already in progress",
|
|
||||||
// EBADF: "bad file descriptor",
|
|
||||||
// EBUSY: "resource busy or locked",
|
|
||||||
// ECANCELED: "operation canceled",
|
|
||||||
// ECHARSET: "invalid Unicode character",
|
|
||||||
// ECONNABORTED: "software caused connection abort",
|
|
||||||
// ECONNREFUSED: "connection refused",
|
|
||||||
// ECONNRESET: "connection reset by peer",
|
|
||||||
// EDESTADDRREQ: "destination address required",
|
|
||||||
// EEXIST: "file already exists",
|
|
||||||
// EFAULT: "bad address in system call argument",
|
|
||||||
// EFBIG: "file too large",
|
|
||||||
// EHOSTUNREACH: "host is unreachable",
|
|
||||||
// EINTR: "interrupted system call",
|
|
||||||
// EINVAL: "invalid argument",
|
|
||||||
// EIO: "i/o error",
|
|
||||||
// EISCONN: "socket is already connected",
|
|
||||||
// EISDIR: "illegal operation on a directory",
|
|
||||||
// ELOOP: "too many symbolic links encountered",
|
|
||||||
// EMFILE: "too many open files",
|
|
||||||
// EMSGSIZE: "message too long",
|
|
||||||
// ENAMETOOLONG: "name too long",
|
|
||||||
// ENETDOWN: "network is down",
|
|
||||||
// ENETUNREACH: "network is unreachable",
|
|
||||||
// ENFILE: "file table overflow",
|
|
||||||
// ENOBUFS: "no buffer space available",
|
|
||||||
// ENODEV: "no such device",
|
|
||||||
// ENOENT: "no such file or directory",
|
|
||||||
// ENOMEM: "not enough memory",
|
|
||||||
// ENONET: "machine is not on the network",
|
|
||||||
// ENOPROTOOPT: "protocol not available",
|
|
||||||
// ENOSPC: "no space left on device",
|
|
||||||
// ENOSYS: "function not implemented",
|
|
||||||
// ENOTCONN: "socket is not connected",
|
|
||||||
// ENOTDIR: "not a directory",
|
|
||||||
// ENOTEMPTY: "directory not empty",
|
|
||||||
// ENOTSOCK: "socket operation on non-socket",
|
|
||||||
// ENOTSUP: "operation not supported on socket",
|
|
||||||
// EOVERFLOW: "value too large for defined data type",
|
|
||||||
// EPERM: "operation not permitted",
|
|
||||||
// EPIPE: "broken pipe",
|
|
||||||
// EPROTO: "protocol error",
|
|
||||||
// EPROTONOSUPPORT: "protocol not supported",
|
|
||||||
// EPROTOTYPE: "protocol wrong type for socket",
|
|
||||||
// ERANGE: "result too large",
|
|
||||||
// EROFS: "read-only file system",
|
|
||||||
// ESHUTDOWN: "cannot send after transport endpoint shutdown",
|
|
||||||
// ESPIPE: "invalid seek",
|
|
||||||
// ESRCH: "no such process",
|
|
||||||
// ETIMEDOUT: "connection timed out",
|
|
||||||
// ETXTBSY: "text file is busy",
|
|
||||||
// EXDEV: "cross-device link not permitted",
|
|
||||||
// UNKNOWN: "unknown error",
|
|
||||||
// EOF: "end of file",
|
|
||||||
// ENXIO: "no such device or address",
|
|
||||||
// EMLINK: "too many links",
|
|
||||||
// EHOSTDOWN: "host is down",
|
|
||||||
// EREMOTEIO: "remote I/O error",
|
|
||||||
// ENOTTY: "inappropriate ioctl for device",
|
|
||||||
// EFTYPE: "inappropriate file type or format",
|
|
||||||
// EILSEQ: "illegal byte sequence",
|
|
||||||
// ESOCKTNOSUPPORT: "socket type not supported",
|
|
||||||
// ENODATA: "no data available",
|
|
||||||
// EUNATCH: "protocol driver not attached",
|
|
||||||
//}
|
|
||||||
|
|
||||||
type Errno c.Int
|
type Errno c.Int
|
||||||
|
|
||||||
//go:linkname TranslateSysError C.uv_translate_sys_error
|
//go:linkname TranslateSysError C.uv_translate_sys_error
|
||||||
|
|||||||
@@ -17,12 +17,6 @@ const (
|
|||||||
METRICS_IDLE_TIME
|
METRICS_IDLE_TIME
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
RUN_DEFAULT RunMode = iota
|
|
||||||
RUN_ONCE
|
|
||||||
RUN_NOWAIT
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
UV_LEAVE_GROUP Membership = iota
|
UV_LEAVE_GROUP Membership = iota
|
||||||
UV_JOIN_GROUP
|
UV_JOIN_GROUP
|
||||||
@@ -68,8 +62,6 @@ const (
|
|||||||
|
|
||||||
type LoopOption c.Int
|
type LoopOption c.Int
|
||||||
|
|
||||||
type RunMode c.Int
|
|
||||||
|
|
||||||
type Membership c.Int
|
type Membership c.Int
|
||||||
|
|
||||||
type HandleType c.Int
|
type HandleType c.Int
|
||||||
@@ -85,9 +77,6 @@ type OsFd c.Int
|
|||||||
// ----------------------------------------------
|
// ----------------------------------------------
|
||||||
|
|
||||||
/* Handle types. */
|
/* Handle types. */
|
||||||
type Loop struct {
|
|
||||||
Unused [0]byte
|
|
||||||
}
|
|
||||||
|
|
||||||
type Handle struct {
|
type Handle struct {
|
||||||
Unused [0]byte
|
Unused [0]byte
|
||||||
@@ -101,14 +90,6 @@ type Stream struct {
|
|||||||
Unused [0]byte
|
Unused [0]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type Tcp struct {
|
|
||||||
Unused [0]byte
|
|
||||||
}
|
|
||||||
|
|
||||||
type Udp struct {
|
|
||||||
Unused [0]byte
|
|
||||||
}
|
|
||||||
|
|
||||||
type Pipe struct {
|
type Pipe struct {
|
||||||
Unused [0]byte
|
Unused [0]byte
|
||||||
}
|
}
|
||||||
@@ -121,10 +102,6 @@ type Poll struct {
|
|||||||
Unused [0]byte
|
Unused [0]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type Timer struct {
|
|
||||||
Unused [0]byte
|
|
||||||
}
|
|
||||||
|
|
||||||
type Prepare struct {
|
type Prepare struct {
|
||||||
Unused [0]byte
|
Unused [0]byte
|
||||||
}
|
}
|
||||||
@@ -183,17 +160,6 @@ type Connect struct {
|
|||||||
Unused [0]byte
|
Unused [0]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type UdpSend struct {
|
|
||||||
Unused [0]byte
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------
|
|
||||||
|
|
||||||
type Buf struct {
|
|
||||||
Base *c.Char
|
|
||||||
Len uintptr
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------
|
// ----------------------------------------------
|
||||||
|
|
||||||
/* Function type */
|
/* Function type */
|
||||||
@@ -257,7 +223,7 @@ func (shutdown *Shutdown) Shutdown(stream *Stream, shutdownCb ShutdownCb) c.Int
|
|||||||
|
|
||||||
// ----------------------------------------------
|
// ----------------------------------------------
|
||||||
|
|
||||||
/* HandleT related function and method */
|
/* Handle related function and method */
|
||||||
|
|
||||||
// llgo:link (*Handle).Ref C.uv_ref
|
// llgo:link (*Handle).Ref C.uv_ref
|
||||||
func (handle *Handle) Ref() {}
|
func (handle *Handle) Ref() {}
|
||||||
@@ -317,9 +283,6 @@ func (handle *Handle) Fileno(fd *OsFd) c.Int {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:linkname InitBuf C.uv_buf_init
|
|
||||||
func InitBuf(base *c.Char, len c.Uint) Buf
|
|
||||||
|
|
||||||
//go:linkname UvPipe C.uv_pipe
|
//go:linkname UvPipe C.uv_pipe
|
||||||
func UvPipe(fds [2]Uv_File, readFlags c.Int, writeFlags c.Int) c.Int {
|
func UvPipe(fds [2]Uv_File, readFlags c.Int, writeFlags c.Int) c.Int {
|
||||||
return 0
|
return 0
|
||||||
|
|||||||
@@ -62,6 +62,24 @@ type UdpFlags c.Int
|
|||||||
|
|
||||||
// ----------------------------------------------
|
// ----------------------------------------------
|
||||||
|
|
||||||
|
/* Handle types. */
|
||||||
|
|
||||||
|
type Tcp struct {
|
||||||
|
Unused [0]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type Udp struct {
|
||||||
|
Unused [0]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Request types. */
|
||||||
|
|
||||||
|
type UdpSend struct {
|
||||||
|
Unused [0]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
|
||||||
/* Function type */
|
/* Function type */
|
||||||
|
|
||||||
// llgo:type C
|
// llgo:type C
|
||||||
@@ -78,7 +96,7 @@ type UdpRecvCb func(handle *Udp, nread c.Long, buf *Buf, addr *net.SockAddr, fla
|
|||||||
|
|
||||||
// ----------------------------------------------
|
// ----------------------------------------------
|
||||||
|
|
||||||
/* TcpT related function and method */
|
/* Tcp related function and method */
|
||||||
|
|
||||||
//go:linkname InitTcp C.uv_tcp_init
|
//go:linkname InitTcp C.uv_tcp_init
|
||||||
func InitTcp(loop *Loop, tcp *Tcp) c.Int
|
func InitTcp(loop *Loop, tcp *Tcp) c.Int
|
||||||
@@ -131,7 +149,7 @@ func TcpConnect(req *Connect, tcp *Tcp, addr *net.SockAddr, connectCb ConnectCb)
|
|||||||
|
|
||||||
// ----------------------------------------------
|
// ----------------------------------------------
|
||||||
|
|
||||||
/* UdpT related function and method */
|
/* Udp related function and method */
|
||||||
|
|
||||||
//go:linkname InitUdp C.uv_udp_init
|
//go:linkname InitUdp C.uv_udp_init
|
||||||
func InitUdp(loop *Loop, udp *Udp) c.Int
|
func InitUdp(loop *Loop, udp *Udp) c.Int
|
||||||
|
|||||||
@@ -5,10 +5,22 @@ import (
|
|||||||
_ "unsafe"
|
_ "unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
|
||||||
|
/* Handle types. */
|
||||||
|
|
||||||
|
type Timer struct {
|
||||||
|
Unused [0]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
|
||||||
// llgo:type C
|
// llgo:type C
|
||||||
type TimerCb func(timer *Timer)
|
type TimerCb func(timer *Timer)
|
||||||
|
|
||||||
/* TimerT related function and method */
|
// ----------------------------------------------
|
||||||
|
|
||||||
|
/* Timer related function and method */
|
||||||
|
|
||||||
//go:linkname InitTimer C.uv_timer_init
|
//go:linkname InitTimer C.uv_timer_init
|
||||||
func InitTimer(loop *Loop, timer *Timer) c.Int
|
func InitTimer(loop *Loop, timer *Timer) c.Int
|
||||||
|
|||||||
Reference in New Issue
Block a user