diff --git a/c/neco/_demo/generators/_c/generators.c b/c/neco/_demo/cgen/_c/gen.c similarity index 96% rename from c/neco/_demo/generators/_c/generators.c rename to c/neco/_demo/cgen/_c/gen.c index 59891aaa..b71c5d81 100644 --- a/c/neco/_demo/generators/_c/generators.c +++ b/c/neco/_demo/cgen/_c/gen.c @@ -1,4 +1,4 @@ -#include "../../../_neco/neco.h" +#include "../../../_wrap/neco.h" #include #include diff --git a/c/neco/_demo/generators/generators.go b/c/neco/_demo/cgen/cgen.go similarity index 50% rename from c/neco/_demo/generators/generators.go rename to c/neco/_demo/cgen/cgen.go index 32ea5429..87c3eb49 100644 --- a/c/neco/_demo/generators/generators.go +++ b/c/neco/_demo/cgen/cgen.go @@ -7,13 +7,13 @@ import ( ) const ( - LLGoFiles = "_c/generators.c; ../../_neco/neco.c" + LLGoFiles = "_c/gen.c; ../../_wrap/neco.c" LLGoPackage = "link" ) func main() { - run_main() + runMain() } -//go:linkname run_main C.run_main -func run_main() {} +//go:linkname runMain C.run_main +func runMain() {} diff --git a/c/neco/_demo/gogenerators/g2.go b/c/neco/_demo/gen/gen.go similarity index 67% rename from c/neco/_demo/gogenerators/g2.go rename to c/neco/_demo/gen/gen.go index 8e13a8e8..cd5771f0 100644 --- a/c/neco/_demo/gogenerators/g2.go +++ b/c/neco/_demo/gen/gen.go @@ -15,16 +15,16 @@ func main() { func run_main() { // c.Printf(c.Str("run_main")) // c.Fflush(c.Stdout) - neco.Neco_env_setpaniconerror(true) - neco.Neco_env_setcanceltype(neco.NECO_CANCEL_ASYNC) - ret := neco.Neco_start(main2, 0) - c.Fprintf(c.Stderr, c.Str("neco_start: %s (code %d)\n"), neco.Neco_strerror(int(ret)), ret) + neco.EnvSetpaniconerror(true) + neco.EnvSetcanceltype(neco.CANCEL_ASYNC) + ret := neco.Start(main2, 0) + c.Fprintf(c.Stderr, c.Str("neco_start: %s (code %d)\n"), neco.Strerror(ret), ret) } func main2(argc c.Int, argv ...any) { // c.Printf(c.Str("main2")) // c.Fflush(c.Stdout) - neco.Neco_exit_prog(main3()) + neco.ExitProg(main3()) } func main3() c.Int { @@ -33,18 +33,18 @@ func main3() c.Int { // c.Fflush(c.Stdout) // Create a new generator coroutine that is used to send ints. - gen := new(neco.Neco_gen) - neco.Neco_gen_start(&gen, unsafe.Sizeof(int(0)), coroutine, 0) + gen := new(neco.Gen) + neco.GenStart(&gen, unsafe.Sizeof(int(0)), coroutine, 0) // Iterate over each int until the generator is closed. var i c.Int for { - ret := neco.Neco_gen_next(gen, c.Pointer(&i)) + ret := neco.GenNext(gen, c.Pointer(&i)) // c.Printf(c.Str("gen [%d, %d] "), ret, c.Int(neco.NECO_CLOSED)) // c.Fflush(c.Stdout) - if ret != c.Int(neco.NECO_CLOSED) { + if ret != c.Int(neco.CLOSED) { c.Printf(c.Str("%d\n"), i) } else { break @@ -52,7 +52,7 @@ func main3() c.Int { } // This coroutine no longer needs the generator. - neco.Neco_gen_release(gen) + neco.GenRelease(gen) // c.Printf(c.Str("main3 end")) // c.Fflush(c.Stdout) @@ -63,7 +63,7 @@ func main3() c.Int { func coroutine(argc c.Int, argv ...any) { // Yield each int to the caller, one at a time. for i := 0; i < 10; i++ { - neco.Neco_gen_yield(c.Pointer(&i)) + neco.GenYield(c.Pointer(&i)) } // c.Printf(c.Str("coroutine end")) // c.Fflush(c.Stdout) diff --git a/c/neco/_demo/gen2/gen2.go b/c/neco/_demo/gen2/gen2.go new file mode 100644 index 00000000..fcac1094 --- /dev/null +++ b/c/neco/_demo/gen2/gen2.go @@ -0,0 +1,48 @@ +package main + +import ( + "unsafe" + + "github.com/goplus/llgo/c" + "github.com/goplus/llgo/c/neco" +) + +func main() { + neco.Main(func() c.Int { + // Create a new generator coroutine that is used to send ints. + gen := new(neco.Gen) + neco.GenStart(&gen, unsafe.Sizeof(int(0)), coroutine, 0) + + // Iterate over each int until the generator is closed. + var i c.Int + for { + ret := neco.GenNext(gen, c.Pointer(&i)) + + // c.Printf(c.Str("gen [%d, %d] "), ret, c.Int(neco.NECO_CLOSED)) + // c.Fflush(c.Stdout) + + if ret != c.Int(neco.CLOSED) { + c.Printf(c.Str("%d\n"), i) + } else { + break + } + } + + // This coroutine no longer needs the generator. + neco.GenRelease(gen) + + // c.Printf(c.Str("main3 end")) + // c.Fflush(c.Stdout) + + return 0 + }) +} + +func coroutine(argc c.Int, argv ...any) { + // Yield each int to the caller, one at a time. + for i := 0; i < 10; i++ { + neco.GenYield(c.Pointer(&i)) + } + // c.Printf(c.Str("coroutine end")) + // c.Fflush(c.Stdout) +} diff --git a/c/neco/_neco/neco.c b/c/neco/_wrap/neco.c similarity index 100% rename from c/neco/_neco/neco.c rename to c/neco/_wrap/neco.c diff --git a/c/neco/_neco/neco.h b/c/neco/_wrap/neco.h similarity index 100% rename from c/neco/_neco/neco.h rename to c/neco/_wrap/neco.h diff --git a/c/neco/neco.go b/c/neco/neco.go index bc39a7e3..87fb1747 100644 --- a/c/neco/neco.go +++ b/c/neco/neco.go @@ -7,64 +7,89 @@ import ( ) const ( - LLGoFiles = "_neco/neco.c" + LLGoFiles = "_wrap/neco.c" LLGoPackage = "link" ) const ( - NECO_OK = 0 ///< Successful result (no error) - NECO_ERROR = -1 ///< System error (check errno) - NECO_INVAL = -2 ///< Invalid argument - NECO_PERM = -3 ///< Operation not permitted - NECO_NOMEM = -4 ///< Cannot allocate memory - NECO_EOF = -5 ///< End of file or stream (neco_stream_*) - NECO_NOTFOUND = -6 ///< No such coroutine (neco_cancel) - NECO_NOSIGWATCH = -7 ///< Not watching on a signal - NECO_CLOSED = -8 ///< Channel is closed - NECO_EMPTY = -9 ///< Channel is empty (neco_chan_tryrecv) - NECO_TIMEDOUT = -10 ///< Deadline has elapsed (neco_*_dl) - NECO_CANCELED = -11 ///< Operation canceled (by neco_cancel) - NECO_BUSY = -12 ///< Resource busy (mutex_trylock) - NECO_NEGWAITGRP = -13 ///< Negative waitgroup counter - NECO_GAIERROR = -14 ///< Error with getaddrinfo (check neco_gai_error) - NECO_UNREADFAIL = -15 ///< Failed to unread byte (neco_stream_unread_byte) - NECO_PARTIALWRITE = -16 ///< Failed to write all data (neco_stream_flush) - NECO_NOTGENERATOR = -17 ///< Coroutine is not a generator (neco_gen_yield) - NECO_NOTSUSPENDED = -18 ///< Coroutine is not suspended (neco_resume) + OK = 0 ///< Successful result (no error) + ERROR = -1 ///< System error (check errno) + INVAL = -2 ///< Invalid argument + PERM = -3 ///< Operation not permitted + NOMEM = -4 ///< Cannot allocate memory + EOF = -5 ///< End of file or stream (neco_stream_*) + NOTFOUND = -6 ///< No such coroutine (neco_cancel) + NOSIGWATCH = -7 ///< Not watching on a signal + CLOSED = -8 ///< Channel is closed + EMPTY = -9 ///< Channel is empty (neco_chan_tryrecv) + TIMEDOUT = -10 ///< Deadline has elapsed (neco_*_dl) + CANCELED = -11 ///< Operation canceled (by neco_cancel) + BUSY = -12 ///< Resource busy (mutex_trylock) + NEGWAITGRP = -13 ///< Negative waitgroup counter + GAIERROR = -14 ///< Error with getaddrinfo (check neco_gai_error) + UNREADFAIL = -15 ///< Failed to unread byte (neco_stream_unread_byte) + PARTIALWRITE = -16 ///< Failed to write all data (neco_stream_flush) + NOTGENERATOR = -17 ///< Coroutine is not a generator (neco_gen_yield) + NOTSUSPENDED = -18 ///< Coroutine is not suspended (neco_resume) - NECO_CANCEL_ASYNC = 1 - NECO_CANCEL_INLINE = 2 - NECO_CANCEL_ENABLE = 3 - NECO_CANCEL_DISABLE = 4 + CANCEL_ASYNC = 1 + CANCEL_INLINE = 2 + CANCEL_ENABLE = 3 + CANCEL_DISABLE = 4 + + EAI_SYSTEM = 11 + + NANOSECOND = int64(1) + MICROSECOND = int64(1000) + MILLISECOND = int64(1000000) + SECOND = int64(1000000000) + MINUTE = int64(60000000000) + HOUR = int64(3600000000000) ) -//go:linkname Neco_gen_yield C.neco_gen_yield -func Neco_gen_yield(data c.Pointer) c.Int +// generator +type Gen struct{} -//go:linkname Neco_gen_next C.neco_gen_next -func Neco_gen_next(gen *Neco_gen, data c.Pointer) c.Int +//go:linkname GenYield C.neco_gen_yield +func GenYield(data c.Pointer) c.Int -//go:linkname Neco_gen_start C.neco_gen_start -func Neco_gen_start(gen **Neco_gen, data_size uintptr, co Neco_coro, argc c.Int, argv ...any) c.Int +//go:linkname GenNext C.neco_gen_next +func GenNext(gen *Gen, data c.Pointer) c.Int -//go:linkname Neco_gen_release C.neco_gen_release -func Neco_gen_release(gen *Neco_gen) c.Int +//go:linkname GenStart C.neco_gen_start +func GenStart(gen **Gen, dataSize uintptr, co Coro, argc c.Int, __llgo_va_list /* argv */ ...any) c.Int -//go:linkname Neco_exit_prog C.__neco_exit_prog -func Neco_exit_prog(code c.Int) +//go:linkname GenRelease C.neco_gen_release +func GenRelease(gen *Gen) c.Int -//go:linkname Neco_env_setpaniconerror C.neco_env_setpaniconerror -func Neco_env_setpaniconerror(paniconerror bool) +//go:linkname ExitProg C.__neco_exit_prog +func ExitProg(code c.Int) -//go:linkname Neco_env_setcanceltype C.neco_env_setcanceltype -func Neco_env_setcanceltype(type_ c.Int) +//go:linkname EnvSetpaniconerror C.neco_env_setpaniconerror +func EnvSetpaniconerror(paniconerror bool) -//go:linkname Neco_strerror C.neco_strerror -func Neco_strerror(errcode int) *c.Char +//go:linkname EnvSetcanceltype C.neco_env_setcanceltype +func EnvSetcanceltype(type_ c.Int) -//go:linkname Neco_start C.neco_start -func Neco_start(co Neco_coro, argc c.Int, argv ...any) c.Int +//go:linkname Strerror C.neco_strerror +func Strerror(errcode c.Int) *c.Char -type Neco_gen struct{} +//go:linkname Start C.neco_start +func Start(co Coro, argc c.Int, __llgo_va_list /* argv */ ...any) c.Int -type Neco_coro = func(argc c.Int, argv ...any) +// llgo:type C +type Coro = func(argc c.Int, __llgo_va_list /* argv */ ...any) + +var mainfn func() c.Int + +func Main(fn func() c.Int) { + mainfn = fn + + EnvSetpaniconerror(true) + EnvSetcanceltype(CANCEL_ASYNC) + ret := Start(func(argc c.Int, args ...any) { + ExitProg(mainfn()) + }, 0) + c.Fprintf(c.Stderr, c.Str("llgo/c/neco.RunMain: Start: %s (code %d)\n"), Strerror(ret), ret) + c.Exit(1) +}