diff --git a/_demo/libuv/echo_server.go b/_demo/libuv/echo_server.go deleted file mode 100644 index 81d18148..00000000 --- a/_demo/libuv/echo_server.go +++ /dev/null @@ -1,109 +0,0 @@ -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) -} diff --git a/c/libuv/README.md b/c/libuv/README.md new file mode 100644 index 00000000..30f2ed5b --- /dev/null +++ b/c/libuv/README.md @@ -0,0 +1,44 @@ +LLGo wrapper of libuv +===== + +## How to install + +### on macOS (Homebrew) + +```sh +brew install libuv +``` + +### on Linux (Debian/Ubuntu) + +```sh +apt-get install -y libuv1-dev +``` + +### on Linux (CentOS/RHEL) + +```sh +yum install -y libuv-devel +``` + +### on Linux (Arch Linux) + +```sh +pacman -S libuv +``` + +## Demos + +The `_demo` directory contains our demos (it start with `_` to prevent the `go` command from compiling it): + +* [async_fs](_demo/async_fs/async_fs.go): a simple async file read demo +* [echo_server](_demo/echo_server/echo_server.go): a basic async tcp echo server + +### How to run demos + +To run the demos in directory `_demo`: + +```sh +cd # eg. cd _demo/sqlitedemo +llgo run . +``` diff --git a/c/libuv/_demo/async_fs/async_fs.go b/c/libuv/_demo/async_fs/async_fs.go new file mode 100644 index 00000000..6a549441 --- /dev/null +++ b/c/libuv/_demo/async_fs/async_fs.go @@ -0,0 +1,97 @@ +package main + +import ( + "unsafe" + + "github.com/goplus/llgo/c" + "github.com/goplus/llgo/c/libuv" + "github.com/goplus/llgo/c/os" +) + +const BUFFER_SIZE = 1024 + +var ( + loop *libuv.Loop + openReq libuv.Fs + readReq libuv.Fs + closeReq libuv.Fs + + buffer [BUFFER_SIZE]c.Char + iov libuv.Buf +) + +func main() { + // Print the libuv version + c.Printf(c.Str("libuv version: %d\n"), libuv.Version()) + + // Initialize the loop + loop = libuv.DefaultLoop() + + // Open the file + libuv.FsOpen(loop, &openReq, c.Str("example.txt"), os.O_RDONLY, 0, onOpen) + + // Run the loop + libuv.Run(loop, libuv.RUN_DEFAULT) + + // Cleanup + defer cleanup() +} + +func onOpen(req *libuv.Fs) { + // Check for errors + if libuv.FsGetResult(req) < 0 { + c.Fprintf(c.Stderr, c.Str("Error opening file: %s\n"), libuv.Strerror(libuv.LoopClose(loop))) + libuv.LoopClose(loop) + return + } + // Init buffer + iov = libuv.InitBuf((*c.Char)(unsafe.Pointer(&buffer[0])), c.Uint(unsafe.Sizeof(buffer))) + // Read the file + readRes := libuv.FsRead(loop, &readReq, libuv.UvFile(libuv.FsGetResult(req)), &iov, 1, -1, onRead) + if readRes != 0 { + c.Printf(c.Str("Error in FsRead: %s (code: %d)\n"), libuv.Strerror(c.Int(readRes)), readRes) + libuv.LoopClose(loop) + return + } +} + +func onRead(req *libuv.Fs) { + // Check for errors + if libuv.FsGetResult(req) < 0 { + c.Fprintf(c.Stderr, c.Str("Read error: %s\n"), libuv.Strerror(libuv.FsGetResult(req))) + libuv.LoopClose(loop) + } else if libuv.FsGetResult(req) == 0 { + c.Printf(c.Str("EOF\n")) + // Close the file + closeRes := libuv.FsClose(loop, &closeReq, libuv.UvFile(libuv.FsGetResult(&openReq)), onClose) + if closeRes != 0 { + // Print the content + c.Printf(c.Str("Error in FsClose: %s (code: %d)\n"), libuv.Strerror(c.Int(closeRes)), closeRes) + libuv.LoopClose(loop) + return + } + } else { + c.Printf(c.Str("Read %d bytes\n"), libuv.FsGetResult(req)) + c.Printf(c.Str("Read content: %.*s\n"), libuv.FsGetResult(req), (*c.Char)(unsafe.Pointer(&buffer[0]))) + libuv.LoopClose(loop) + } +} + +func onClose(req *libuv.Fs) { + // Check for errors + if libuv.FsGetResult(req) < 0 { + c.Fprintf(c.Stderr, c.Str("Error closing file: %s\n"), libuv.Strerror(libuv.FsGetResult(req))) + } else { + c.Printf(c.Str("\nFile closed successfully.\n")) + } + libuv.LoopClose(loop) +} + +func cleanup() { + // Cleanup the requests + libuv.FsReqCleanup(&openReq) + libuv.FsReqCleanup(&readReq) + libuv.FsReqCleanup(&closeReq) + // Close the loop + libuv.LoopClose(loop) +} diff --git a/c/libuv/_demo/async_fs/example.txt b/c/libuv/_demo/async_fs/example.txt new file mode 100755 index 00000000..190a1803 --- /dev/null +++ b/c/libuv/_demo/async_fs/example.txt @@ -0,0 +1 @@ +123 diff --git a/c/libuv/_demo/echo_server/echo_server.go b/c/libuv/_demo/echo_server/echo_server.go index 81d18148..fdb04b5b 100644 --- a/c/libuv/_demo/echo_server/echo_server.go +++ b/c/libuv/_demo/echo_server/echo_server.go @@ -1,10 +1,11 @@ package main import ( + "unsafe" + "github.com/goplus/llgo/c" "github.com/goplus/llgo/c/libuv" "github.com/goplus/llgo/c/net" - "unsafe" ) var DEFAULT_PORT c.Int = 8080 @@ -13,75 +14,8 @@ 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) - } + Req libuv.Write + Buf libuv.Buf } func main() { @@ -95,6 +29,7 @@ func main() { // Set up the address to bind the server to var addr net.SockaddrIn libuv.Ip4Addr(c.Str("0.0.0.0"), DEFAULT_PORT, &addr) + c.Printf(c.Str("Listening on %s:%d\n"), c.Str("0.0.0.0"), DEFAULT_PORT) // Bind the server to the specified address and port (&server).Bind((*net.SockAddr)(c.Pointer(&addr)), 0) @@ -105,5 +40,81 @@ func main() { } // Start listening for incoming connections - loop.Run(libuv.RUN_DEFAULT) + libuv.Run(loop, libuv.RUN_DEFAULT) +} + +func FreeWriteReq(req *libuv.Write) { + wr := (*WriteReq)(c.Pointer(req)) + // Free the buffer base and the WriteReq itself. + c.Free(c.Pointer(wr.Buf.Base)) + c.Free(c.Pointer(wr)) +} + +func AllocBuffer(handle *libuv.Handle, suggestedSize uintptr, buf *libuv.Buf) { + // Allocate memory for the buffer based on the suggested size. + 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)) + } + 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")) + c.Free(c.Pointer(buf.Base)) + return + } + // Initialize the buffer with the data read. + req.Buf = libuv.InitBuf(buf.Base, c.Uint(nread)) + // Write the data back to the client. + (&req.Req).Write(client, &req.Buf, 1, EchoWrite) + return + } + if nread < 0 { + // Handle read errors and EOF. + if (libuv.Errno)(nread) != libuv.EOF { + c.Fprintf(c.Stderr, c.Str("Read error: %s\n"), libuv.Strerror(c.Int(nread))) + } + (*libuv.Handle)(c.Pointer(client)).Close(nil) + } + // Free the buffer if it's no longer needed. + 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 + } + + // Allocate memory for a new client. + 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 + } + + // Initialize the client TCP handle. + if libuv.InitTcp(loop, client) < 0 { + c.Fprintf(c.Stderr, c.Str("Failed to initialize client\n")) + c.Free(c.Pointer(client)) + return + } + + // Accept the new connection and start reading data. + if server.Accept((*libuv.Stream)(client)) == 0 { + (*libuv.Stream)(client).StartRead(AllocBuffer, EchoRead) + } else { + (*libuv.Handle)(c.Pointer(client)).Close(nil) + } } diff --git a/c/libuv/_demo/libuv/fs.go b/c/libuv/_demo/libuv/fs.go deleted file mode 100644 index 7d50f2e9..00000000 --- a/c/libuv/_demo/libuv/fs.go +++ /dev/null @@ -1,70 +0,0 @@ -package main - -import ( - "github.com/goplus/llgo/c" - "github.com/goplus/llgo/c/libuv" - "github.com/goplus/llgo/c/os" - "golang.org/x/tools/container/intsets" - "unsafe" -) - -const bufferSize = 1024 - -var buffer []c.Char -var iov libuv.Buf - -var loop *libuv.Loop -var readReq *libuv.Fs -var closeReq *libuv.Fs -var openReq *libuv.Fs - -func initBuffer() { - buffer = make([]c.Char, bufferSize) -} - -func main() { - loop = libuv.DefaultLoop() - initBuffer() - - file := libuv.NewFile(loop, openReq) - - path := c.Str("example.txt") - - file.Open(path, os.O_RDONLY, 0, onOpen) - - loop.Run(libuv.RUN_DEFAULT) - - libuv.FsReqCleanup(openReq) - loop.Close() - c.Free(unsafe.Pointer(loop)) -} - -func onOpen(req *libuv.Fs) { - if req.GetResult() < 0 { - c.Fprintf(c.Stderr, c.Str("Error opening file: %s\n"), libuv.Strerror(req.GetResult())) - } else { - iov = libuv.InitBuf(unsafe.SliceData(buffer), c.Uint(unsafe.Sizeof(buffer))) - libuv.FsRead(loop, readReq, req.GetResult(), []libuv.Buf{iov}, 1, -1, onRead) - } - libuv.FsReqCleanup(req) -} - -func onRead(req *libuv.Fs) { - if req.GetResult() < 0 { - c.Fprintf(c.Stderr, c.Str("Read error: %s\n"), libuv.Strerror(req.GetResult())) - } else if req.GetResult() == 0 { - libuv.FsClose(loop, closeReq, req.GetResult(), onClose) - } else { - if req.GetResult() > intsets.MaxInt { - c.Fprintf(c.Stderr, c.Str("Too big file.\n")) - } - c.Printf(c.Str("%.*s"), c.Int(req.GetResult()), buffer) - libuv.FsRead(loop, req, req.GetResult(), []libuv.Buf{iov}, 1, -1, onRead) - } - libuv.FsReqCleanup(req) -} - -func onClose(req *libuv.Fs) { - c.Printf(c.Str("\nFile closed.\n")) - libuv.FsReqCleanup(req) -} diff --git a/c/libuv/fs.go b/c/libuv/fs.go index 555b5b0f..0de0a458 100644 --- a/c/libuv/fs.go +++ b/c/libuv/fs.go @@ -57,9 +57,11 @@ const ( DirentBlock ) -type FsType int +type FsType c.Int -type DirentType int +type DirentType c.Int + +type UvFile c.Int // ---------------------------------------------- @@ -108,35 +110,23 @@ type FsPollCb func(handle *FsPoll, status c.Int, events c.Int) /* Fs related function and method */ -// llgo:link (*Fs).GetType C.uv_fs_get_type -func (f *Fs) GetType() *FsType { - return nil -} +//go:linkname FsGetType C.uv_fs_get_type +func FsGetType(req *Fs) *FsType -// llgo:link (*Fs).GetPath C.uv_fs_get_path -func (f *Fs) GetPath() *c.Char { - return nil -} +//go:linkname FsGetPath C.uv_fs_get_path +func FsGetPath(req *Fs) *c.Char -// llgo:link (*Fs).GetResult C.uv_fs_get_result -func (f *Fs) GetResult() c.Int { - return 0 -} +//go:linkname FsGetResult C.uv_fs_get_result +func FsGetResult(req *Fs) c.Int -// llgo:link (*Fs).GetPtr C.uv_fs_get_ptr -func (f *Fs) GetPtr() c.Pointer { - return nil -} +//go:linkname FsGetPtr C.uv_fs_get_ptr +func FsGetPtr(req *Fs) c.Pointer -// llgo:link (*Fs).GetSystemError C.uv_fs_get_system_error -func (f *Fs) GetSystemError() c.Int { - return 0 -} +//go:linkname FsGetSystemError C.uv_fs_get_system_error +func FsGetSystemError(req *Fs) c.Int -// llgo:link (*Fs).GetStatBuf C.uv_fs_get_statbuf -func (f *Fs) GetStatBuf() *Stat { - return nil -} +//go:linkname FsGetStatBuf C.uv_fs_get_statbuf +func FsGetStatBuf(req *Fs) *Stat //go:linkname FsReqCleanup C.uv_fs_req_cleanup func FsReqCleanup(req *Fs) @@ -148,13 +138,13 @@ func DefaultLoop() *Loop func FsOpen(loop *Loop, req *Fs, path *c.Char, flags c.Int, mode c.Int, cb FsCb) c.Int //go:linkname FsClose C.uv_fs_close -func FsClose(loop *Loop, req *Fs, file c.Int, cb FsCb) c.Int +func FsClose(loop *Loop, req *Fs, file UvFile, cb FsCb) c.Int //go:linkname FsRead C.uv_fs_read -func FsRead(loop *Loop, req *Fs, file c.Int, bufs []Buf, nbufs c.Uint, offset c.Int, cb FsCb) c.Int +func FsRead(loop *Loop, req *Fs, file UvFile, bufs *Buf, nbufs c.Uint, offset c.LongLong, cb FsCb) c.Int //go:linkname FsWrite C.uv_fs_write -func FsWrite(loop *Loop, req *Fs, file c.Int, bufs []Buf, nbufs c.Uint, offset c.Int, cb FsCb) c.Int +func FsWrite(loop *Loop, req *Fs, file UvFile, bufs *Buf, nbufs c.Uint, offset c.LongLong, cb FsCb) c.Int //go:linkname FsUnlink C.uv_fs_unlink func FsUnlink(loop *Loop, req *Fs, path *c.Char, cb FsCb) c.Int @@ -175,22 +165,22 @@ func FsRmdir(loop *Loop, req *Fs, path *c.Char, cb FsCb) c.Int func FsStat(loop *Loop, req *Fs, path *c.Char, cb FsCb) c.Int //go:linkname FsFstat C.uv_fs_fstat -func FsFstat(loop *Loop, req *Fs, file c.Int, cb FsCb) c.Int +func FsFstat(loop *Loop, req *Fs, file UvFile, cb FsCb) c.Int //go:linkname FsRename C.uv_fs_rename func FsRename(loop *Loop, req *Fs, path *c.Char, newPath *c.Char, cb FsCb) c.Int //go:linkname FsFsync C.uv_fs_fsync -func FsFsync(loop *Loop, req *Fs, file c.Int, cb FsCb) c.Int +func FsFsync(loop *Loop, req *Fs, file UvFile, cb FsCb) c.Int //go:linkname FsFdatasync C.uv_fs_fdatasync -func FsFdatasync(loop *Loop, req *Fs, file c.Int, cb FsCb) c.Int +func FsFdatasync(loop *Loop, req *Fs, file UvFile, cb FsCb) c.Int //go:linkname FsFtruncate C.uv_fs_ftruncate -func FsFtruncate(loop *Loop, req *Fs, file c.Int, offset c.Int, cb FsCb) c.Int +func FsFtruncate(loop *Loop, req *Fs, file UvFile, offset c.LongLong, cb FsCb) c.Int //go:linkname FsSendfile C.uv_fs_sendfile -func FsSendfile(loop *Loop, req *Fs, outFd c.Int, inFd c.Int, inOffset c.Int, length c.Int, cb FsCb) c.Int +func FsSendfile(loop *Loop, req *Fs, outFd c.Int, inFd c.Int, inOffset c.LongLong, length c.Int, cb FsCb) c.Int //go:linkname FsAccess C.uv_fs_access func FsAccess(loop *Loop, req *Fs, path *c.Char, flags c.Int, cb FsCb) c.Int @@ -199,13 +189,13 @@ func FsAccess(loop *Loop, req *Fs, path *c.Char, flags c.Int, cb FsCb) c.Int func FsChmod(loop *Loop, req *Fs, path *c.Char, mode c.Int, cb FsCb) c.Int //go:linkname FsFchmod C.uv_fs_fchmod -func FsFchmod(loop *Loop, req *Fs, file c.Int, mode c.Int, cb FsCb) c.Int +func FsFchmod(loop *Loop, req *Fs, file UvFile, mode c.Int, cb FsCb) c.Int //go:linkname FsUtime C.uv_fs_utime func FsUtime(loop *Loop, req *Fs, path *c.Char, atime c.Int, mtime c.Int, cb FsCb) c.Int //go:linkname FsFutime C.uv_fs_futime -func FsFutime(loop *Loop, req *Fs, file c.Int, atime c.Int, mtime c.Int, cb FsCb) c.Int +func FsFutime(loop *Loop, req *Fs, file UvFile, atime c.Int, mtime c.Int, cb FsCb) c.Int //go:linkname FsLutime C.uv_fs_lutime func FsLutime(loop *Loop, req *Fs, path *c.Char, atime c.Int, mtime c.Int, cb FsCb) c.Int @@ -247,7 +237,7 @@ func FsStatfs(loop *Loop, req *Fs, path *c.Char, cb FsCb) c.Int func FsChown(loop *Loop, req *Fs, path *c.Char, uid c.Int, gid c.Int, cb FsCb) c.Int //go:linkname FsFchown C.uv_fs_fchown -func FsFchown(loop *Loop, req *Fs, file c.Int, uid c.Int, gid c.Int, cb FsCb) c.Int +func FsFchown(loop *Loop, req *Fs, file UvFile, uid c.Int, gid c.Int, cb FsCb) c.Int //go:linkname FsLchown C.uv_fs_lchown func FsLchown(loop *Loop, req *Fs, path *c.Char, uid c.Int, gid c.Int, cb FsCb) c.Int @@ -284,247 +274,3 @@ func FsPollClose(handle *FsPoll) c.Int //go:linkname FsPollGetPath C.uv_fs_poll_getpath func FsPollGetPath(handle *FsPoll) *c.Char - -//TODO: Implemnt uv_poll_init_socket - -// Cleanup cleans up the file system request. -func (f *File) Cleanup() { - FsReqCleanup(f.Req) -} - -func NewFile(loop *Loop, req *Fs) *File { - return &File{ - Loop: loop, - Req: req, - } -} - -// Open opens a file specified by the path with given flags and mode, and returns a file descriptor. -func (f *File) Open(path *c.Char, flags int, mode int, cb FsCb) int { - return FsOpen(f.Loop, f.Req, path, flags, mode, cb) -} - -// Close closes a file descriptor. -func (f *File) Close(file int, cb FsCb) int { - return FsClose(f.Loop, f.Req, file, cb) -} - -// Read reads data from a file descriptor into a buffer at a specified offset. -func (f *File) Read(file c.Int, bufs []Buf, nbufs c.Uint, offset c.Int, cb FsCb) int { - return FsRead(f.Loop, f.Req, file, bufs, nbufs, offset, cb) -} - -// Write writes data to a file descriptor from a buffer at a specified offset. -func (f *File) Write(file c.Int, bufs []Buf, nbufs c.Uint, offset c.Int, cb FsCb) int { - return FsWrite(f.Loop, f.Req, file, bufs, nbufs, offset, cb) -} - -// Unlink deletes a file specified by the path. -func (f *File) Unlink(path *c.Char, cb FsCb) int { - return FsUnlink(f.Loop, f.Req, path, cb) -} - -// Mkdir creates a new directory at the specified path with a specified mode. -func (f *File) Mkdir(path *c.Char, mode int, cb FsCb) int { - return FsMkdir(f.Loop, f.Req, path, mode, cb) -} - -// Mkdtemp creates a temporary directory with a template path. -func (f *File) Mkdtemp(tpl *c.Char, cb FsCb) int { - return FsMkdtemp(f.Loop, f.Req, tpl, cb) -} - -// MkStemp creates a temporary file from a template path. -func (f *File) MkStemp(tpl *c.Char, cb FsCb) int { - return FsMkStemp(f.Loop, f.Req, tpl, cb) -} - -// Rmdir removes a directory specified by the path. -func (f *File) Rmdir(path *c.Char, cb FsCb) int { - return FsRmdir(f.Loop, f.Req, path, cb) -} - -// Stat retrieves status information about the file specified by the path. -func (f *File) Stat(path *c.Char, cb FsCb) int { - return FsStat(f.Loop, f.Req, path, cb) -} - -// Fstat retrieves status information about a file descriptor. -func (f *File) Fstat(file int, cb FsCb) int { - return FsFstat(f.Loop, f.Req, file, cb) -} - -// Rename renames a file from the old path to the new path. -func (f *File) Rename(path *c.Char, newPath *c.Char, cb FsCb) int { - return FsRename(f.Loop, f.Req, path, newPath, cb) -} - -// Fsync synchronizes a file descriptor's state with storage device. -func (f *File) Fsync(file int, cb FsCb) int { - return FsFsync(f.Loop, f.Req, file, cb) -} - -// Fdatasync synchronizes a file descriptor's data with storage device. -func (f *File) Fdatasync(file int, cb FsCb) int { - return FsFdatasync(f.Loop, f.Req, file, cb) -} - -// Ftruncate truncates a file to a specified length. -func (f *File) Ftruncate(file int, offset int, cb FsCb) int { - return FsFtruncate(f.Loop, f.Req, file, offset, cb) -} - -// Sendfile sends data from one file descriptor to another. -func (f *File) Sendfile(outFd int, inFd int, inOffset int, length int, cb FsCb) int { - return FsSendfile(f.Loop, f.Req, outFd, inFd, inOffset, length, cb) -} - -// Access checks the access permissions of a file specified by the path. -func (f *File) Access(path *c.Char, flags int, cb FsCb) int { - return FsAccess(f.Loop, f.Req, path, flags, cb) -} - -// Chmod changes the permissions of a file specified by the path. -func (f *File) Chmod(path *c.Char, mode int, cb FsCb) int { - return FsChmod(f.Loop, f.Req, path, mode, cb) -} - -// Fchmod changes the permissions of a file descriptor. -func (f *File) Fchmod(file int, mode int, cb FsCb) int { - return FsFchmod(f.Loop, f.Req, file, mode, cb) -} - -// Utime updates the access and modification times of a file specified by the path. -func (f *File) Utime(path *c.Char, atime int, mtime int, cb FsCb) int { - return FsUtime(f.Loop, f.Req, path, atime, mtime, cb) -} - -// Futime updates the access and modification times of a file descriptor. -func (f *File) Futime(file int, atime int, mtime int, cb FsCb) int { - return FsFutime(f.Loop, f.Req, file, atime, mtime, cb) -} - -// Lutime updates the access and modification times of a file specified by the path, even if the path is a symbolic link. -func (f *File) Lutime(path *c.Char, atime int, mtime int, cb FsCb) int { - return FsLutime(f.Loop, f.Req, path, atime, mtime, cb) -} - -// Link creates a new link to an existing file. -func (f *File) Link(path *c.Char, newPath *c.Char, cb FsCb) int { - return FsLink(f.Loop, f.Req, path, newPath, cb) -} - -// Symlink creates a symbolic link from the path to the new path. -func (f *File) Symlink(path *c.Char, newPath *c.Char, flags int, cb FsCb) int { - return FsSymlink(f.Loop, f.Req, path, newPath, flags, cb) -} - -// Readlink reads the target of a symbolic link. -func (f *File) Readlink(path *c.Char, cb FsCb) int { - return FsReadlink(f.Loop, f.Req, path, cb) -} - -// Realpath resolves the absolute path of a file. -func (f *File) Realpath(path *c.Char, cb FsCb) int { - return FsRealpath(f.Loop, f.Req, path, cb) -} - -// Copyfile copies a file from the source path to the destination path. -func (f *File) Copyfile(path *c.Char, newPath *c.Char, flags int, cb FsCb) int { - return FsCopyfile(f.Loop, f.Req, path, newPath, flags, cb) -} - -// Scandir scans a directory for entries. -func (f *File) Scandir(path *c.Char, flags int, cb FsCb) int { - return FsScandir(f.Loop, f.Req, path, flags, cb) -} - -// OpenDir opens a directory specified by the path. -func (f *File) OpenDir(path *c.Char, cb FsCb) int { - return FsOpenDir(f.Loop, f.Req, path, cb) -} - -// Readdir reads entries from an open directory. -func (f *File) Readdir(dir int, cb FsCb) int { - return FsReaddir(f.Loop, f.Req, dir, cb) -} - -// CloseDir closes an open directory. -func (f *File) CloseDir() int { - return FsCloseDir(f.Loop, f.Req) -} - -// Statfs retrieves file system status information. -func (f *File) Statfs(path *c.Char, cb FsCb) int { - return FsStatfs(f.Loop, f.Req, path, cb) -} - -// Chown Change file ownership -func (f *File) Chown(path *c.Char, uid int, gid int, cb FsCb) int { - return FsChown(f.Loop, f.Req, path, uid, gid, cb) -} - -// Fchown Change file ownership by file descriptor -func (f *File) Fchown(file int, uid int, gid int, cb FsCb) int { - return FsFchown(f.Loop, f.Req, file, uid, gid, cb) -} - -// Lchown Change file ownership (symlink) -func (f *File) Lchown(path *c.Char, uid int, gid int, cb FsCb) int { - return FsLchown(f.Loop, f.Req, path, uid, gid, cb) -} - -// Lstat Get file status (symlink) -func (f *File) Lstat(path *c.Char, cb FsCb) int { - return FsLstat(f.Loop, f.Req, path, cb) -} - -// Init Initialize a file event handle -func (e *FsEvent) Init(loop *Loop) int { - return FsEventInit(loop, e) -} - -// Start listening for file events -func (e *FsEvent) Start(cb FsEventCb, path *c.Char, flags int) int { - return FsEventStart(e, cb, path, flags) -} - -// Stop listening for file events -func (e *FsEvent) Stop() int { - return FsEventStop(e) -} - -// Close the file event handle -func (e *FsEvent) Close() int { - return FsEventClose(e) -} - -// GetPath Get the path of the file event -func (e *FsEvent) GetPath() *c.Char { - return FsEventGetpath(e) -} - -// Init Initialize a file poll handle -func (p *FsPoll) Init(loop *Loop) int { - return FsPollInit(loop, p) -} - -// Start polling for file changes -func (p *FsPoll) Start(cb FsPollCb, path *c.Char, interval uint) int { - return FsPollStart(p, cb, path, interval) -} - -// Stop polling for file changes -func (p *FsPoll) Stop() int { - return FsPollStop(p) -} - -// Close the file poll handle -func (p *FsPoll) Close() int { - return FsPollClose(p) -} - -// GetPath Get the path of the file poll -func (p *FsPoll) GetPath() *c.Char { - return FsPollGetPath(p) -} diff --git a/c/libuv/libuv.go b/c/libuv/libuv.go index fb0c7664..11a36700 100644 --- a/c/libuv/libuv.go +++ b/c/libuv/libuv.go @@ -11,6 +11,11 @@ const ( ) // ---------------------------------------------- +const ( + RUN_DEFAULT RunMode = iota + RUN_ONCE + RUN_NOWAIT +) const ( LOOP_BLOCK_SIGNAL LoopOption = iota @@ -60,6 +65,15 @@ const ( REQ_TYPE_MAX ) +const ( + READABLE PollEvent = 1 << iota + WRITABLE + DISCONNECT + PRIPRIORITIZED +) + +type RunMode c.Int + type LoopOption c.Int type Membership c.Int @@ -68,26 +82,30 @@ type HandleType c.Int type ReqType c.Int -type Uv_File c.Int - type OsSock c.Int type OsFd c.Int +type PollEvent c.Int + // ---------------------------------------------- /* Handle types. */ -type Handle struct { +type Loop struct { Unused [0]byte } +type Handle struct { + Unused [96]byte +} + type Dir struct { Unused [0]byte } type Stream struct { - Unused [0]byte + Unused [264]byte } type Pipe struct { @@ -122,18 +140,6 @@ type Process struct { Unused [0]byte } -type FsEvent struct { - Unused [0]byte -} - -type FsPoll struct { - Unused [0]byte -} - -type Signal struct { - Unused [0]byte -} - /* Request types. */ type Req struct { @@ -153,14 +159,17 @@ type Shutdown struct { } type Write struct { - Unused [0]byte + Unused [192]byte } type Connect struct { Unused [0]byte } -// ---------------------------------------------- +type Buf struct { + Base *c.Char + Len uintptr +} // ---------------------------------------------- /* Function type */ @@ -200,6 +209,9 @@ type ShutdownCb func(req *Shutdown, status c.Int) // llgo:type C type WalkCb func(handle *Handle, arg c.Pointer) +// llgo:type C +type PollCb func(handle *Poll, status c.Int, events c.Int) + // ---------------------------------------------- //go:linkname Version C.uv_version @@ -284,7 +296,7 @@ func (handle *Handle) Fileno(fd *OsFd) c.Int { } //go:linkname UvPipe C.uv_pipe -func UvPipe(fds [2]Uv_File, readFlags c.Int, writeFlags c.Int) c.Int { +func UvPipe(fds [2]UvFile, readFlags c.Int, writeFlags c.Int) c.Int { return 0 } @@ -351,22 +363,22 @@ func (stream *Stream) StopRead() c.Int { } // llgo:link (*Write).Write C.uv_write -func (req *Write) Write(stream *Stream, bufs []Buf, nbufs c.Uint, writeCb WriteCb) c.Int { +func (req *Write) Write(stream *Stream, bufs *Buf, nbufs c.Uint, writeCb WriteCb) c.Int { return 0 } // llgo:link (*Write).Write2 C.uv_write2 -func (req *Write) Write2(stream *Stream, bufs []Buf, nbufs c.Uint, sendStream *Stream, writeCb WriteCb) c.Int { +func (req *Write) Write2(stream *Stream, bufs *Buf, nbufs c.Uint, sendStream *Stream, writeCb WriteCb) c.Int { return 0 } // llgo:link (*Stream).TryWrite C.uv_try_write -func (stream *Stream) TryWrite(bufs []Buf, nbufs c.Uint) c.Int { +func (stream *Stream) TryWrite(bufs *Buf, nbufs c.Uint) c.Int { return 0 } // llgo:link (*Stream).TryWrite2 C.uv_try_write2 -func (stream *Stream) TryWrite2(bufs []Buf, nbufs c.Uint, sendStream *Stream) c.Int { +func (stream *Stream) TryWrite2(bufs *Buf, nbufs c.Uint, sendStream *Stream) c.Int { return 0 } @@ -387,6 +399,78 @@ func (stream *Stream) SetBlocking(blocking c.Int) c.Int { // ---------------------------------------------- +/* Loop related functions and method. */ + +//go:linkname LoopSize C.uv_loop_size +func LoopSize() uintptr + +//go:linkname Run C.uv_run +func Run(loop *Loop, mode RunMode) c.Int + +//go:linkname LoopAlive C.uv_loop_alive +func LoopAlive(loop *Loop) c.Int + +//go:linkname LoopClose C.uv_loop_close +func LoopClose(loop *Loop) c.Int + +//go:linkname LoopConfigure C.uv_loop_configure +func LoopConfigure(loop *Loop, option LoopOption, arg c.Int) c.Int + +//go:linkname LoopDefault C.uv_default_loop +func LoopDefault() *Loop + +//go:linkname LoopDelete C.uv_loop_delete +func LoopDelete(loop *Loop) c.Int + +//go:linkname LoopFork C.uv_loop_fork +func LoopFork(loop *Loop) c.Int + +//go:linkname LoopInit C.uv_loop_init +func LoopInit(loop *Loop) c.Int + +//go:linkname LoopNew C.uv_loop_new +func LoopNew() *Loop + +//go:linkname LoopNow C.uv_now +func LoopNow(loop *Loop) c.UlongLong + +//go:linkname LoopUpdateTime C.uv_update_time +func LoopUpdateTime(loop *Loop) + +//go:linkname LoopBackendFd C.uv_backend_fd +func LoopBackendFd(loop *Loop) c.Int + +//go:linkname LoopBackendTimeout C.uv_backend_timeout +func LoopBackendTimeout(loop *Loop) c.Int + +//go:linkname LoopWalk C.uv_walk +func LoopWalk(loop *Loop, walkCb WalkCb, arg c.Pointer) + +// ---------------------------------------------- + +/* Buf related functions and method. */ + +//go:linkname InitBuf C.uv_buf_init +func InitBuf(base *c.Char, len c.Uint) Buf + +// ---------------------------------------------- + +/* Poll related function and method */ + +//go:linkname PollInit C.uv_poll_init +func PollInit(loop *Loop, handle *Poll, fd OsFd) c.Int + +//go:linkname PollStart C.uv_poll_start +func PollStart(handle *Poll, events c.Int, cb PollCb) c.Int + +//go:linkname PollStop C.uv_poll_stop +func PollStop(handle *Poll) c.Int + +//go:linkname PollInitSocket C.uv_poll_init_socket +func PollInitSocket(loop *Loop, handle *Poll, socket c.Int) c.Int + +// ---------------------------------------------- + /* Getaddrinfo related function and method */ //go:linkname Getaddrinfo C.uv_getaddrinfo diff --git a/c/libuv/net.go b/c/libuv/net.go index e2f824f6..3fbb8f96 100644 --- a/c/libuv/net.go +++ b/c/libuv/net.go @@ -65,7 +65,7 @@ type UdpFlags c.Int /* Handle types. */ type Tcp struct { - Unused [0]byte + Unused [264]byte } type Udp struct { @@ -207,8 +207,8 @@ func (udp *Udp) SetMulticastInterface(interfaceAddr *c.Char) c.Int { return 0 } -// llgo:link (*Udp).SAetBroadcast C.uv_udp_set_broadcast -func (udp *Udp) SAetBroadcast(on c.Int) c.Int { +// llgo:link (*Udp).SetBroadcast C.uv_udp_set_broadcast +func (udp *Udp) SetBroadcast(on c.Int) c.Int { return 0 } @@ -218,15 +218,15 @@ func (udp *Udp) SetTTL(ttl c.Int) c.Int { } //go:linkname Send C.uv_udp_send -func Send(req *UdpSend, udp *Udp, bufs []Buf, nbufs c.Uint, addr *net.SockAddr, sendCb UdpSendCb) c.Int +func Send(req *UdpSend, udp *Udp, bufs *Buf, nbufs c.Uint, addr *net.SockAddr, sendCb UdpSendCb) c.Int // llgo:link (*Udp).TrySend C.uv_udp_try_send -func (udp *Udp) TrySend(bufs []Buf, nbufs c.Uint, addr *net.SockAddr) c.Int { +func (udp *Udp) TrySend(bufs *Buf, nbufs c.Uint, addr *net.SockAddr) c.Int { return 0 } -// llgo:link (*Udp).RecvStart C.uv_udp_recv_start -func (udp *Udp) RecvStart(allocCb AllocCb, recvCb UdpRecvCb) c.Int { +// llgo:link (*Udp).StartRecv C.uv_udp_recv_start +func (udp *Udp) StartRecv(allocCb AllocCb, recvCb UdpRecvCb) c.Int { return 0 } @@ -235,8 +235,8 @@ func (udp *Udp) UsingRecvmmsg() c.Int { return 0 } -// llgo:link (*Udp).RecvStop C.uv_udp_recv_stop -func (udp *Udp) RecvStop() c.Int { +// llgo:link (*Udp).StopRecv C.uv_udp_recv_stop +func (udp *Udp) StopRecv() c.Int { return 0 } diff --git a/c/libuv/signal.go b/c/libuv/signal.go index 97847d1c..8aad3b0e 100644 --- a/c/libuv/signal.go +++ b/c/libuv/signal.go @@ -13,24 +13,20 @@ type Signal struct { // ---------------------------------------------- -/* Signal related functions and method. */ +/* Function type */ // llgo:type C type SignalCb func(handle *Signal, sigNum c.Int) -//go:linkname UvSignalInit C.uv_signal_init -func UvSignalInit(loop *Loop, handle *Signal) c.Int +// ---------------------------------------------- -// llgo:link (*Signal).Start C.uv_signal_start -func (s *Signal) Start(cb SignalCb, signum c.Int) c.Int { - return 0 -} +/* Signal related functions and method. */ -// llgo:link (*Signal).StartOneshot C.uv_signal_start_oneshot -func (s *Signal) StartOneshot(handle *Signal, cb SignalCb, signum c.Int) c.Int { - return 0 -} +//go:linkname SignalInit C.uv_signal_init +func SignalInit(loop *Loop, handle *Signal) c.Int -func (s *Signal) Init(loop *Loop) int { - return UvSignalInit(loop, s) -} +//go:linkname SignalStart C.uv_signal_start +func SignalStart(handle *Signal, cb SignalCb, signum c.Int) c.Int + +//go:linkname SignalStartOneshot C.uv_signal_start_oneshot +func SignalStartOneshot(handle *Signal, cb SignalCb, signum c.Int) c.Int diff --git a/c/libuv/timer.go b/c/libuv/timer.go index fff1af5d..feeabe5a 100644 --- a/c/libuv/timer.go +++ b/c/libuv/timer.go @@ -15,7 +15,7 @@ type Timer struct { // ---------------------------------------------- -// llgo:type C +// llgo:type Cgit type TimerCb func(timer *Timer) // ----------------------------------------------