Compare commits
295 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
621f05c687 | ||
|
|
daf97eabab | ||
|
|
ee3d11cb53 | ||
|
|
1bc7e5e0a5 | ||
|
|
9280d23b1a | ||
|
|
cacd52f81d | ||
|
|
95f64761ca | ||
|
|
6e24792b9b | ||
|
|
9afe26f1d6 | ||
|
|
e7d959da90 | ||
|
|
c3f0867d2c | ||
|
|
1eaf124d4e | ||
|
|
03076bdc76 | ||
|
|
cd32d6debe | ||
|
|
3212f059ff | ||
|
|
9ae4b93083 | ||
|
|
aae7af2194 | ||
|
|
63f4c73ef0 | ||
|
|
f93d3381e0 | ||
|
|
099c80e04b | ||
|
|
14face336e | ||
|
|
67b10d8d38 | ||
|
|
1219230168 | ||
|
|
8d840e694d | ||
|
|
87382aad4d | ||
|
|
aca3a05222 | ||
|
|
84ca145663 | ||
|
|
01d0338851 | ||
|
|
f427c0532d | ||
|
|
c8532a548c | ||
|
|
1e3aef5b94 | ||
|
|
0d3180271b | ||
|
|
f0d17b13f2 | ||
|
|
9a46301d46 | ||
|
|
3bd609ee41 | ||
|
|
2c7f0e8583 | ||
|
|
ce36a25ba3 | ||
|
|
c53484f92e | ||
|
|
f391ccb8e8 | ||
|
|
a96d6a8148 | ||
|
|
bdca09007d | ||
|
|
c0e84043c9 | ||
|
|
0a884df74f | ||
|
|
519b14d506 | ||
|
|
f008a65d91 | ||
|
|
61bb70cd30 | ||
|
|
68fa3dadb0 | ||
|
|
eb38d03976 | ||
|
|
d480bb3ecd | ||
|
|
dfdb6fa1a6 | ||
|
|
42352d9f57 | ||
|
|
eae1c5db70 | ||
|
|
cc37097164 | ||
|
|
6597cc9ce8 | ||
|
|
b3f752d46c | ||
|
|
679e2d0f6b | ||
|
|
4607079ca9 | ||
|
|
ad1a42d6a5 | ||
|
|
afdf31a66c | ||
|
|
37956e2f05 | ||
|
|
dc6aa66f9a | ||
|
|
f16f16c15e | ||
|
|
3b95cbd960 | ||
|
|
3b5e8edd37 | ||
|
|
5f4571e895 | ||
|
|
2d5e991eaf | ||
|
|
7ba8bb4405 | ||
|
|
82aa181540 | ||
|
|
1a3e17bae8 | ||
|
|
e0e3664fdb | ||
|
|
23bfaf1ba2 | ||
|
|
e7d72b6f53 | ||
|
|
eab26deab9 | ||
|
|
49540dbe5e | ||
|
|
cbd891785e | ||
|
|
b1cc732cb2 | ||
|
|
b3b4f55c68 | ||
|
|
8b6b039c13 | ||
|
|
9dca62ff8b | ||
|
|
e0892fcebb | ||
|
|
adf1443105 | ||
|
|
53c2558d26 | ||
|
|
a5ea240793 | ||
|
|
4cd1629118 | ||
|
|
ce32a73e86 | ||
|
|
8a13fc7cd9 | ||
|
|
708de50887 | ||
|
|
4df478316c | ||
|
|
a5dff9fb15 | ||
|
|
b51f4d53b6 | ||
|
|
7d045842dd | ||
|
|
a9ece9e49d | ||
|
|
e6da067cf8 | ||
|
|
bae40c82b9 | ||
|
|
651edf5bc0 | ||
|
|
3a8642b1e0 | ||
|
|
09b6b9259c | ||
|
|
907f326788 | ||
|
|
4a350d8ad9 | ||
|
|
3881db0b4e | ||
|
|
9edae3e877 | ||
|
|
236208e393 | ||
|
|
4ff98de707 | ||
|
|
54964629fe | ||
|
|
072f606784 | ||
|
|
21d2338ec1 | ||
|
|
0d468e0df4 | ||
|
|
5007d49c83 | ||
|
|
35ba69a175 | ||
|
|
fa0ce2a14c | ||
|
|
389750d7d8 | ||
|
|
6c7db7ad23 | ||
|
|
2986426251 | ||
|
|
56444ebcaf | ||
|
|
c63a1978cb | ||
|
|
9d9e998d49 | ||
|
|
f7c991fa9a | ||
|
|
4d14fbb1e7 | ||
|
|
5428730e7a | ||
|
|
bf773df099 | ||
|
|
6dea5100b1 | ||
|
|
aa55f4dceb | ||
|
|
516e92926a | ||
|
|
2cd9994321 | ||
|
|
e69306a2ba | ||
|
|
93ecd031bd | ||
|
|
4eaf69dfa7 | ||
|
|
bc93bda1b7 | ||
|
|
6923f0df2a | ||
|
|
bc584aa56e | ||
|
|
ec95d06f6c | ||
|
|
c5d18d9046 | ||
|
|
af06983c60 | ||
|
|
e027872f50 | ||
|
|
e98e4fde8d | ||
|
|
2daf9de890 | ||
|
|
ae50511135 | ||
|
|
2227f83b1d | ||
|
|
e764a2298d | ||
|
|
ed4a8c2a36 | ||
|
|
8cc3e571e3 | ||
|
|
66a89a7d54 | ||
|
|
666be94a71 | ||
|
|
49fabf23a8 | ||
|
|
a3b23e348a | ||
|
|
384e887fdb | ||
|
|
d3e84cbc4c | ||
|
|
1b06948fb0 | ||
|
|
98d075728f | ||
|
|
1a7ecda67c | ||
|
|
067078db86 | ||
|
|
37650fae75 | ||
|
|
13be3e3216 | ||
|
|
87a7809104 | ||
|
|
e82c33716a | ||
|
|
9ebdddad1f | ||
|
|
90f85bb9c3 | ||
|
|
002d04a3a1 | ||
|
|
88a0b12e73 | ||
|
|
5828e7f576 | ||
|
|
a11da90d10 | ||
|
|
d8026833dc | ||
|
|
8029bb6142 | ||
|
|
baaddd395c | ||
|
|
8bcbe7b3c6 | ||
|
|
4297320886 | ||
|
|
614994d8c7 | ||
|
|
65e1f261c0 | ||
|
|
aa4caa6938 | ||
|
|
9741574516 | ||
|
|
c27c654180 | ||
|
|
c63580ee38 | ||
|
|
e9d4328fad | ||
|
|
545f9f2cca | ||
|
|
db6930d9e4 | ||
|
|
9379a41b37 | ||
|
|
c0eeedc71a | ||
|
|
400197def8 | ||
|
|
0f8b202531 | ||
|
|
1eb9775f34 | ||
|
|
89bdb315d5 | ||
|
|
ab1afd68b7 | ||
|
|
e1109e9e51 | ||
|
|
7230e19166 | ||
|
|
eb7a94bb55 | ||
|
|
18de4e57eb | ||
|
|
74cc12133e | ||
|
|
7583354f44 | ||
|
|
14c49dd681 | ||
|
|
e060208417 | ||
|
|
635eea7acb | ||
|
|
2c47f4a23d | ||
|
|
2223577302 | ||
|
|
f42d235dec | ||
|
|
06a3e278ff | ||
|
|
17c30b5fdc | ||
|
|
024b30d0b7 | ||
|
|
a108610a67 | ||
|
|
12b6abe6a3 | ||
|
|
6f82b36962 | ||
|
|
ea6b397526 | ||
|
|
118bb3f3ba | ||
|
|
bd68075f4d | ||
|
|
5fa68f8cdd | ||
|
|
199aaf2d05 | ||
|
|
892efcc166 | ||
|
|
bc90c6b82f | ||
|
|
82d3d1f0f3 | ||
|
|
576b3198f1 | ||
|
|
f55cad8f1c | ||
|
|
d98654b50d | ||
|
|
675d9d8c09 | ||
|
|
bab0bb349f | ||
|
|
65d3ed8ce8 | ||
|
|
8fc4000b63 | ||
|
|
5b35f781cb | ||
|
|
2cd11b7da7 | ||
|
|
cf30d2923c | ||
|
|
8fc97794e8 | ||
|
|
df2ba37687 | ||
|
|
85b16b2a54 | ||
|
|
eeabc6b61a | ||
|
|
2b3dafed61 | ||
|
|
7232fc36ab | ||
|
|
a8e1fd1054 | ||
|
|
c248a50338 | ||
|
|
fa0ca23798 | ||
|
|
ed224cf912 | ||
|
|
b51df25371 | ||
|
|
db8cc8eb7b | ||
|
|
a027e9fe14 | ||
|
|
b882ca809a | ||
|
|
daf0a9dc9a | ||
|
|
f2dafa7544 | ||
|
|
7fe22875a6 | ||
|
|
3da3c8ecd8 | ||
|
|
254acbbbe2 | ||
|
|
519c850f17 | ||
|
|
1cf57508b0 | ||
|
|
f8bacfcc67 | ||
|
|
9daa77c1a4 | ||
|
|
c4775dd313 | ||
|
|
ae87cb031e | ||
|
|
3c049f25ee | ||
|
|
85a90b62b7 | ||
|
|
10b0124951 | ||
|
|
c0d7ff9543 | ||
|
|
74012d4869 | ||
|
|
830c40440f | ||
|
|
21a2f71ad9 | ||
|
|
cf75e3e664 | ||
|
|
ffc307323a | ||
|
|
ff0aec28c5 | ||
|
|
31394b03ae | ||
|
|
2ab93cb385 | ||
|
|
172b396dc9 | ||
|
|
9b82d08087 | ||
|
|
410617f73b | ||
|
|
ade0d38a7c | ||
|
|
3ce55a2ac4 | ||
|
|
cc6e4dbec0 | ||
|
|
2935ae7bf1 | ||
|
|
96e418e63b | ||
|
|
e4a84dcfe9 | ||
|
|
9ea91cfce3 | ||
|
|
8c7f0cf988 | ||
|
|
afa9a00259 | ||
|
|
a0ee11c300 | ||
|
|
6e02dace18 | ||
|
|
93bac6f26f | ||
|
|
8657fbd810 | ||
|
|
68203be004 | ||
|
|
b2323ef2e7 | ||
|
|
70b017fb72 | ||
|
|
607e3bbc11 | ||
|
|
315c9285de | ||
|
|
c22427b8fd | ||
|
|
2fcfac9e84 | ||
|
|
7cc857233f | ||
|
|
f85aa09784 | ||
|
|
0b0cecc2a9 | ||
|
|
3b5b9c9587 | ||
|
|
cbe190fa70 | ||
|
|
9156466351 | ||
|
|
f79caf095d | ||
|
|
d31dcd13fc | ||
|
|
552224bbfe | ||
|
|
5ba01674fb | ||
|
|
7390afc5e1 | ||
|
|
85ec23d552 | ||
|
|
007064c0ac | ||
|
|
fd53756170 | ||
|
|
9e6dd9f23d | ||
|
|
ef8be6c7c2 | ||
|
|
de4b5b70da |
32
.github/workflows/go.yml
vendored
32
.github/workflows/go.yml
vendored
@@ -14,36 +14,36 @@ jobs:
|
||||
test:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [macos-latest, ubuntu-latest]
|
||||
os:
|
||||
- macos-latest
|
||||
- ubuntu-24.04
|
||||
llvm: [18]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Update Homebrew
|
||||
# needed as long as LLVM 18 is still fresh
|
||||
if: matrix.llvm == 18 && startsWith(matrix.os, 'macos')
|
||||
run: brew update
|
||||
- name: Install LLVM ${{ matrix.llvm }} and bdw-gc
|
||||
- name: Install dependencies
|
||||
if: startsWith(matrix.os, 'macos')
|
||||
run: |
|
||||
HOMEBREW_NO_AUTO_UPDATE=1 brew install llvm@${{ matrix.llvm }} bdw-gc
|
||||
echo `brew --prefix llvm@${{ matrix.llvm }}`/bin >> $GITHUB_PATH
|
||||
- name: Install LLVM ${{ matrix.llvm }} and libgc-dev
|
||||
brew update
|
||||
brew install llvm@${{ matrix.llvm }} pkg-config bdw-gc openssl cjson sqlite python@3.12
|
||||
echo "$(brew --prefix llvm@${{ matrix.llvm }})/bin" >> $GITHUB_PATH
|
||||
|
||||
- name: Install dependencies
|
||||
if: startsWith(matrix.os, 'ubuntu')
|
||||
run: |
|
||||
echo "deb http://apt.llvm.org/$(lsb_release -cs)/ llvm-toolchain-$(lsb_release -cs)-${{ matrix.llvm }} main" | sudo tee /etc/apt/sources.list.d/llvm.list
|
||||
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y llvm-${{ matrix.llvm }}-dev clang-${{ matrix.llvm }} lld-${{ matrix.llvm }} pkg-config libgc-dev libcjson-dev libsqlite3-dev python3.11-dev
|
||||
echo /usr/lib/llvm-${{ matrix.llvm }}/bin >> $GITHUB_PATH
|
||||
|
||||
sudo apt-get install -y llvm-${{ matrix.llvm }}-dev clang-${{ matrix.llvm }} lld-${{ matrix.llvm }} pkg-config libgc-dev libssl-dev libcjson-dev libsqlite3-dev python3.12-dev
|
||||
echo "/usr/lib/llvm-${{ matrix.llvm }}/bin" >> $GITHUB_PATH
|
||||
|
||||
- name: Clang information
|
||||
run: |
|
||||
echo $PATH
|
||||
which clang
|
||||
clang --version
|
||||
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
@@ -62,19 +62,19 @@ jobs:
|
||||
|
||||
- name: Install
|
||||
run: go install ./...
|
||||
|
||||
|
||||
- name: LLGO tests
|
||||
if: matrix.os != 'ubuntu-latest'
|
||||
run: |
|
||||
echo "Test result on ${{ matrix.os }} with LLVM ${{ matrix.llvm }}" > result.md
|
||||
LLGOROOT=$PWD bash .github/workflows/test_llgo.sh
|
||||
|
||||
|
||||
- name: Test _demo and _pydemo
|
||||
run: |
|
||||
set +e
|
||||
LLGOROOT=$PWD bash .github/workflows/test_demo.sh
|
||||
exit 0
|
||||
|
||||
|
||||
- name: Show test result
|
||||
run: cat result.md
|
||||
|
||||
|
||||
2
.github/workflows/test_demo.sh
vendored
2
.github/workflows/test_demo.sh
vendored
@@ -8,7 +8,7 @@ for d in ./_demo/* ./_pydemo/*; do
|
||||
total=$((total+1))
|
||||
if [ -d "$d" ]; then
|
||||
echo "Testing $d"
|
||||
if ! llgo run -v "$d"; then
|
||||
if ! llgo run "$d"; then
|
||||
echo "FAIL"
|
||||
failed=$((failed+1))
|
||||
failed_cases="$failed_cases\n* :x: $d"
|
||||
|
||||
93
README.md
93
README.md
@@ -27,11 +27,13 @@ LLGo := Go + C + Python
|
||||
LLGo is compatible with C and Python through the language's **Application Binary Interface (ABI)**, while LLGo is compatible with Go through its **syntax (source code)**.
|
||||
|
||||
|
||||
## C standard libary support
|
||||
## C/C++ standard libary support
|
||||
|
||||
You can import a C standard library in LLGo!
|
||||
You can import a C/C++ standard library in LLGo!
|
||||
|
||||
* [c](https://pkg.go.dev/github.com/goplus/llgo/c)
|
||||
* [c/syscall](https://pkg.go.dev/github.com/goplus/llgo/c/syscall)
|
||||
* [c/sys](https://pkg.go.dev/github.com/goplus/llgo/c/sys)
|
||||
* [c/os](https://pkg.go.dev/github.com/goplus/llgo/c/os)
|
||||
* [c/math](https://pkg.go.dev/github.com/goplus/llgo/c/math)
|
||||
* [c/math/cmplx](https://pkg.go.dev/github.com/goplus/llgo/c/math/cmplx)
|
||||
@@ -40,6 +42,8 @@ You can import a C standard library in LLGo!
|
||||
* [c/pthread/sync](https://pkg.go.dev/github.com/goplus/llgo/c/pthread/sync)
|
||||
* [c/sync/atomic](https://pkg.go.dev/github.com/goplus/llgo/c/sync/atomic)
|
||||
* [c/time](https://pkg.go.dev/github.com/goplus/llgo/c/time)
|
||||
* [c/net](https://pkg.go.dev/github.com/goplus/llgo/c/net)
|
||||
* [cpp/std](https://pkg.go.dev/github.com/goplus/llgo/cpp/std)
|
||||
|
||||
Here is a simple example:
|
||||
|
||||
@@ -69,6 +73,45 @@ llgo run .
|
||||
```
|
||||
|
||||
|
||||
## How support C/C++ and Python
|
||||
|
||||
LLGo use `go:linkname` to link an extern symbol througth its ABI:
|
||||
|
||||
```go
|
||||
import _ "unsafe" // for go:linkname
|
||||
|
||||
//go:linkname Sqrt C.sqrt
|
||||
func Sqrt(x float64) float64
|
||||
```
|
||||
|
||||
You can directly integrate it into [your own code](_demo/linkname/linkname.go):
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import _ "unsafe" // for go:linkname
|
||||
|
||||
//go:linkname Sqrt C.sqrt
|
||||
func Sqrt(x float64) float64
|
||||
|
||||
func main() {
|
||||
println("sqrt(2) =", Sqrt(2))
|
||||
}
|
||||
```
|
||||
|
||||
Or put it into a package (see [c/math](c/math/math.go)):
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import "github.com/goplus/llgo/c/math"
|
||||
|
||||
func main() {
|
||||
println("sqrt(2) =", math.Sqrt(2))
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Python support
|
||||
|
||||
You can import a Python library in LLGo!
|
||||
@@ -171,12 +214,16 @@ The currently supported libraries include:
|
||||
* [c/bdwgc](https://pkg.go.dev/github.com/goplus/llgo/c/bdwgc)
|
||||
* [c/cjson](https://pkg.go.dev/github.com/goplus/llgo/c/cjson)
|
||||
* [c/clang](https://pkg.go.dev/github.com/goplus/llgo/c/clang)
|
||||
* [c/inih](https://pkg.go.dev/github.com/goplus/llgo/c/inih)
|
||||
* [c/libuv](https://pkg.go.dev/github.com/goplus/llgo/c/libuv)
|
||||
* [c/llama2](https://pkg.go.dev/github.com/goplus/llgo/c/llama2)
|
||||
* [c/lua](https://pkg.go.dev/github.com/goplus/llgo/c/lua)
|
||||
* [c/neco](https://pkg.go.dev/github.com/goplus/llgo/c/neco)
|
||||
* [c/openssl](https://pkg.go.dev/github.com/goplus/llgo/c/openssl)
|
||||
* [c/raylib](https://pkg.go.dev/github.com/goplus/llgo/c/raylib)
|
||||
* [c/sqlite](https://pkg.go.dev/github.com/goplus/llgo/c/sqlite)
|
||||
* [c/zlib](https://pkg.go.dev/github.com/goplus/llgo/c/zlib)
|
||||
* [cpp/inih](https://pkg.go.dev/github.com/goplus/llgo/cpp/inih)
|
||||
* [cpp/llvm](https://pkg.go.dev/github.com/goplus/llgo/cpp/llvm)
|
||||
|
||||
Here are some examples related to them:
|
||||
|
||||
@@ -197,7 +244,7 @@ All Go syntax (not including `cgo`) is already supported. Here are some examples
|
||||
* [goroutine](_demo/goroutine/goroutine.go): goroutine demo
|
||||
|
||||
|
||||
## Defer
|
||||
### Defer
|
||||
|
||||
LLGo `defer` does not support usage in loops. This is not a bug but a feature, because we think that using `defer` in a loop is a very unrecommended practice.
|
||||
|
||||
@@ -224,31 +271,55 @@ Here are the Go packages that can be imported correctly:
|
||||
* [math](https://pkg.go.dev/math)
|
||||
* [math/bits](https://pkg.go.dev/math/bits)
|
||||
* [math/cmplx](https://pkg.go.dev/math/cmplx)
|
||||
* [math/rand](https://pkg.go.dev/math/rand)
|
||||
* [errors](https://pkg.go.dev/errors)
|
||||
* [context](https://pkg.go.dev/context)
|
||||
* [io](https://pkg.go.dev/io)
|
||||
* [io/fs](https://pkg.go.dev/io/fs)
|
||||
* [log](https://pkg.go.dev/log)
|
||||
* [flag](https://pkg.go.dev/flag)
|
||||
* [sort](https://pkg.go.dev/sort)
|
||||
* [bytes](https://pkg.go.dev/bytes)
|
||||
* [bufio](https://pkg.go.dev/bufio)
|
||||
* [strings](https://pkg.go.dev/strings)
|
||||
* [strconv](https://pkg.go.dev/strconv)
|
||||
* [path](https://pkg.go.dev/path)
|
||||
* [path/filepath](https://pkg.go.dev/path/filepath)
|
||||
* [sync/atomic](https://pkg.go.dev/sync/atomic)
|
||||
* [sync](https://pkg.go.dev/sync) (partially)
|
||||
* [syscall](https://pkg.go.dev/syscall) (partially)
|
||||
* [errors](https://pkg.go.dev/errors) (partially)
|
||||
* [io](https://pkg.go.dev/io) (partially)
|
||||
* [io/fs](https://pkg.go.dev/io/fs) (partially)
|
||||
* [runtime](https://pkg.go.dev/runtime) (partially)
|
||||
* [os](https://pkg.go.dev/os) (partially)
|
||||
* [os/exec](https://pkg.go.dev/os/exec) (partially)
|
||||
* [fmt](https://pkg.go.dev/fmt) (partially)
|
||||
* [reflect](https://pkg.go.dev/reflect) (partially)
|
||||
* [time](https://pkg.go.dev/time) (partially)
|
||||
* [encoding/binary](https://pkg.go.dev/encoding/binary)
|
||||
* [encoding/hex](https://pkg.go.dev/encoding/hex)
|
||||
* [encoding/base32](https://pkg.go.dev/encoding/base32)
|
||||
* [encoding/base64](https://pkg.go.dev/encoding/base64)
|
||||
* [encoding/csv](https://pkg.go.dev/encoding/csv)
|
||||
* [hash](https://pkg.go.dev/hash)
|
||||
* [hash/adler32](https://pkg.go.dev/hash/adler32)
|
||||
* [hash/crc32](https://pkg.go.dev/hash/crc32) (partially)
|
||||
* [hash/crc64](https://pkg.go.dev/hash/crc64)
|
||||
* [crypto/md5](https://pkg.go.dev/crypto/md5)
|
||||
* [regexp](https://pkg.go.dev/regexp)
|
||||
* [regexp/syntax](https://pkg.go.dev/regexp/syntax)
|
||||
|
||||
|
||||
## Dependencies
|
||||
|
||||
- [Go 1.20+](https://go.dev) (build only)
|
||||
- [Go 1.20+](https://go.dev)
|
||||
- [LLVM 18](https://llvm.org)
|
||||
- [LLD 18](https://lld.llvm.org)
|
||||
- [Clang 18](https://clang.llvm.org)
|
||||
- [pkg-config 0.29+](https://www.freedesktop.org/wiki/Software/pkg-config/)
|
||||
- [bdwgc/libgc 8.0+](https://www.hboehm.info/gc/)
|
||||
- [OpenSSL 3.0+](https://www.openssl.org/)
|
||||
- [cJSON 1.7+](https://github.com/DaveGamble/cJSON) (optional, for [github.com/goplus/llgo/c/cjson](https://pkg.go.dev/github.com/goplus/llgo/c/cjson))
|
||||
- [SQLite 3](https://www.sqlite.org) (optional, for [github.com/goplus/llgo/c/sqlite](https://pkg.go.dev/github.com/goplus/llgo/c/sqlite))
|
||||
- [Python 3.11+](https://www.python.org) (optional, for [github.com/goplus/llgo/py](https://pkg.go.dev/github.com/goplus/llgo/py))
|
||||
- [Python 3.12+](https://www.python.org) (optional, for [github.com/goplus/llgo/py](https://pkg.go.dev/github.com/goplus/llgo/py))
|
||||
|
||||
## How to install
|
||||
|
||||
@@ -258,7 +329,7 @@ Follow these steps to generate the `llgo` command (its usage is the same as the
|
||||
|
||||
```sh
|
||||
brew update # execute if needed
|
||||
brew install llvm@18 pkg-config libgc
|
||||
brew install llvm@18 pkg-config bdw-gc openssl
|
||||
brew install cjson sqlite python@3.12 # optional
|
||||
export PATH=$(brew --prefix llvm@18)/bin:$PATH # you may want to add this to your shell RC file, e.g. ~/.zshrc
|
||||
go install -v github.com/goplus/llgo/cmd/llgo@latest
|
||||
@@ -270,7 +341,7 @@ go install -v github.com/goplus/llgo/cmd/llgo@latest
|
||||
echo "deb http://apt.llvm.org/$(lsb_release -cs)/ llvm-toolchain-$(lsb_release -cs)-18 main" | sudo tee /etc/apt/sources.list.d/llvm.list
|
||||
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||
sudo apt-get update # execute if needed
|
||||
sudo apt-get install -y llvm-18-dev clang-18 lld-18 pkg-config libgc-dev
|
||||
sudo apt-get install -y llvm-18-dev clang-18 lld-18 pkg-config libgc-dev libssl-dev
|
||||
sudo apt-get install -y libcjson-dev libsqlite3-dev python3.12-dev # optional
|
||||
export PATH=/usr/lib/llvm-18/bin:$PATH # you may want to add this to your shell RC file, e.g. ~/.bashrc
|
||||
go install -v github.com/goplus/llgo/cmd/llgo@latest
|
||||
|
||||
47
_cmptest/_bigsqrt2/sqrt2.go
Normal file
47
_cmptest/_bigsqrt2/sqrt2.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// We'll do computations with 200 bits of precision in the mantissa.
|
||||
const prec = 200
|
||||
|
||||
// Compute the square root of 2 using Newton's Method. We start with
|
||||
// an initial estimate for sqrt(2), and then iterate:
|
||||
// x_{n+1} = 1/2 * ( x_n + (2.0 / x_n) )
|
||||
|
||||
// Since Newton's Method doubles the number of correct digits at each
|
||||
// iteration, we need at least log_2(prec) steps.
|
||||
steps := int(math.Log2(prec))
|
||||
|
||||
// Initialize values we need for the computation.
|
||||
two := new(big.Float).SetPrec(prec).SetInt64(2)
|
||||
half := new(big.Float).SetPrec(prec).SetFloat64(0.5)
|
||||
|
||||
// Use 1 as the initial estimate.
|
||||
x := new(big.Float).SetPrec(prec).SetInt64(1)
|
||||
|
||||
// We use t as a temporary variable. There's no need to set its precision
|
||||
// since big.Float values with unset (== 0) precision automatically assume
|
||||
// the largest precision of the arguments when used as the result (receiver)
|
||||
// of a big.Float operation.
|
||||
t := new(big.Float)
|
||||
|
||||
// Iterate.
|
||||
for i := 0; i <= steps; i++ {
|
||||
t.Quo(two, x) // t = 2.0 / x_n
|
||||
t.Add(x, t) // t = x_n + (2.0 / x_n)
|
||||
x.Mul(half, t) // x_{n+1} = 0.5 * t
|
||||
}
|
||||
|
||||
// We can use the usual fmt.Printf verbs since big.Float implements fmt.Formatter
|
||||
fmt.Printf("sqrt(2) = %.50f\n", x)
|
||||
|
||||
// Print the error between 2 and x*x.
|
||||
t.Mul(x, x) // t = x*x
|
||||
fmt.Printf("error = %e\n", t.Sub(two, t))
|
||||
}
|
||||
16
_cmptest/_jsondemo/json.go
Normal file
16
_cmptest/_jsondemo/json.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := `{"name":"math","items":[{"name":"sqrt","sig":"(x, /)"},{"name":"pi"}]}`
|
||||
data := unsafe.Slice(unsafe.StringData(s), len(s))
|
||||
var v any
|
||||
json.Unmarshal(data, &v)
|
||||
b, _ := json.MarshalIndent(v, "", " ")
|
||||
fmt.Println(string(b))
|
||||
}
|
||||
@@ -13,7 +13,7 @@ func main() {
|
||||
select {
|
||||
case m := <-c:
|
||||
handle(m)
|
||||
case <-time.After(10 * time.Second):
|
||||
case <-time.After(time.Second / 10):
|
||||
fmt.Println("timed out")
|
||||
}
|
||||
}
|
||||
|
||||
48
_cmptest/base64demo/base64.go
Normal file
48
_cmptest/base64demo/base64.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/base32"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"log"
|
||||
)
|
||||
|
||||
func base64Demo() {
|
||||
msg := "Hello, 世界"
|
||||
encoded := base64.StdEncoding.EncodeToString([]byte(msg))
|
||||
fmt.Println(encoded)
|
||||
decoded, err := base64.StdEncoding.DecodeString(encoded)
|
||||
if err != nil {
|
||||
fmt.Println("decode error:", err)
|
||||
return
|
||||
}
|
||||
fmt.Println(string(decoded))
|
||||
}
|
||||
|
||||
func base32Demo() {
|
||||
str := "JBSWY3DPFQQHO33SNRSCC==="
|
||||
dst := make([]byte, base32.StdEncoding.DecodedLen(len(str)))
|
||||
n, err := base32.StdEncoding.Decode(dst, []byte(str))
|
||||
if err != nil {
|
||||
fmt.Println("decode error:", err)
|
||||
return
|
||||
}
|
||||
dst = dst[:n]
|
||||
fmt.Printf("%q\n", dst)
|
||||
}
|
||||
|
||||
func hexDemo() {
|
||||
const s = "48656c6c6f20476f7068657221"
|
||||
decoded, err := hex.DecodeString(s)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Printf("%s\n", decoded)
|
||||
|
||||
}
|
||||
func main() {
|
||||
base64Demo()
|
||||
base32Demo()
|
||||
hexDemo()
|
||||
}
|
||||
28
_cmptest/crcdemo/crc.go
Normal file
28
_cmptest/crcdemo/crc.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"hash/adler32"
|
||||
"hash/crc32"
|
||||
"hash/crc64"
|
||||
)
|
||||
|
||||
func crc64Demo() {
|
||||
crc := crc64.MakeTable(crc64.ECMA)
|
||||
fmt.Printf("%016x\n", crc64.Checksum([]byte("Hello world"), crc))
|
||||
}
|
||||
|
||||
func crc32Demo() {
|
||||
crc32q := crc32.MakeTable(crc32.IEEE)
|
||||
fmt.Printf("%08x\n", crc32.Checksum([]byte("Hello world"), crc32q))
|
||||
}
|
||||
|
||||
func adler32Demo() {
|
||||
fmt.Printf("%08x\n", adler32.Checksum([]byte("Hello world")))
|
||||
}
|
||||
|
||||
func main() {
|
||||
adler32Demo()
|
||||
crc32Demo()
|
||||
crc64Demo()
|
||||
}
|
||||
30
_cmptest/csvdemo/csv.go
Normal file
30
_cmptest/csvdemo/csv.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/csv"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
in := `first_name,last_name,username
|
||||
"Rob","Pike",rob
|
||||
Ken,Thompson,ken
|
||||
"Robert","Griesemer","gri"
|
||||
`
|
||||
r := csv.NewReader(strings.NewReader(in))
|
||||
|
||||
for {
|
||||
record, err := r.Read()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Println(record)
|
||||
}
|
||||
}
|
||||
20
_cmptest/envexpand/expand.go
Normal file
20
_cmptest/envexpand/expand.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
mapper := func(placeholderName string) string {
|
||||
switch placeholderName {
|
||||
case "DAY_PART":
|
||||
return "morning"
|
||||
case "NAME":
|
||||
return "Gopher"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
fmt.Println(os.Expand("Good ${DAY_PART}, $NAME!", mapper))
|
||||
}
|
||||
21
_cmptest/flagdemo/flagdemo.go
Normal file
21
_cmptest/flagdemo/flagdemo.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println("args:", os.Args[1:])
|
||||
if len(os.Args) == 1 {
|
||||
os.Args = []string{"flagdemo", "-cpu", "100"}
|
||||
}
|
||||
|
||||
verbose := flag.Bool("v", false, "verbose")
|
||||
cpu := flag.Int("cpu", 1, "cpu number")
|
||||
host := flag.String("host", ":8888", "host")
|
||||
flag.Parse()
|
||||
|
||||
fmt.Println("host:", *host, "cpu:", *cpu, "verbose:", *verbose)
|
||||
}
|
||||
14
_cmptest/md5demo/md5.go
Normal file
14
_cmptest/md5demo/md5.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
func main() {
|
||||
h := md5.New()
|
||||
io.WriteString(h, "The fog is getting thicker!")
|
||||
io.WriteString(h, "And Leon's getting laaarger!")
|
||||
fmt.Printf("%x", h.Sum(nil))
|
||||
}
|
||||
24
_cmptest/osexec/exec.go
Normal file
24
_cmptest/osexec/exec.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
|
||||
"github.com/goplus/llgo/xtool/env/llvm"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ls := "ls"
|
||||
if runtime.GOOS == "windows" {
|
||||
ls = "dir"
|
||||
}
|
||||
cmd := exec.Command(ls)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
cmd.Run()
|
||||
|
||||
dir := llvm.New("").BinDir()
|
||||
fmt.Println(dir)
|
||||
}
|
||||
30
_cmptest/osproc/exec.go
Normal file
30
_cmptest/osproc/exec.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ls := "ls"
|
||||
args := []string{ls, "-l"}
|
||||
if runtime.GOOS == "windows" {
|
||||
ls = "dir"
|
||||
args = []string{ls}
|
||||
}
|
||||
lspath, _ := exec.LookPath(ls)
|
||||
if lspath != "" {
|
||||
ls = lspath
|
||||
}
|
||||
proc, err := os.StartProcess(ls, args, &os.ProcAttr{
|
||||
Files: []*os.File{nil, os.Stdout, os.Stderr},
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Println("os.StartProcess error:", err)
|
||||
return
|
||||
}
|
||||
proc.Wait()
|
||||
fmt.Println("proc.Wait done")
|
||||
}
|
||||
26
_cmptest/pipedemo/pipe.go
Normal file
26
_cmptest/pipedemo/pipe.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
func main() {
|
||||
data := []byte("This is some data that needs to be stored in Body.")
|
||||
pr, pw := io.Pipe()
|
||||
go func() {
|
||||
defer pw.Close()
|
||||
if _, err := pw.Write(data); err != nil {
|
||||
fmt.Println("Error writing to pipe:", err)
|
||||
return
|
||||
}
|
||||
}()
|
||||
defer pr.Close()
|
||||
|
||||
readData, err := io.ReadAll(pr)
|
||||
if err != nil {
|
||||
fmt.Println("Error reading from Body:", err)
|
||||
return
|
||||
}
|
||||
fmt.Println("Body:", string(readData))
|
||||
}
|
||||
12
_cmptest/printfdemo/demo.go
Normal file
12
_cmptest/printfdemo/demo.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/goplus/llgo/xtool/nm"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sym := nm.Symbol{Name: "abc", Type: nm.Text}
|
||||
fmt.Printf("%016x %c %s\n", sym.Addr, sym.Type, sym.Name)
|
||||
}
|
||||
25
_cmptest/readfiledemo/readf.go
Normal file
25
_cmptest/readfiledemo/readf.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fileName := "err.log"
|
||||
os.WriteFile(fileName, []byte("123"), 0644)
|
||||
|
||||
_, err := os.Stat(fileName)
|
||||
if os.IsNotExist(err) {
|
||||
fmt.Fprintf(os.Stderr, "File %s not found\n", fileName)
|
||||
return
|
||||
}
|
||||
|
||||
data, err := os.ReadFile(fileName)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "ReadFile: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("%s\n", data)
|
||||
}
|
||||
11
_cmptest/regexdemo/regex.go
Normal file
11
_cmptest/regexdemo/regex.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/goplus/llgo/xtool/env"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(env.ExpandEnv("$(pkg-config --libs bdw-gc)"))
|
||||
}
|
||||
@@ -1,7 +1,12 @@
|
||||
package main
|
||||
|
||||
import "strconv"
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
println(strconv.Itoa(-123))
|
||||
fmt.Println(strconv.Itoa(-123))
|
||||
fmt.Println(strings.Split("abc,def,123", ","))
|
||||
}
|
||||
|
||||
18
_demo/cmd5demo/md5.go
Normal file
18
_demo/cmd5demo/md5.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"unsafe"
|
||||
|
||||
"github.com/goplus/llgo/c/openssl"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var md5 openssl.MD5_CTX
|
||||
var h = make([]byte, openssl.MD5_LBLOCK)
|
||||
md5.Init()
|
||||
md5.UpdateString("The fog is getting thicker!")
|
||||
md5.UpdateString("And Leon's getting laaarger!")
|
||||
md5.Final(unsafe.SliceData(h))
|
||||
fmt.Printf("%x", h)
|
||||
}
|
||||
26
_demo/crand/rand.go
Normal file
26
_demo/crand/rand.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/goplus/llgo/c"
|
||||
"github.com/goplus/llgo/c/math/rand"
|
||||
"github.com/goplus/llgo/c/time"
|
||||
)
|
||||
|
||||
func fastrand64() uint64 {
|
||||
v1 := uint64(rand.Random())
|
||||
v2 := uint64(rand.Random())
|
||||
return v1 ^ (v2 << 32)
|
||||
}
|
||||
|
||||
func main() {
|
||||
rand.Srand(c.Uint(time.Time(nil)))
|
||||
fmt.Printf("%x\n", rand.Rand())
|
||||
fmt.Printf("%x\n", rand.Rand())
|
||||
|
||||
rand.Srandom(c.Uint(time.Time(nil)))
|
||||
fmt.Printf("%x\n", rand.Random())
|
||||
fmt.Printf("%x\n", rand.Random())
|
||||
fmt.Printf("%x\n", fastrand64())
|
||||
}
|
||||
68
_demo/cshademo/sha.go
Normal file
68
_demo/cshademo/sha.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"unsafe"
|
||||
|
||||
"github.com/goplus/llgo/c/openssl"
|
||||
)
|
||||
|
||||
func main() {
|
||||
str := "His money is twice tainted:"
|
||||
|
||||
var sha1 openssl.SHA_CTX
|
||||
sha1.Init()
|
||||
sha1.UpdateString(str)
|
||||
|
||||
h1 := make([]byte, openssl.SHA_DIGEST_LENGTH)
|
||||
sha1.Final(unsafe.SliceData(h1))
|
||||
fmt.Printf("%x\n", h1)
|
||||
|
||||
h2 := make([]byte, openssl.SHA_DIGEST_LENGTH)
|
||||
openssl.SHA1String(str, unsafe.SliceData(h2))
|
||||
fmt.Printf("%x\n", h2)
|
||||
|
||||
var sha256 openssl.SHA256_CTX
|
||||
sha256.Init()
|
||||
sha256.UpdateString(str)
|
||||
h3 := make([]byte, openssl.SHA256_DIGEST_LENGTH)
|
||||
sha256.Final(unsafe.SliceData(h3))
|
||||
fmt.Printf("%x\n", h3)
|
||||
|
||||
h4 := make([]byte, openssl.SHA256_DIGEST_LENGTH)
|
||||
openssl.SHA256String(str, unsafe.SliceData(h4))
|
||||
fmt.Printf("%x\n", h4)
|
||||
|
||||
var sha512 openssl.SHA512_CTX
|
||||
sha512.Init()
|
||||
sha512.UpdateString("His money is twice tainted:")
|
||||
|
||||
h5 := make([]byte, openssl.SHA512_DIGEST_LENGTH)
|
||||
sha512.Final(unsafe.SliceData(h5))
|
||||
fmt.Printf("%x\n", h5)
|
||||
|
||||
h6 := make([]byte, openssl.SHA512_DIGEST_LENGTH)
|
||||
openssl.SHA512String(str, unsafe.SliceData(h6))
|
||||
fmt.Printf("%x\n", h6)
|
||||
|
||||
var sha224 openssl.SHA224_CTX
|
||||
sha224.Init()
|
||||
sha224.UpdateString(str)
|
||||
|
||||
h7 := make([]byte, openssl.SHA224_DIGEST_LENGTH)
|
||||
sha224.Final(unsafe.SliceData(h7))
|
||||
fmt.Printf("%x\n", h7)
|
||||
h8 := make([]byte, openssl.SHA224_DIGEST_LENGTH)
|
||||
openssl.SHA224String(str, unsafe.SliceData(h8))
|
||||
fmt.Printf("%x\n", h8)
|
||||
|
||||
var sha384 openssl.SHA384_CTX
|
||||
sha384.Init()
|
||||
sha384.UpdateString(str)
|
||||
h9 := make([]byte, openssl.SHA384_DIGEST_LENGTH)
|
||||
sha384.Final(unsafe.SliceData(h9))
|
||||
fmt.Printf("%x\n", h9)
|
||||
h10 := make([]byte, openssl.SHA384_DIGEST_LENGTH)
|
||||
openssl.SHA384String(str, unsafe.SliceData(h10))
|
||||
fmt.Printf("%x\n", h10)
|
||||
}
|
||||
77
_demo/fcntl/fcntl.go
Normal file
77
_demo/fcntl/fcntl.go
Normal file
@@ -0,0 +1,77 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/goplus/llgo/c"
|
||||
"github.com/goplus/llgo/c/os"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
filename := c.Str("testfile.txt")
|
||||
data := c.Str("Hello, os!")
|
||||
var buffer [20]c.Char
|
||||
|
||||
// Open a file, O_CREAT|O_WRONLY|O_TRUNC means create, write only, or clear the file
|
||||
fd := os.Open(filename, os.O_CREAT|os.O_WRONLY|os.O_TRUNC, 0644)
|
||||
if fd == -1 {
|
||||
c.Printf(c.Str("open error\n"))
|
||||
return
|
||||
}
|
||||
|
||||
// Writing data to a file
|
||||
bytesWritten := os.Write(fd, c.Pointer(data), c.Strlen(data))
|
||||
if bytesWritten == -1 {
|
||||
c.Printf(c.Str("write error\n"))
|
||||
os.Close(fd)
|
||||
return
|
||||
}
|
||||
c.Printf(c.Str("Written %ld bytes to %s\n"), bytesWritten, filename)
|
||||
|
||||
// Get file status flags
|
||||
flags := os.Fcntl(fd, os.F_GETFL)
|
||||
if flags == -1 {
|
||||
c.Printf(c.Str("os error\n"))
|
||||
os.Close(fd)
|
||||
return
|
||||
}
|
||||
c.Printf(c.Str("File flags: %d\n"), flags)
|
||||
|
||||
// Set the file status flag to non-blocking mode
|
||||
if os.Fcntl(fd, os.F_SETFL, flags|os.O_NONBLOCK) == -1 {
|
||||
c.Printf(c.Str("os error\n"))
|
||||
os.Close(fd)
|
||||
return
|
||||
}
|
||||
c.Printf(c.Str("set file status successfully\n"))
|
||||
|
||||
|
||||
|
||||
c.Printf(c.Str("111"))
|
||||
// Close file
|
||||
os.Close(fd)
|
||||
|
||||
// Reopen the file, O_RDONLY means read-only
|
||||
fd = os.Open(filename, os.O_RDONLY)
|
||||
if fd == -1 {
|
||||
c.Printf(c.Str("open error\n"))
|
||||
return
|
||||
}
|
||||
|
||||
// Reading data from a file
|
||||
// &buffer[:][0]
|
||||
// unsafe.SliceData(buffer[:])
|
||||
bytesRead := os.Read(fd, c.Pointer(unsafe.SliceData(buffer[:])), unsafe.Sizeof(buffer)-1)
|
||||
if bytesRead == -1 {
|
||||
c.Printf(c.Str("read error\n"))
|
||||
os.Close(fd)
|
||||
return
|
||||
}
|
||||
|
||||
// Ensure that the buffer is null-terminated
|
||||
buffer[bytesRead] = c.Char(0)
|
||||
c.Printf(c.Str("Read %ld bytes: %s\n"), bytesRead, &buffer[0])
|
||||
|
||||
// Close file
|
||||
os.Close(fd)
|
||||
}
|
||||
10
_demo/linkname/linkname.go
Normal file
10
_demo/linkname/linkname.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package main
|
||||
|
||||
import _ "unsafe" // for go:linkname
|
||||
|
||||
//go:linkname Sqrt C.sqrt
|
||||
func Sqrt(x float64) float64
|
||||
|
||||
func main() {
|
||||
println("sqrt(2) =", Sqrt(2))
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"github.com/goplus/llgo/c"
|
||||
"github.com/goplus/llgo/c/llama2"
|
||||
"github.com/goplus/llgo/c/time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
@@ -11,7 +12,7 @@ func main() {
|
||||
var tokenizerPath *c.Char = c.Str("tokenizer.bin")
|
||||
var temperature, topp c.Float = 1.0, 0.9
|
||||
var steps c.Int = 256
|
||||
var rngSeed uint64 = uint64(c.Time(nil))
|
||||
var rngSeed uint64 = uint64(time.Time(nil))
|
||||
|
||||
loop: // parse command line arguments
|
||||
for {
|
||||
|
||||
20
_demo/netdbdemo/netdb.go
Normal file
20
_demo/netdbdemo/netdb.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/goplus/llgo/c"
|
||||
"github.com/goplus/llgo/c/net"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var hints net.AddrInfo
|
||||
hints.Family = net.AF_UNSPEC
|
||||
hints.SockType = net.SOCK_STREAM
|
||||
|
||||
host := "httpbin.org"
|
||||
port := "80"
|
||||
|
||||
var result *net.AddrInfo
|
||||
c.Printf(c.Str("%d\n"), net.Getaddrinfo(c.Str(host), c.Str(port), &hints, &result))
|
||||
|
||||
c.Printf(c.Str("%d\n"), net.Freeaddrinfo(result))
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/goplus/llgo/c"
|
||||
"github.com/goplus/llgo/c/math/rand"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var s c.Uint = 6
|
||||
rand.Srand(s)
|
||||
rr := rand.RandR(&s)
|
||||
r := rand.Rand()
|
||||
println("r:", r)
|
||||
println("rr:", rr)
|
||||
}
|
||||
12
_demo/randdemo/rand.go
Normal file
12
_demo/randdemo/rand.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(rand.Intn(100))
|
||||
fmt.Println(rand.Intn(100))
|
||||
fmt.Println(rand.Intn(100))
|
||||
}
|
||||
@@ -4,27 +4,27 @@ import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/goplus/llgo/c"
|
||||
"github.com/goplus/llgo/c/net"
|
||||
"github.com/goplus/llgo/c/os"
|
||||
"github.com/goplus/llgo/c/socket"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sockfd := socket.Socket(socket.AF_INET, socket.SOCK_STREAM, 0)
|
||||
sockfd := net.Socket(net.AF_INET, net.SOCK_STREAM, 0)
|
||||
msg := c.Str("Hello, World!")
|
||||
defer os.Close(sockfd)
|
||||
|
||||
server := socket.GetHostByName(c.Str("localhost"))
|
||||
server := net.GetHostByName(c.Str("localhost"))
|
||||
if server == nil {
|
||||
c.Perror(c.Str("hostname get error"))
|
||||
return
|
||||
}
|
||||
|
||||
servAddr := &socket.SockaddrIn{}
|
||||
servAddr.Family = socket.AF_INET
|
||||
servAddr.Port = socket.Htons(uint16(1234))
|
||||
servAddr := &net.SockaddrIn{}
|
||||
servAddr.Family = net.AF_INET
|
||||
servAddr.Port = net.Htons(uint16(1234))
|
||||
c.Memcpy(unsafe.Pointer(&servAddr.Addr.Addr), unsafe.Pointer(*server.AddrList), uintptr(server.Length))
|
||||
|
||||
if res := socket.Connect(sockfd, (*socket.SockAddr)(unsafe.Pointer(servAddr)), c.Uint(16)); res < 0 {
|
||||
if res := net.Connect(sockfd, (*net.SockAddr)(unsafe.Pointer(servAddr)), c.Uint(16)); res < 0 {
|
||||
c.Perror(c.Str("connect error"))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -4,36 +4,36 @@ import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/goplus/llgo/c"
|
||||
"github.com/goplus/llgo/c/net"
|
||||
"github.com/goplus/llgo/c/os"
|
||||
"github.com/goplus/llgo/c/socket"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var buffer [256]c.Char
|
||||
|
||||
sockfd := socket.Socket(socket.AF_INET, socket.SOCK_STREAM, 0)
|
||||
sockfd := net.Socket(net.AF_INET, net.SOCK_STREAM, 0)
|
||||
defer os.Close(sockfd)
|
||||
|
||||
servAddr := &socket.SockaddrIn{
|
||||
Family: socket.AF_INET,
|
||||
Port: socket.Htons(uint16(1234)),
|
||||
Addr: socket.InAddr{Addr: 0x00000000},
|
||||
servAddr := &net.SockaddrIn{
|
||||
Family: net.AF_INET,
|
||||
Port: net.Htons(uint16(1234)),
|
||||
Addr: net.InAddr{Addr: 0x00000000},
|
||||
Zero: [8]c.Char{0, 0, 0, 0, 0, 0, 0, 0},
|
||||
}
|
||||
if res := socket.Bind(sockfd, servAddr, c.Uint(unsafe.Sizeof(*servAddr))); res < 0 {
|
||||
if res := net.Bind(sockfd, servAddr, c.Uint(unsafe.Sizeof(*servAddr))); res < 0 {
|
||||
c.Perror(c.Str("bind error"))
|
||||
return
|
||||
}
|
||||
|
||||
if socket.Listen(sockfd, 5) < 0 {
|
||||
if net.Listen(sockfd, 5) < 0 {
|
||||
c.Printf(c.Str("listen error"))
|
||||
return
|
||||
}
|
||||
c.Printf(c.Str("Listening on port 1234...\n"))
|
||||
|
||||
cliAddr, clilen := &socket.SockaddrIn{}, c.Uint(unsafe.Sizeof(servAddr))
|
||||
cliAddr, clilen := &net.SockaddrIn{}, c.Uint(unsafe.Sizeof(servAddr))
|
||||
|
||||
newsockfd := socket.Accept(sockfd, cliAddr, &clilen)
|
||||
newsockfd := net.Accept(sockfd, cliAddr, &clilen)
|
||||
defer os.Close(newsockfd)
|
||||
c.Printf(c.Str("Connection accepted."))
|
||||
|
||||
|
||||
4
c/c.go
4
c/c.go
@@ -28,6 +28,7 @@ const (
|
||||
)
|
||||
|
||||
type (
|
||||
Void = [0]byte
|
||||
Char = int8
|
||||
Float = float32
|
||||
Double = float64
|
||||
@@ -226,9 +227,6 @@ func Perror(s *Char)
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
//go:linkname Time C.time
|
||||
func Time(*int32) int32
|
||||
|
||||
//go:linkname Usleep C.usleep
|
||||
func Usleep(useconds Uint) Int
|
||||
|
||||
|
||||
@@ -22,6 +22,22 @@ func main() {
|
||||
|
||||
mod.SetItem(c.Str("items"), syms)
|
||||
|
||||
c.Printf(c.Str("%s\n"), mod.CStr())
|
||||
cstr := mod.CStr()
|
||||
str := c.GoString(cstr)
|
||||
c.Printf(c.Str("%s\n"), cstr)
|
||||
cjson.FreeCStr(cstr)
|
||||
|
||||
mod.Delete()
|
||||
|
||||
cjsonLoad(str)
|
||||
}
|
||||
|
||||
func cjsonLoad(str string) {
|
||||
mod := cjson.ParseString(str)
|
||||
|
||||
cstr := mod.Print()
|
||||
c.Printf(c.Str("%s\n"), cstr)
|
||||
cjson.FreeCStr(cstr)
|
||||
|
||||
mod.Delete()
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
package cjson
|
||||
|
||||
import (
|
||||
_ "unsafe"
|
||||
"unsafe"
|
||||
|
||||
"github.com/goplus/llgo/c"
|
||||
)
|
||||
@@ -31,6 +31,20 @@ type JSON struct {
|
||||
Unused [0]byte
|
||||
}
|
||||
|
||||
//go:linkname Parse C.cJSON_Parse
|
||||
func Parse(value *c.Char) *JSON
|
||||
|
||||
//go:linkname ParseWithLength C.cJSON_ParseWithLength
|
||||
func ParseWithLength(value *byte, valueLength uintptr) *JSON
|
||||
|
||||
func ParseBytes(value []byte) *JSON {
|
||||
return ParseWithLength(unsafe.SliceData(value), uintptr(len(value)))
|
||||
}
|
||||
|
||||
func ParseString(value string) *JSON {
|
||||
return ParseWithLength(unsafe.StringData(value), uintptr(len(value)))
|
||||
}
|
||||
|
||||
//go:linkname Null C.cJSON_CreateNull
|
||||
func Null() *JSON
|
||||
|
||||
@@ -119,3 +133,21 @@ func (o *JSON) PrintUnformatted() *c.Char { return nil }
|
||||
//
|
||||
// llgo:link (*JSON).PrintBuffered C.cJSON_PrintBuffered
|
||||
func (o *JSON) PrintBuffered(prebuffer c.Int, fmt c.Int) *c.Char { return nil }
|
||||
|
||||
// llgo:link (*JSON).GetObjectItemCaseSensitive C.cJSON_GetObjectItemCaseSensitive
|
||||
func (o *JSON) GetObjectItemCaseSensitive(key *c.Char) *JSON { return nil }
|
||||
|
||||
// llgo:link (*JSON).GetArraySize C.cJSON_GetArraySize
|
||||
func (o *JSON) GetArraySize() c.Int { return 0 }
|
||||
|
||||
// llgo:link (*JSON).GetArrayItem C.cJSON_GetArrayItem
|
||||
func (o *JSON) GetArrayItem(index c.Int) *JSON { return nil }
|
||||
|
||||
// llgo:link (*JSON).GetStringValue C.cJSON_GetStringValue
|
||||
func (o *JSON) GetStringValue() *c.Char { return nil }
|
||||
|
||||
//go:linkname Free C.cJSON_free
|
||||
func Free(ptr unsafe.Pointer)
|
||||
|
||||
//go:linkname FreeCStr C.cJSON_free
|
||||
func FreeCStr(*c.Char)
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/goplus/llgo/c"
|
||||
"github.com/goplus/llgo/c/clang"
|
||||
)
|
||||
@@ -13,6 +16,7 @@ func visit(cursor, parent clang.Cursor, clientData c.Pointer) clang.ChildVisitRe
|
||||
|
||||
func printAST(cursor clang.Cursor, depth c.Uint) {
|
||||
cursorKind := cursor.Kind.String()
|
||||
|
||||
cursorSpelling := cursor.String()
|
||||
|
||||
for i := c.Uint(0); i < depth; i++ {
|
||||
@@ -28,9 +32,16 @@ func printAST(cursor clang.Cursor, depth c.Uint) {
|
||||
}
|
||||
|
||||
func main() {
|
||||
if c.Argc != 2 {
|
||||
fmt.Fprintln(os.Stderr, "Usage: castdump <headerFile>")
|
||||
return
|
||||
}
|
||||
sourceFile := *c.Advance(c.Argv, 1)
|
||||
|
||||
index := clang.CreateIndex(0, 0)
|
||||
|
||||
unit := index.ParseTranslationUnit(
|
||||
c.Str("todo"),
|
||||
sourceFile,
|
||||
nil, 0,
|
||||
nil, 0,
|
||||
clang.TranslationUnit_None,
|
||||
@@ -42,6 +53,7 @@ func main() {
|
||||
}
|
||||
|
||||
cursor := unit.Cursor()
|
||||
|
||||
printAST(cursor, 0)
|
||||
|
||||
unit.Dispose()
|
||||
|
||||
131
c/clang/_demo/symboldump/symboldump.go
Normal file
131
c/clang/_demo/symboldump/symboldump.go
Normal file
@@ -0,0 +1,131 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"unsafe"
|
||||
|
||||
"github.com/goplus/llgo/c"
|
||||
"github.com/goplus/llgo/c/clang"
|
||||
)
|
||||
|
||||
type Context struct {
|
||||
namespaceName string
|
||||
className string
|
||||
}
|
||||
|
||||
func newContext() *Context {
|
||||
return &Context{}
|
||||
}
|
||||
|
||||
func (c *Context) setNamespaceName(name string) {
|
||||
c.namespaceName = name
|
||||
}
|
||||
|
||||
func (c *Context) setClassName(name string) {
|
||||
c.className = name
|
||||
}
|
||||
|
||||
var context = newContext()
|
||||
|
||||
func print_cursor_info(cursor clang.Cursor) {
|
||||
loc := cursor.Location()
|
||||
var file clang.File
|
||||
var line, column c.Uint
|
||||
|
||||
loc.SpellingLocation(&file, &line, &column, nil)
|
||||
filename := file.FileName()
|
||||
|
||||
c.Printf(c.Str("%s:%d:%d\n"), filename.CStr(), line, column)
|
||||
|
||||
cursorStr := cursor.String()
|
||||
symbol := cursor.Mangling()
|
||||
defer symbol.Dispose()
|
||||
defer cursorStr.Dispose()
|
||||
defer filename.Dispose()
|
||||
|
||||
if context.namespaceName != "" && context.className != "" {
|
||||
fmt.Printf("%s:%s:", context.namespaceName, context.className)
|
||||
} else if context.namespaceName != "" {
|
||||
fmt.Printf("%s:", context.namespaceName)
|
||||
}
|
||||
c.Printf(c.Str("%s\n"), cursorStr.CStr())
|
||||
|
||||
if cursor.Kind == clang.CXXMethod || cursor.Kind == clang.FunctionDecl {
|
||||
c.Printf(c.Str("symbol:%s\n"), symbol.CStr())
|
||||
|
||||
typeStr := cursor.ResultType().String()
|
||||
defer typeStr.Dispose()
|
||||
c.Printf(c.Str("Return Type: %s\n"), typeStr.CStr())
|
||||
c.Printf(c.Str("Parameters(%d): ( "), cursor.NumArguments())
|
||||
|
||||
for i := 0; i < int(cursor.NumArguments()); i++ {
|
||||
argCurSor := cursor.Argument(c.Uint(i))
|
||||
argType := argCurSor.Type().String()
|
||||
argName := argCurSor.String()
|
||||
c.Printf(c.Str("%s %s"), argType.CStr(), argName.CStr())
|
||||
if i < int(cursor.NumArguments())-1 {
|
||||
c.Printf(c.Str(", "))
|
||||
}
|
||||
|
||||
argType.Dispose()
|
||||
argName.Dispose()
|
||||
}
|
||||
|
||||
c.Printf(c.Str(" )\n"))
|
||||
println("--------------------------------")
|
||||
}
|
||||
}
|
||||
|
||||
func visit(cursor, parent clang.Cursor, clientData c.Pointer) clang.ChildVisitResult {
|
||||
if cursor.Kind == clang.Namespace {
|
||||
nameStr := cursor.String()
|
||||
context.setNamespaceName(c.GoString(nameStr.CStr()))
|
||||
clang.VisitChildren(cursor, visit, nil)
|
||||
context.setNamespaceName("")
|
||||
} else if cursor.Kind == clang.ClassDecl {
|
||||
nameStr := cursor.String()
|
||||
context.setClassName(c.GoString(nameStr.CStr()))
|
||||
clang.VisitChildren(cursor, visit, nil)
|
||||
context.setClassName("")
|
||||
} else if cursor.Kind == clang.CXXMethod || cursor.Kind == clang.FunctionDecl {
|
||||
print_cursor_info(cursor)
|
||||
}
|
||||
|
||||
return clang.ChildVisit_Continue
|
||||
}
|
||||
|
||||
func parse(filename *c.Char) {
|
||||
index := clang.CreateIndex(0, 0)
|
||||
args := make([]*c.Char, 3)
|
||||
args[0] = c.Str("-x")
|
||||
args[1] = c.Str("c++")
|
||||
args[2] = c.Str("-std=c++11")
|
||||
unit := index.ParseTranslationUnit(
|
||||
filename,
|
||||
unsafe.SliceData(args), 3,
|
||||
nil, 0,
|
||||
clang.TranslationUnit_None,
|
||||
)
|
||||
|
||||
if unit == nil {
|
||||
println("Unable to parse translation unit. Quitting.")
|
||||
c.Exit(1)
|
||||
}
|
||||
|
||||
cursor := unit.Cursor()
|
||||
|
||||
clang.VisitChildren(cursor, visit, nil)
|
||||
unit.Dispose()
|
||||
index.Dispose()
|
||||
}
|
||||
|
||||
func main() {
|
||||
if c.Argc != 2 {
|
||||
fmt.Fprintln(os.Stderr, "Usage: <C++ header file>\n")
|
||||
return
|
||||
} else {
|
||||
sourceFile := *c.Advance(c.Argv, 1)
|
||||
parse(sourceFile)
|
||||
}
|
||||
}
|
||||
50
c/clang/_wrap/cursor.cpp
Normal file
50
c/clang/_wrap/cursor.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
#include <clang-c/Index.h>
|
||||
#include <stdio.h>
|
||||
|
||||
typedef enum CXChildVisitResult (*wrap_CXCursorVisitor)(CXCursor *cursor, CXCursor *parent, CXClientData client_data);
|
||||
|
||||
typedef struct {
|
||||
CXClientData data;
|
||||
wrap_CXCursorVisitor visitor;
|
||||
} wrap_data;
|
||||
|
||||
CXChildVisitResult wrap_visitor(CXCursor cursor, CXCursor parent, CXClientData data) {
|
||||
wrap_data *d = (wrap_data *)(data);
|
||||
return d->visitor(&cursor, &parent, d->data);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
CXString wrap_clang_getCursorSpelling(CXCursor *cur) { return clang_getCursorSpelling(*cur); }
|
||||
|
||||
CXString wrap_clang_Cursor_getMangling(CXCursor *cur) { return clang_Cursor_getMangling(*cur); }
|
||||
|
||||
int wrap_clang_Cursor_getNumArguments(CXCursor *cur) { return clang_Cursor_getNumArguments(*cur); }
|
||||
|
||||
void wrap_clang_Cursor_getArgument(CXCursor *C, unsigned i, CXCursor *argCur) {
|
||||
*argCur = clang_Cursor_getArgument(*C, i);
|
||||
}
|
||||
|
||||
void wrap_clang_getTranslationUnitCursor(CXTranslationUnit uint, CXCursor *cur) {
|
||||
*cur = clang_getTranslationUnitCursor(uint);
|
||||
}
|
||||
|
||||
void wrap_clang_getCursorType(CXCursor *cur, CXType *typ) { *typ = clang_getCursorType(*cur); }
|
||||
|
||||
void wrap_clang_getCursorResultType(CXCursor *cur, CXType *typ) { *typ = clang_getCursorResultType(*cur); }
|
||||
|
||||
CXString wrap_clang_getTypeSpelling(CXType *typ) { return clang_getTypeSpelling(*typ); }
|
||||
|
||||
void wrap_clang_getCursorLocation(CXCursor *cur, CXSourceLocation *loc) { *loc = clang_getCursorLocation(*cur); }
|
||||
|
||||
void wrap_clang_getSpellingLocation(CXSourceLocation *loc, CXFile *file, unsigned *line, unsigned *column,
|
||||
unsigned *offset) {
|
||||
clang_getSpellingLocation(*loc, file, line, column, offset);
|
||||
}
|
||||
|
||||
unsigned wrap_clang_visitChildren(CXCursor *parent, wrap_CXCursorVisitor visitor, CXClientData client_data) {
|
||||
wrap_data data = {client_data, visitor};
|
||||
return clang_visitChildren(*parent, wrap_visitor, CXClientData(&data));
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
7
c/clang/_wrap/llgo_check.cpp
Normal file
7
c/clang/_wrap/llgo_check.cpp
Normal file
@@ -0,0 +1,7 @@
|
||||
#include <stdio.h>
|
||||
#include <clang-c/Index.h>
|
||||
|
||||
int main() {
|
||||
printf("sizeof(clang.Cursor) = %lu\n", sizeof(CXCursor));
|
||||
return 0;
|
||||
}
|
||||
16
c/clang/_wrap/llgo_check.go
Normal file
16
c/clang/_wrap/llgo_check.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/goplus/llgo/c"
|
||||
"github.com/goplus/llgo/c/clang"
|
||||
)
|
||||
|
||||
const (
|
||||
LLGoCFlags = "-I$(llvm-config --includedir)"
|
||||
)
|
||||
|
||||
func main() {
|
||||
c.Printf(c.Str("sizeof(clang.Cursor) = %lu\n"), unsafe.Sizeof(clang.Cursor{}))
|
||||
}
|
||||
@@ -38,13 +38,13 @@ type String struct {
|
||||
/**
|
||||
* Retrieve the character data associated with the given string.
|
||||
*/
|
||||
// llgo:link C.clang_getCString
|
||||
// llgo:link String.CStr C.clang_getCString
|
||||
func (String) CStr() *c.Char { return nil }
|
||||
|
||||
/**
|
||||
* Free the given string.
|
||||
*/
|
||||
// llgo:link C.clang_disposeString
|
||||
// llgo:link String.Dispose C.clang_disposeString
|
||||
func (String) Dispose() {}
|
||||
|
||||
type StringSet struct {
|
||||
@@ -55,5 +55,5 @@ type StringSet struct {
|
||||
/**
|
||||
* Free the given string set.
|
||||
*/
|
||||
// llgo:link C.clang_disposeStringSet
|
||||
// llgo:link (*StringSet).Dispose C.clang_disposeStringSet
|
||||
func (*StringSet) Dispose() {}
|
||||
|
||||
1280
c/clang/clang.go
1280
c/clang/clang.go
File diff suppressed because it is too large
Load Diff
44
c/libuv/README.md
Normal file
44
c/libuv/README.md
Normal file
@@ -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 <demo-directory> # eg. cd _demo/sqlitedemo
|
||||
llgo run .
|
||||
```
|
||||
97
c/libuv/_demo/async_fs/async_fs.go
Normal file
97
c/libuv/_demo/async_fs/async_fs.go
Normal file
@@ -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.Errno(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.File(libuv.FsGetResult(req)), &iov, 1, -1, onRead)
|
||||
if readRes != 0 {
|
||||
c.Printf(c.Str("Error in FsRead: %s (code: %d)\n"), libuv.Strerror(libuv.Errno(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.Errno(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.File(libuv.FsGetResult(&openReq)), onClose)
|
||||
if closeRes != 0 {
|
||||
// Print the content
|
||||
c.Printf(c.Str("Error in FsClose: %s (code: %d)\n"), libuv.Strerror(libuv.Errno(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.Errno(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)
|
||||
}
|
||||
1
c/libuv/_demo/async_fs/example.txt
Executable file
1
c/libuv/_demo/async_fs/example.txt
Executable file
@@ -0,0 +1 @@
|
||||
123
|
||||
120
c/libuv/_demo/echo_server/echo_server.go
Normal file
120
c/libuv/_demo/echo_server/echo_server.go
Normal file
@@ -0,0 +1,120 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/goplus/llgo/c"
|
||||
"github.com/goplus/llgo/c/libuv"
|
||||
"github.com/goplus/llgo/c/net"
|
||||
)
|
||||
|
||||
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 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)
|
||||
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)
|
||||
res := (*libuv.Stream)(&server).Listen(DEFAULT_BACKLOG, OnNewConnection)
|
||||
if res != 0 {
|
||||
c.Fprintf(c.Stderr, c.Str("Listen error: %s\n"), libuv.Strerror((libuv.Errno(res))))
|
||||
return
|
||||
}
|
||||
|
||||
// Start listening for incoming connections
|
||||
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((libuv.Errno(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((libuv.Errno)(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(libuv.Errno(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)
|
||||
}
|
||||
}
|
||||
118
c/libuv/error.go
Normal file
118
c/libuv/error.go
Normal file
@@ -0,0 +1,118 @@
|
||||
package libuv
|
||||
|
||||
import (
|
||||
_ "unsafe"
|
||||
|
||||
"github.com/goplus/llgo/c"
|
||||
"github.com/goplus/llgo/c/net"
|
||||
"github.com/goplus/llgo/c/syscall"
|
||||
)
|
||||
|
||||
const (
|
||||
E2BIG = Errno(syscall.E2BIG)
|
||||
EACCES = Errno(syscall.EACCES)
|
||||
EADDRINUSE = Errno(syscall.EADDRINUSE)
|
||||
EADDRNOTAVAIL = Errno(syscall.EADDRNOTAVAIL)
|
||||
EAFNOSUPPORT = Errno(syscall.EAFNOSUPPORT)
|
||||
EAGAIN = Errno(syscall.EAGAIN)
|
||||
EALREADY = Errno(syscall.EALREADY)
|
||||
EBADF = Errno(syscall.EBADF)
|
||||
EBUSY = Errno(syscall.EBUSY)
|
||||
ECANCELED = Errno(syscall.ECANCELED)
|
||||
ECONNABORTED = Errno(syscall.ECONNABORTED)
|
||||
ECONNREFUSED = Errno(syscall.ECONNREFUSED)
|
||||
ECONNRESET = Errno(syscall.ECONNRESET)
|
||||
EDESTADDRREQ = Errno(syscall.EDESTADDRREQ)
|
||||
EEXIST = Errno(syscall.EEXIST)
|
||||
EFAULT = Errno(syscall.EFAULT)
|
||||
EFBIG = Errno(syscall.EFBIG)
|
||||
EHOSTUNREACH = Errno(syscall.EHOSTUNREACH)
|
||||
EINTR = Errno(syscall.EINTR)
|
||||
EINVAL = Errno(syscall.EINVAL)
|
||||
EIO = Errno(syscall.EIO)
|
||||
EISCONN = Errno(syscall.EISCONN)
|
||||
EISDIR = Errno(syscall.EISDIR)
|
||||
ELOOP = Errno(syscall.ELOOP)
|
||||
EMFILE = Errno(syscall.EMFILE)
|
||||
EMSGSIZE = Errno(syscall.EMSGSIZE)
|
||||
ENAMETOOLONG = Errno(syscall.ENAMETOOLONG)
|
||||
ENETDOWN = Errno(syscall.ENETDOWN)
|
||||
ENETUNREACH = Errno(syscall.ENETUNREACH)
|
||||
ENFILE = Errno(syscall.ENFILE)
|
||||
ENOBUFS = Errno(syscall.ENOBUFS)
|
||||
ENODEV = Errno(syscall.ENODEV)
|
||||
ENOENT = Errno(syscall.ENOENT)
|
||||
ENOMEM = Errno(syscall.ENOMEM)
|
||||
ENOPROTOOPT = Errno(syscall.ENOPROTOOPT)
|
||||
ENOSPC = Errno(syscall.ENOSPC)
|
||||
ENOSYS = Errno(syscall.ENOSYS)
|
||||
ENOTCONN = Errno(syscall.ENOTCONN)
|
||||
ENOTDIR = Errno(syscall.ENOTDIR)
|
||||
ENOTEMPTY = Errno(syscall.ENOTEMPTY)
|
||||
ENOTSOCK = Errno(syscall.ENOTSOCK)
|
||||
ENOTSUP = Errno(syscall.ENOTSUP)
|
||||
EOVERFLOW = Errno(syscall.EOVERFLOW)
|
||||
EPERM = Errno(syscall.EPERM)
|
||||
EPIPE = Errno(syscall.EPIPE)
|
||||
EPROTO = Errno(syscall.EPROTO)
|
||||
EPROTONOSUPPORT = Errno(syscall.EPROTONOSUPPORT)
|
||||
EPROTOTYPE = Errno(syscall.EPROTOTYPE)
|
||||
ERANGE = Errno(syscall.ERANGE)
|
||||
EROFS = Errno(syscall.EROFS)
|
||||
ESHUTDOWN = Errno(syscall.ESHUTDOWN)
|
||||
ESPIPE = Errno(syscall.ESPIPE)
|
||||
ESRCH = Errno(syscall.ESRCH)
|
||||
ETIMEDOUT = Errno(syscall.ETIMEDOUT)
|
||||
ETXTBSY = Errno(syscall.ETXTBSY)
|
||||
EXDEV = Errno(syscall.EXDEV)
|
||||
ENXIO = Errno(syscall.ENXIO)
|
||||
EMLINK = Errno(syscall.EMLINK)
|
||||
EHOSTDOWN = Errno(syscall.EHOSTDOWN)
|
||||
ENOTTY = Errno(syscall.ENOTTY)
|
||||
//EFTYPE = Errno(syscall.EFTYPE)
|
||||
EILSEQ = Errno(syscall.EILSEQ)
|
||||
ESOCKTNOSUPPORT = Errno(syscall.ESOCKTNOSUPPORT)
|
||||
)
|
||||
|
||||
const (
|
||||
EAI_ADDRFAMILY = Errno(net.EAI_ADDRFAMILY)
|
||||
EAI_AGAIN = Errno(net.EAI_AGAIN)
|
||||
EAI_BADFLAGS = Errno(net.EAI_BADFLAGS)
|
||||
EAI_BADHINTS = Errno(net.EAI_BADHINTS)
|
||||
EAI_FAIL = Errno(net.EAI_FAIL)
|
||||
EAI_FAMILY = Errno(net.EAI_FAMILY)
|
||||
EAI_MEMORY = Errno(net.EAI_MEMORY)
|
||||
EAI_NODATA = Errno(net.EAI_NODATA)
|
||||
EAI_NONAME = Errno(net.EAI_NONAME)
|
||||
EAI_OVERFLOW = Errno(net.EAI_OVERFLOW)
|
||||
EAI_PROTOCOL = Errno(net.EAI_PROTOCOL)
|
||||
EAI_SERVICE = Errno(net.EAI_SERVICE)
|
||||
EAI_SOCKTYPE = Errno(net.EAI_SOCKTYPE)
|
||||
)
|
||||
|
||||
const (
|
||||
EAI_CANCELED Errno = -3003
|
||||
ECHARSET Errno = -4080
|
||||
ENONET Errno = -4056
|
||||
UNKNOWN Errno = -4094
|
||||
EOF Errno = -1
|
||||
EREMOTEIO Errno = -4030
|
||||
ERRNO_MAX Errno = EOF - 1
|
||||
)
|
||||
|
||||
type Errno c.Int
|
||||
|
||||
//go:linkname TranslateSysError C.uv_translate_sys_error
|
||||
func TranslateSysError(sysErrno c.Int) Errno
|
||||
|
||||
//go:linkname Strerror C.uv_strerror
|
||||
func Strerror(err Errno) *c.Char
|
||||
|
||||
//go:linkname StrerrorR C.uv_strerror_r
|
||||
func StrerrorR(err Errno, buf *c.Char, bufLen uintptr) *c.Char
|
||||
|
||||
//go:linkname ErrName C.uv_err_name
|
||||
func ErrName(err Errno) *c.Char
|
||||
|
||||
//go:linkname ErrNameR C.uv_err_name_r
|
||||
func ErrNameR(err Errno, buf *c.Char, bufLen uintptr) *c.Char
|
||||
272
c/libuv/fs.go
Normal file
272
c/libuv/fs.go
Normal file
@@ -0,0 +1,272 @@
|
||||
package libuv
|
||||
|
||||
import (
|
||||
_ "unsafe"
|
||||
|
||||
"github.com/goplus/llgo/c"
|
||||
)
|
||||
|
||||
const (
|
||||
FS_UNKNOWN FsType = -1
|
||||
FS_CUSTOM FsType = 0
|
||||
FS_OPEN FsType = 1
|
||||
FS_CLOSE FsType = 2
|
||||
FS_READ FsType = 3
|
||||
FS_WRITE FsType = 4
|
||||
FS_SENDFILE FsType = 5
|
||||
FS_STAT FsType = 6
|
||||
FS_LSTAT FsType = 7
|
||||
FS_FSTAT FsType = 8
|
||||
FS_FTRUNCATE FsType = 9
|
||||
FS_UTIME FsType = 10
|
||||
FS_FUTIME FsType = 11
|
||||
FS_ACCESS FsType = 12
|
||||
FS_CHMOD FsType = 13
|
||||
FS_FCHMOD FsType = 14
|
||||
FS_FSYNC FsType = 15
|
||||
FS_FDATASYNC FsType = 16
|
||||
FS_UNLINK FsType = 17
|
||||
FS_RMDIR FsType = 18
|
||||
FS_MKDIR FsType = 19
|
||||
FS_MKDTEMP FsType = 20
|
||||
FS_RENAME FsType = 21
|
||||
FS_SCANDIR FsType = 22
|
||||
FS_LINK FsType = 23
|
||||
FS_SYMLINK FsType = 24
|
||||
FS_READLINK FsType = 25
|
||||
FS_CHOWN FsType = 26
|
||||
FS_FCHOWN FsType = 27
|
||||
FS_REALPATH FsType = 28
|
||||
FS_COPYFILE FsType = 29
|
||||
FS_LCHOWN FsType = 30
|
||||
FS_OPENDIR FsType = 31
|
||||
FS_READDIR FsType = 32
|
||||
FS_CLOSEDIR FsType = 33
|
||||
FS_STATFS FsType = 34
|
||||
FS_MKSTEMP FsType = 35
|
||||
FS_LUTIME FsType = 36
|
||||
)
|
||||
|
||||
const (
|
||||
DirentUnknown DirentType = iota
|
||||
DirentFile
|
||||
DirentDir
|
||||
DirentLink
|
||||
DirentFifo
|
||||
DirentSocket
|
||||
DirentChar
|
||||
DirentBlock
|
||||
)
|
||||
|
||||
type FsType c.Int
|
||||
|
||||
type DirentType c.Int
|
||||
|
||||
type File c.Int
|
||||
|
||||
// ----------------------------------------------
|
||||
|
||||
/* Handle types. */
|
||||
|
||||
type Fs struct {
|
||||
Unused [0]byte
|
||||
}
|
||||
|
||||
type FsEvent struct {
|
||||
Unused [0]byte
|
||||
}
|
||||
|
||||
type FsPoll struct {
|
||||
Unused [0]byte
|
||||
}
|
||||
|
||||
type Dirent struct {
|
||||
Name *c.Char
|
||||
Type DirentType
|
||||
}
|
||||
|
||||
type Stat struct {
|
||||
Unused [0]byte
|
||||
}
|
||||
|
||||
// ----------------------------------------------
|
||||
|
||||
/* Function type */
|
||||
|
||||
// llgo:type C
|
||||
type FsCb func(req *Fs)
|
||||
|
||||
// llgo:type C
|
||||
type FsEventCb func(handle *FsEvent, filename *c.Char, events c.Int, status c.Int)
|
||||
|
||||
// llgo:type C
|
||||
type FsPollCb func(handle *FsPoll, status c.Int, events c.Int)
|
||||
|
||||
// ----------------------------------------------
|
||||
|
||||
/* Fs related function and method */
|
||||
|
||||
//go:linkname FsGetType C.uv_fs_get_type
|
||||
func FsGetType(req *Fs) FsType
|
||||
|
||||
//go:linkname FsGetPath C.uv_fs_get_path
|
||||
func FsGetPath(req *Fs) *c.Char
|
||||
|
||||
//go:linkname FsGetResult C.uv_fs_get_result
|
||||
func FsGetResult(req *Fs) c.Int
|
||||
|
||||
//go:linkname FsGetPtr C.uv_fs_get_ptr
|
||||
func FsGetPtr(req *Fs) c.Pointer
|
||||
|
||||
//go:linkname FsGetSystemError C.uv_fs_get_system_error
|
||||
func FsGetSystemError(req *Fs) c.Int
|
||||
|
||||
//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)
|
||||
|
||||
//go:linkname DefaultLoop C.uv_default_loop
|
||||
func DefaultLoop() *Loop
|
||||
|
||||
//go:linkname FsOpen C.uv_fs_open
|
||||
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 File, cb FsCb) c.Int
|
||||
|
||||
//go:linkname FsRead C.uv_fs_read
|
||||
func FsRead(loop *Loop, req *Fs, file File, 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 File, 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
|
||||
|
||||
//go:linkname FsMkdir C.uv_fs_mkdir
|
||||
func FsMkdir(loop *Loop, req *Fs, path *c.Char, mode c.Int, cb FsCb) c.Int
|
||||
|
||||
//go:linkname FsMkdtemp C.uv_fs_mkdtemp
|
||||
func FsMkdtemp(loop *Loop, req *Fs, tpl *c.Char, cb FsCb) c.Int
|
||||
|
||||
//go:linkname FsMkStemp C.uv_fs_mkstemp
|
||||
func FsMkStemp(loop *Loop, req *Fs, tpl *c.Char, cb FsCb) c.Int
|
||||
|
||||
//go:linkname FsRmdir C.uv_fs_rmdir
|
||||
func FsRmdir(loop *Loop, req *Fs, path *c.Char, cb FsCb) c.Int
|
||||
|
||||
//go:linkname FsStat C.uv_fs_stat
|
||||
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 File, 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 File, cb FsCb) c.Int
|
||||
|
||||
//go:linkname FsFdatasync C.uv_fs_fdatasync
|
||||
func FsFdatasync(loop *Loop, req *Fs, file File, cb FsCb) c.Int
|
||||
|
||||
//go:linkname FsFtruncate C.uv_fs_ftruncate
|
||||
func FsFtruncate(loop *Loop, req *Fs, file File, 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.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
|
||||
|
||||
//go:linkname FsChmod C.uv_fs_chmod
|
||||
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 File, 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 File, 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
|
||||
|
||||
//go:linkname FsLink C.uv_fs_link
|
||||
func FsLink(loop *Loop, req *Fs, path *c.Char, newPath *c.Char, cb FsCb) c.Int
|
||||
|
||||
//go:linkname FsSymlink C.uv_fs_symlink
|
||||
func FsSymlink(loop *Loop, req *Fs, path *c.Char, newPath *c.Char, flags c.Int, cb FsCb) c.Int
|
||||
|
||||
//go:linkname FsReadlink C.uv_fs_read
|
||||
func FsReadlink(loop *Loop, req *Fs, path *c.Char, cb FsCb) c.Int
|
||||
|
||||
//go:linkname FsRealpath C.uv_fs_realpath
|
||||
func FsRealpath(loop *Loop, req *Fs, path *c.Char, cb FsCb) c.Int
|
||||
|
||||
//go:linkname FsCopyfile C.uv_fs_copyfile
|
||||
func FsCopyfile(loop *Loop, req *Fs, path *c.Char, newPath *c.Char, flags c.Int, cb FsCb) c.Int
|
||||
|
||||
//go:linkname FsScandir C.uv_fs_scandir
|
||||
func FsScandir(loop *Loop, req *Fs, path *c.Char, flags c.Int, cb FsCb) c.Int
|
||||
|
||||
//go:linkname FsScandirNext C.uv_fs_scandir_next
|
||||
func FsScandirNext(req *Fs, ent *Dirent) c.Int
|
||||
|
||||
//go:linkname FsOpenDir C.uv_fs_opendir
|
||||
func FsOpenDir(loop *Loop, req *Fs, path *c.Char, cb FsCb) c.Int
|
||||
|
||||
//go:linkname FsReaddir C.uv_fs_readdir
|
||||
func FsReaddir(loop *Loop, req *Fs, dir c.Int, cb FsCb) c.Int
|
||||
|
||||
//go:linkname FsCloseDir C.uv_fs_closedir
|
||||
func FsCloseDir(loop *Loop, req *Fs) c.Int
|
||||
|
||||
//go:linkname FsStatfs C.uv_fs_statfs
|
||||
func FsStatfs(loop *Loop, req *Fs, path *c.Char, cb FsCb) c.Int
|
||||
|
||||
//go:linkname FsChown C.uv_fs_chown
|
||||
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 File, 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
|
||||
|
||||
//go:linkname FsLstat C.uv_fs_lstat
|
||||
func FsLstat(loop *Loop, req *Fs, path *c.Char, cb FsCb) c.Int
|
||||
|
||||
//go:linkname FsEventInit C.uv_fs_event_init
|
||||
func FsEventInit(loop *Loop, handle *FsEvent) c.Int
|
||||
|
||||
//go:linkname FsEventStart C.uv_fs_event_start
|
||||
func FsEventStart(handle *FsEvent, cb FsEventCb, path *c.Char, flags c.Int) c.Int
|
||||
|
||||
//go:linkname FsEventStop C.uv_fs_event_stop
|
||||
func FsEventStop(handle *FsEvent) c.Int
|
||||
|
||||
//go:linkname FsEventClose C.uv_fs_event_close
|
||||
func FsEventClose(handle *FsEvent) c.Int
|
||||
|
||||
//go:linkname FsEventGetpath C.uv_fs_event_getpath
|
||||
func FsEventGetpath(handle *FsEvent) *c.Char
|
||||
|
||||
//go:linkname FsPollInit C.uv_fs_poll_init
|
||||
func FsPollInit(loop *Loop, handle *FsPoll) c.Int
|
||||
|
||||
//go:linkname FsPollStart C.uv_fs_poll_start
|
||||
func FsPollStart(handle *FsPoll, cb FsPollCb, path *c.Char, interval uint) c.Int
|
||||
|
||||
//go:linkname FsPollStop C.uv_fs_poll_stop
|
||||
func FsPollStop(handle *FsPoll) c.Int
|
||||
|
||||
//go:linkname FsPollClose C.uv_fs_poll_close
|
||||
func FsPollClose(handle *FsPoll) c.Int
|
||||
|
||||
//go:linkname FsPollGetPath C.uv_fs_poll_getpath
|
||||
func FsPollGetPath(handle *FsPoll) *c.Char
|
||||
456
c/libuv/libuv.go
Normal file
456
c/libuv/libuv.go
Normal file
@@ -0,0 +1,456 @@
|
||||
package libuv
|
||||
|
||||
import (
|
||||
_ "unsafe"
|
||||
|
||||
"github.com/goplus/llgo/c"
|
||||
"github.com/goplus/llgo/c/net"
|
||||
)
|
||||
|
||||
const (
|
||||
LLGoPackage = "link: $(pkg-config --libs libuv); -luv"
|
||||
)
|
||||
|
||||
// ----------------------------------------------
|
||||
const (
|
||||
RUN_DEFAULT RunMode = iota
|
||||
RUN_ONCE
|
||||
RUN_NOWAIT
|
||||
)
|
||||
|
||||
const (
|
||||
LOOP_BLOCK_SIGNAL LoopOption = iota
|
||||
METRICS_IDLE_TIME
|
||||
)
|
||||
|
||||
const (
|
||||
UV_LEAVE_GROUP Membership = iota
|
||||
UV_JOIN_GROUP
|
||||
)
|
||||
|
||||
const (
|
||||
UNKNOWN_HANDLE HandleType = iota
|
||||
ASYNC
|
||||
CHECK
|
||||
FS_EVENT
|
||||
FS_POLL
|
||||
HANDLE
|
||||
IDLE
|
||||
NAMED_PIPE
|
||||
POLL
|
||||
PREPARE
|
||||
PROCESS
|
||||
STREAM
|
||||
TCP
|
||||
TIMER
|
||||
TTY
|
||||
UDP
|
||||
SIGNAL
|
||||
FILE
|
||||
HANDLE_TYPE_MAX
|
||||
)
|
||||
|
||||
const (
|
||||
UNKNOWN_REQ ReqType = iota
|
||||
REQ
|
||||
CONNECT
|
||||
WRITE
|
||||
SHUTDOWN
|
||||
UDP_SEND
|
||||
FS
|
||||
WORK
|
||||
GETADDRINFO
|
||||
GETNAMEINFO
|
||||
RANDOM
|
||||
REQ_TYPE_PRIVATE
|
||||
REQ_TYPE_MAX
|
||||
)
|
||||
|
||||
const (
|
||||
READABLE PollEvent = 1 << iota
|
||||
WRITABLE
|
||||
DISCONNECT
|
||||
PRIPRIORITIZED
|
||||
)
|
||||
|
||||
type RunMode c.Int
|
||||
|
||||
type LoopOption c.Int
|
||||
|
||||
type Membership c.Int
|
||||
|
||||
type HandleType c.Int
|
||||
|
||||
type ReqType c.Int
|
||||
|
||||
type OsSock c.Int
|
||||
|
||||
type OsFd c.Int
|
||||
|
||||
type PollEvent c.Int
|
||||
|
||||
// ----------------------------------------------
|
||||
|
||||
/* Handle types. */
|
||||
|
||||
type Loop struct {
|
||||
Unused [0]byte
|
||||
}
|
||||
|
||||
type Handle struct {
|
||||
Unused [96]byte
|
||||
}
|
||||
|
||||
type Stream struct {
|
||||
Unused [264]byte
|
||||
}
|
||||
|
||||
type Poll struct {
|
||||
Unused [0]byte
|
||||
}
|
||||
|
||||
/* Request types. */
|
||||
|
||||
type Req struct {
|
||||
Unused [0]byte
|
||||
}
|
||||
|
||||
type GetAddrInfo struct {
|
||||
Unused [0]byte
|
||||
}
|
||||
|
||||
type GetNameInfo struct {
|
||||
Unused [0]byte
|
||||
}
|
||||
|
||||
type Shutdown struct {
|
||||
Unused [0]byte
|
||||
}
|
||||
|
||||
type Write struct {
|
||||
Unused [192]byte
|
||||
}
|
||||
|
||||
type Connect struct {
|
||||
Unused [0]byte
|
||||
}
|
||||
|
||||
type Buf struct {
|
||||
Base *c.Char
|
||||
Len uintptr
|
||||
} // ----------------------------------------------
|
||||
|
||||
/* Function type */
|
||||
|
||||
// llgo:type C
|
||||
type MallocFunc func(size uintptr) c.Pointer
|
||||
|
||||
// llgo:type C
|
||||
type ReallocFunc func(ptr c.Pointer, size uintptr) c.Pointer
|
||||
|
||||
// llgo:type C
|
||||
type CallocFunc func(count uintptr, size uintptr) c.Pointer
|
||||
|
||||
// llgo:type C
|
||||
type FreeFunc func(ptr c.Pointer)
|
||||
|
||||
// llgo:type C
|
||||
type AllocCb func(handle *Handle, suggestedSize uintptr, buf *Buf)
|
||||
|
||||
// llgo:type C
|
||||
type ReadCb func(stream *Stream, nread c.Long, buf *Buf)
|
||||
|
||||
// llgo:type C
|
||||
type WriteCb func(req *Write, status c.Int)
|
||||
|
||||
// llgo:type C
|
||||
type GetaddrinfoCb func(req *GetAddrInfo, status c.Int, res *net.AddrInfo)
|
||||
|
||||
// llgo:type C
|
||||
type GetnameinfoCb func(req *GetNameInfo, status c.Int, hostname *c.Char, service *c.Char)
|
||||
|
||||
// llgo:type C
|
||||
type ConnectionCb func(server *Stream, status c.Int)
|
||||
|
||||
// llgo:type C
|
||||
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
|
||||
func Version() c.Uint
|
||||
|
||||
//go:linkname VersionString C.uv_version_string
|
||||
func VersionString() *c.Char
|
||||
|
||||
//go:linkname LibraryShutdown C.uv_library_shutdown
|
||||
func LibraryShutdown()
|
||||
|
||||
//go:linkname ReplaceAllocator C.uv_replace_allocator
|
||||
func ReplaceAllocator(mallocFunc MallocFunc, reallocFunc ReallocFunc, callocFunc CallocFunc, freeFunc FreeFunc) c.Int
|
||||
|
||||
// ----------------------------------------------
|
||||
|
||||
// llgo:link (*Shutdown).Shutdown C.uv_shutdown
|
||||
func (shutdown *Shutdown) Shutdown(stream *Stream, shutdownCb ShutdownCb) c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// ----------------------------------------------
|
||||
|
||||
/* Handle related function and method */
|
||||
|
||||
// llgo:link (*Handle).Ref C.uv_ref
|
||||
func (handle *Handle) Ref() {}
|
||||
|
||||
// llgo:link (*Handle).Unref C.uv_unref
|
||||
func (handle *Handle) Unref() {}
|
||||
|
||||
// llgo:link (*Handle).HasRef C.uv_has_ref
|
||||
func (handle *Handle) HasRef() c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
//go:linkname HandleSize C.uv_handle_size
|
||||
func HandleSize(handleType HandleType) uintptr
|
||||
|
||||
// llgo:link (*Handle).GetType C.uv_handle_get_type
|
||||
func (handle *Handle) GetType() HandleType {
|
||||
return 0
|
||||
}
|
||||
|
||||
//go:linkname HandleTypeName C.uv_handle_type_name
|
||||
func HandleTypeName(handleType HandleType) *c.Char
|
||||
|
||||
// llgo:link (*Handle).GetData C.uv_handle_get_data
|
||||
func (handle *Handle) GetData() c.Pointer {
|
||||
return nil
|
||||
}
|
||||
|
||||
// llgo:link (*Handle).GetLoop C.uv_handle_get_loop
|
||||
func (handle *Handle) GetLoop() *Loop {
|
||||
return nil
|
||||
}
|
||||
|
||||
// llgo:link (*Handle).SetData C.uv_handle_set_data
|
||||
func (handle *Handle) SetData(data c.Pointer) {}
|
||||
|
||||
// llgo:link (*Handle).IsActive C.uv_is_active
|
||||
func (handle *Handle) IsActive() c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*Handle).Close C.uv_close
|
||||
func (handle *Handle) Close(closeCb CloseCb) {}
|
||||
|
||||
// llgo:link (*Handle).SendBufferSize C.uv_send_buffer_size
|
||||
func (handle *Handle) SendBufferSize(value *c.Int) c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*Handle).RecvBufferSize C.uv_recv_buffer_size
|
||||
func (handle *Handle) RecvBufferSize(value *c.Int) c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*Handle).Fileno C.uv_fileno
|
||||
func (handle *Handle) Fileno(fd *OsFd) c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
//go:linkname Pipe C.uv_pipe
|
||||
func Pipe(fds [2]File, readFlags c.Int, writeFlags c.Int) c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
//go:linkname Socketpair C.uv_socketpair
|
||||
func Socketpair(_type c.Int, protocol c.Int, socketVector [2]OsSock, flag0 c.Int, flag1 c.Int) c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*Handle).IsClosing C.uv_is_closing
|
||||
func (handle *Handle) IsClosing() c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// ----------------------------------------------
|
||||
|
||||
/* Req related function and method */
|
||||
|
||||
//go:linkname ReqSize C.uv_req_size
|
||||
func ReqSize(reqType ReqType) uintptr
|
||||
|
||||
// llgo:link (*Req).GetData C.uv_req_get_data
|
||||
func (req *Req) GetData() c.Pointer {
|
||||
return nil
|
||||
}
|
||||
|
||||
// llgo:link (*Req).SetData C.uv_handle_set_data
|
||||
func (req *Req) SetData(data c.Pointer) {}
|
||||
|
||||
// llgo:link (*Req).GetType C.uv_req_get_type
|
||||
func (req *Req) GetType() ReqType {
|
||||
return 0
|
||||
}
|
||||
|
||||
//go:linkname TypeName C.uv_req_type_name
|
||||
func TypeName(reqType ReqType) *c.Char
|
||||
|
||||
// ----------------------------------------------
|
||||
|
||||
/* Stream related function and method */
|
||||
|
||||
// llgo:link (*Stream).GetWriteQueueSize C.uv_stream_get_write_queue_size
|
||||
func (stream *Stream) GetWriteQueueSize() uintptr {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*Stream).Listen C.uv_listen
|
||||
func (stream *Stream) Listen(backlog c.Int, connectionCb ConnectionCb) c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*Stream).Accept C.uv_accept
|
||||
func (server *Stream) Accept(client *Stream) c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*Stream).StartRead C.uv_read_start
|
||||
func (stream *Stream) StartRead(allocCb AllocCb, readCb ReadCb) c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*Stream).StopRead C.uv_read_stop
|
||||
func (stream *Stream) StopRead() c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*Write).Write C.uv_write
|
||||
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 {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*Stream).TryWrite C.uv_try_write
|
||||
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 {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*Stream).IsReadable C.uv_is_readable
|
||||
func (stream *Stream) IsReadable() c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*Stream).IsWritable C.uv_is_writable
|
||||
func (stream *Stream) IsWritable() c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*Stream).SetBlocking C.uv_stream_set_blocking
|
||||
func (stream *Stream) SetBlocking(blocking c.Int) c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// ----------------------------------------------
|
||||
|
||||
/* 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
|
||||
func Getaddrinfo(loop *Loop, req *GetAddrInfo, getaddrinfoCb GetaddrinfoCb, node *c.Char, service *c.Char, hints *net.AddrInfo) c.Int
|
||||
|
||||
//go:linkname Freeaddrinfo C.uv_freeaddrinfo
|
||||
func Freeaddrinfo(addrInfo *net.AddrInfo)
|
||||
|
||||
// ----------------------------------------------
|
||||
|
||||
/* Getnameinfo related function and method */
|
||||
|
||||
//go:linkname Getnameinfo C.uv_getnameinfo
|
||||
func Getnameinfo(loop *Loop, req *GetNameInfo, getnameinfoCb GetnameinfoCb, addr *net.SockAddr, flags c.Int) c.Int
|
||||
275
c/libuv/net.go
Normal file
275
c/libuv/net.go
Normal file
@@ -0,0 +1,275 @@
|
||||
package libuv
|
||||
|
||||
import (
|
||||
_ "unsafe"
|
||||
|
||||
"github.com/goplus/llgo/c"
|
||||
"github.com/goplus/llgo/c/net"
|
||||
)
|
||||
|
||||
const (
|
||||
/* Used with uv_tcp_bind, when an IPv6 address is used. */
|
||||
TCP_IPV6ONLY TcpFlags = 1
|
||||
)
|
||||
|
||||
/*
|
||||
* UDP support.
|
||||
*/
|
||||
const (
|
||||
/* Disables dual stack mode. */
|
||||
UDP_IPV6ONLY UdpFlags = 1
|
||||
/*
|
||||
* Indicates message was truncated because read buffer was too small. The
|
||||
* remainder was discarded by the OS. Used in uv_udp_recv_cb.
|
||||
*/
|
||||
UDP_PARTIAL UdpFlags = 2
|
||||
/*
|
||||
* Indicates if SO_REUSEADDR will be set when binding the handle.
|
||||
* This sets the SO_REUSEPORT socket flag on the BSDs and OS X. On other
|
||||
* Unix platforms, it sets the SO_REUSEADDR flag. What that means is that
|
||||
* multiple threads or processes can bind to the same address without error
|
||||
* (provided they all set the flag) but only the last one to bind will receive
|
||||
* any traffic, in effect "stealing" the port from the previous listener.
|
||||
*/
|
||||
UDP_REUSEADDR UdpFlags = 4
|
||||
/*
|
||||
* Indicates that the message was received by recvmmsg, so the buffer provided
|
||||
* must not be freed by the recv_cb callback.
|
||||
*/
|
||||
UDP_MMSG_CHUNK UdpFlags = 8
|
||||
/*
|
||||
* Indicates that the buffer provided has been fully utilized by recvmmsg and
|
||||
* that it should now be freed by the recv_cb callback. When this flag is set
|
||||
* in uv_udp_recv_cb, nread will always be 0 and addr will always be NULL.
|
||||
*/
|
||||
UDP_MMSG_FREE UdpFlags = 16
|
||||
/*
|
||||
* Indicates if IP_RECVERR/IPV6_RECVERR will be set when binding the handle.
|
||||
* This sets IP_RECVERR for IPv4 and IPV6_RECVERR for IPv6 UDP sockets on
|
||||
* Linux. This stops the Linux kernel from suppressing some ICMP error
|
||||
* messages and enables full ICMP error reporting for faster failover.
|
||||
* This flag is no-op on platforms other than Linux.
|
||||
*/
|
||||
UDP_LINUX_RECVERR UdpFlags = 32
|
||||
/*
|
||||
* Indicates that recvmmsg should be used, if available.
|
||||
*/
|
||||
UDP_RECVMMSG UdpFlags = 256
|
||||
)
|
||||
|
||||
type TcpFlags c.Int
|
||||
|
||||
type UdpFlags c.Int
|
||||
|
||||
// ----------------------------------------------
|
||||
|
||||
/* Handle types. */
|
||||
|
||||
type Tcp struct {
|
||||
Unused [264]byte
|
||||
}
|
||||
|
||||
type Udp struct {
|
||||
Unused [0]byte
|
||||
}
|
||||
|
||||
/* Request types. */
|
||||
|
||||
type UdpSend struct {
|
||||
Unused [0]byte
|
||||
}
|
||||
|
||||
// ----------------------------------------------
|
||||
|
||||
/* Function type */
|
||||
|
||||
// llgo:type C
|
||||
type CloseCb func(handle *Handle)
|
||||
|
||||
// llgo:type C
|
||||
type ConnectCb func(req *Connect, status c.Int)
|
||||
|
||||
// llgo:type C
|
||||
type UdpSendCb func(req *UdpSend, status c.Int)
|
||||
|
||||
// llgo:type C
|
||||
type UdpRecvCb func(handle *Udp, nread c.Long, buf *Buf, addr *net.SockAddr, flags c.Uint)
|
||||
|
||||
// ----------------------------------------------
|
||||
|
||||
/* Tcp related function and method */
|
||||
|
||||
//go:linkname InitTcp C.uv_tcp_init
|
||||
func InitTcp(loop *Loop, tcp *Tcp) c.Int
|
||||
|
||||
//go:linkname InitTcpEx C.uv_tcp_init_ex
|
||||
func InitTcpEx(loop *Loop, tcp *Tcp, flags c.Uint) c.Int
|
||||
|
||||
// llgo:link (*Tcp).Open C.uv_tcp_open
|
||||
func (tcp *Tcp) Open(sock OsSock) c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*Tcp).Nodelay C.uv_tcp_nodelay
|
||||
func (tcp *Tcp) Nodelay(enable c.Int) c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*Tcp).KeepAlive C.uv_tcp_keepalive
|
||||
func (tcp *Tcp) KeepAlive(enable c.Int, delay c.Uint) c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*Tcp).SimultaneousAccepts C.uv_tcp_simultaneous_accepts
|
||||
func (tcp *Tcp) SimultaneousAccepts(enable c.Int) c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*Tcp).Bind C.uv_tcp_bind
|
||||
func (tcp *Tcp) Bind(addr *net.SockAddr, flags c.Uint) c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*Tcp).Getsockname C.uv_tcp_getsockname
|
||||
func (tcp *Tcp) Getsockname(name *net.SockAddr, nameLen *c.Int) c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*Tcp).Getpeername C.uv_tcp_getpeername
|
||||
func (tcp *Tcp) Getpeername(name *net.SockAddr, nameLen *c.Int) c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*Tcp).CloseReset C.uv_tcp_close_reset
|
||||
func (tcp *Tcp) CloseReset(closeCb CloseCb) c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
//go:linkname TcpConnect C.uv_tcp_connect
|
||||
func TcpConnect(req *Connect, tcp *Tcp, addr *net.SockAddr, connectCb ConnectCb) c.Int
|
||||
|
||||
// ----------------------------------------------
|
||||
|
||||
/* Udp related function and method */
|
||||
|
||||
//go:linkname InitUdp C.uv_udp_init
|
||||
func InitUdp(loop *Loop, udp *Udp) c.Int
|
||||
|
||||
//go:linkname InitUdpEx C.uv_udp_init_ex
|
||||
func InitUdpEx(loop *Loop, udp *Udp, flags c.Uint) c.Int
|
||||
|
||||
// llgo:link (*Udp).Open C.uv_udp_open
|
||||
func (udp *Udp) Open(sock OsSock) c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*Udp).Bind C.uv_udp_bind
|
||||
func (udp *Udp) Bind(addr *net.SockAddr, flags c.Uint) c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*Udp).Connect C.uv_udp_connect
|
||||
func (udp *Udp) Connect(addr *net.SockAddr) c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*Udp).Getpeername C.uv_udp_getpeername
|
||||
func (udp *Udp) Getpeername(name *net.SockAddr, nameLen *c.Int) c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*Udp).Getsockname C.uv_udp_getsockname
|
||||
func (udp *Udp) Getsockname(name *net.SockAddr, nameLen *c.Int) c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*Udp).SetMembership C.uv_udp_set_membership
|
||||
func (udp *Udp) SetMembership(multicastAddr *c.Char, interfaceAddr *c.Char, membership Membership) c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*Udp).SourceMembership C.uv_udp_set_source_membership
|
||||
func (udp *Udp) SourceMembership(multicastAddr *c.Char, interfaceAddr *c.Char, sourceAddr *c.Char, membership Membership) c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*Udp).SetMulticastLoop C.uv_udp_set_multicast_loop
|
||||
func (udp *Udp) SetMulticastLoop(on c.Int) c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*Udp).SetMulticastTTL C.uv_udp_set_multicast_ttl
|
||||
func (udp *Udp) SetMulticastTTL(ttl c.Int) c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*Udp).SetMulticastInterface C.uv_udp_set_multicast_interface
|
||||
func (udp *Udp) SetMulticastInterface(interfaceAddr *c.Char) c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*Udp).SetBroadcast C.uv_udp_set_broadcast
|
||||
func (udp *Udp) SetBroadcast(on c.Int) c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*Udp).SetTTL C.uv_udp_set_ttl
|
||||
func (udp *Udp) SetTTL(ttl c.Int) c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
//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
|
||||
|
||||
// llgo:link (*Udp).TrySend C.uv_udp_try_send
|
||||
func (udp *Udp) TrySend(bufs *Buf, nbufs c.Uint, addr *net.SockAddr) c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*Udp).StartRecv C.uv_udp_recv_start
|
||||
func (udp *Udp) StartRecv(allocCb AllocCb, recvCb UdpRecvCb) c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*Udp).UsingRecvmmsg C.uv_udp_using_recvmmsg
|
||||
func (udp *Udp) UsingRecvmmsg() c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*Udp).StopRecv C.uv_udp_recv_stop
|
||||
func (udp *Udp) StopRecv() c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*Udp).GetSendQueueSize C.uv_udp_get_send_queue_size
|
||||
func (udp *Udp) GetSendQueueSize() uintptr {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*Udp).GetSendQueueCount C.uv_udp_get_send_queue_count
|
||||
func (udp *Udp) GetSendQueueCount() uintptr {
|
||||
return 0
|
||||
}
|
||||
|
||||
// ----------------------------------------------
|
||||
|
||||
//go:linkname Ip4Addr C.uv_ip4_addr
|
||||
func Ip4Addr(ip *c.Char, port c.Int, addr *net.SockaddrIn) c.Int
|
||||
|
||||
//go:linkname Ip6Addr C.uv_ip6_addr
|
||||
func Ip6Addr(ip *c.Char, port c.Int, addr *net.SockaddrIn6) c.Int
|
||||
|
||||
//go:linkname Ip4Name C.uv_ip4_name
|
||||
func Ip4Name(src *net.SockaddrIn, dst *c.Char, size uintptr) c.Int
|
||||
|
||||
//go:linkname Ip6Name C.uv_ip6_name
|
||||
func Ip6Name(src *net.SockaddrIn6, dst *c.Char, size uintptr) c.Int
|
||||
|
||||
//go:linkname IpName C.uv_ip_name
|
||||
func IpName(src *net.SockAddr, dst *c.Char, size uintptr) c.Int
|
||||
|
||||
//go:linkname InetNtop C.uv_inet_ntop
|
||||
func InetNtop(af c.Int, src c.Pointer, dst *c.Char, size uintptr) c.Int
|
||||
|
||||
//go:linkname InetPton C.uv_inet_pton
|
||||
func InetPton(af c.Int, src *c.Char, dst c.Pointer) c.Int
|
||||
33
c/libuv/signal.go
Normal file
33
c/libuv/signal.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package libuv
|
||||
|
||||
import (
|
||||
_ "unsafe"
|
||||
|
||||
"github.com/goplus/llgo/c"
|
||||
)
|
||||
|
||||
/* Handle types. */
|
||||
|
||||
type Signal struct {
|
||||
Unused [0]byte
|
||||
}
|
||||
|
||||
// ----------------------------------------------
|
||||
|
||||
/* Function type */
|
||||
|
||||
// llgo:type C
|
||||
type SignalCb func(handle *Signal, sigNum c.Int)
|
||||
|
||||
// ----------------------------------------------
|
||||
|
||||
/* Signal related functions and method. */
|
||||
|
||||
//go:linkname SignalInit C.uv_signal_init
|
||||
func SignalInit(loop *Loop, handle *Signal) c.Int
|
||||
|
||||
//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
|
||||
55
c/libuv/timer.go
Normal file
55
c/libuv/timer.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package libuv
|
||||
|
||||
import (
|
||||
_ "unsafe"
|
||||
|
||||
"github.com/goplus/llgo/c"
|
||||
)
|
||||
|
||||
// ----------------------------------------------
|
||||
|
||||
/* Handle types. */
|
||||
|
||||
type Timer struct {
|
||||
Unused [0]byte
|
||||
}
|
||||
|
||||
// ----------------------------------------------
|
||||
|
||||
// llgo:type Cgit
|
||||
type TimerCb func(timer *Timer)
|
||||
|
||||
// ----------------------------------------------
|
||||
|
||||
/* Timer related function and method */
|
||||
|
||||
//go:linkname InitTimer C.uv_timer_init
|
||||
func InitTimer(loop *Loop, timer *Timer) c.Int
|
||||
|
||||
// llgo:link (*Timer).Start C.uv_timer_start
|
||||
func (timer *Timer) Start(cb TimerCb, timeout uint64, repeat uint64) c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*Timer).Stop C.uv_timer_stop
|
||||
func (timer *Timer) Stop() c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*Timer).Again C.uv_timer_again
|
||||
func (timer *Timer) Again() c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*Timer).SetRepeat C.uv_timer_set_repeat
|
||||
func (timer *Timer) SetRepeat(repeat uint64) {}
|
||||
|
||||
// llgo:link (*Timer).GetRepeat C.uv_timer_get_repeat
|
||||
func (timer *Timer) GetRepeat() uint64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
// llgo:link (*Timer).GetDueIn C.uv_timer_get_due_in
|
||||
func (timer *Timer) GetDueIn() uint64 {
|
||||
return 0
|
||||
}
|
||||
42
c/lua/_demo/coroutine-cfunc/coroutine.go
Normal file
42
c/lua/_demo/coroutine-cfunc/coroutine.go
Normal file
@@ -0,0 +1,42 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/goplus/llgo/c"
|
||||
"github.com/goplus/llgo/c/lua"
|
||||
)
|
||||
|
||||
func coroutineFunc(L *lua.State) c.Int {
|
||||
c.Printf(c.Str("Coroutine started\n"))
|
||||
L.Yield(0) // Pause the coroutine
|
||||
c.Printf(c.Str("Coroutine resumed\n"))
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
L := lua.Newstate()
|
||||
defer L.Close()
|
||||
|
||||
L.Openlibs()
|
||||
co := L.Newthread()
|
||||
L.Pushcfunction(coroutineFunc)
|
||||
L.Xmove(co, 1)
|
||||
|
||||
var nres c.Int
|
||||
|
||||
c.Printf(c.Str("Resuming coroutine for the first time\n"))
|
||||
result := co.Resume(nil, 0, &nres)
|
||||
if result == lua.YIELD {
|
||||
c.Printf(c.Str("Coroutine yielded\n"))
|
||||
result = co.Resume(nil, 0, &nres)
|
||||
if result == 0 {
|
||||
c.Printf(c.Str("Coroutine finished\n"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Expected output:
|
||||
Resuming coroutine for the first time
|
||||
Coroutine started
|
||||
Coroutine yielded
|
||||
Coroutine finished
|
||||
*/
|
||||
@@ -6,28 +6,28 @@ import (
|
||||
)
|
||||
|
||||
func coroutineFunc(L *lua.State) {
|
||||
L.LoadString(c.Str(`
|
||||
L.Loadstring(c.Str(`
|
||||
function coro_func()
|
||||
for i = 1, 5 do
|
||||
coroutine.yield(i)
|
||||
end
|
||||
end
|
||||
`))
|
||||
L.PCall(0, 0, 0)
|
||||
L.GetGlobal(c.Str("coro_func"))
|
||||
L.Pcall(0, 0, 0)
|
||||
L.Getglobal(c.Str("coro_func"))
|
||||
}
|
||||
|
||||
func main() {
|
||||
L := lua.NewState()
|
||||
L := lua.Newstate()
|
||||
defer L.Close()
|
||||
|
||||
L.OpenLibs()
|
||||
L.Openlibs()
|
||||
|
||||
coroutineFunc(L) // Load and get the coroutine function
|
||||
|
||||
co := L.NewThread() // Create a new coroutine/thread
|
||||
L.PushValue(-2) // Move the function to the top of the stack
|
||||
L.XMove(co, 1) // Move the function to the new coroutine
|
||||
co := L.Newthread() // Create a new coroutine/thread
|
||||
L.Pushvalue(-2) // Move the function to the top of the stack
|
||||
L.Xmove(co, 1) // Move the function to the new coroutine
|
||||
|
||||
var nres c.Int
|
||||
var status c.Int
|
||||
@@ -36,14 +36,14 @@ func main() {
|
||||
// Resume coroutine and handle yields
|
||||
for {
|
||||
status = co.Resume(nil, 0, &nres)
|
||||
c.Printf(c.Str("Resuming coroutine %d...\n"), status)
|
||||
if status == lua.YIELD {
|
||||
yieldValue := co.ToInteger(-1)
|
||||
c.Printf(c.Str("Resuming coroutine %d...\n"), status)
|
||||
yieldValue := co.Tointeger(-1)
|
||||
c.Printf(c.Str("Yield value: %d\n"), yieldValue)
|
||||
co.Pop(1) // Clean up the stack
|
||||
|
||||
// Check if the coroutine is yieldable
|
||||
if co.IsYieldable() != 0 {
|
||||
if co.Isyieldable() != 0 {
|
||||
c.Printf(c.Str("Coroutine is yieldable.\n"))
|
||||
} else {
|
||||
c.Printf(c.Str("Coroutine is not yieldable.\n"))
|
||||
@@ -58,3 +58,23 @@ func main() {
|
||||
finalStatus := co.Status()
|
||||
c.Printf(c.Str("Final status of coroutine: %d\n"), finalStatus)
|
||||
}
|
||||
|
||||
/* Expected output:
|
||||
Resuming coroutine...
|
||||
Resuming coroutine 1...
|
||||
Yield value: 1
|
||||
Coroutine is yieldable.
|
||||
Resuming coroutine 1...
|
||||
Yield value: 2
|
||||
Coroutine is yieldable.
|
||||
Resuming coroutine 1...
|
||||
Yield value: 3
|
||||
Coroutine is yieldable.
|
||||
Resuming coroutine 1...
|
||||
Yield value: 4
|
||||
Coroutine is yieldable.
|
||||
Resuming coroutine 1...
|
||||
Yield value: 5
|
||||
Coroutine is yieldable.
|
||||
Final status of coroutine: 0
|
||||
*/
|
||||
|
||||
@@ -8,11 +8,11 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
L := lua.NewState()
|
||||
L := lua.Newstate()
|
||||
defer L.Close()
|
||||
L.OpenLibs()
|
||||
if res := L.LoadString(c.Str("function doubleNumber(x) ! return x * 2 end")); res != lua.OK {
|
||||
c.Printf(c.Str("error: %s\n"), L.ToString(-1))
|
||||
L.Openlibs()
|
||||
if res := L.Loadstring(c.Str("function doubleNumber(x) ! return x * 2 end")); res != lua.OK {
|
||||
c.Printf(c.Str("error: %s\n"), L.Tostring(-1))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,21 +8,21 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
L := lua.NewState()
|
||||
L := lua.Newstate()
|
||||
defer L.Close()
|
||||
|
||||
L.OpenLibs()
|
||||
if res := L.DoString(c.Str("function combineParams(num, str) return 'Result: ' .. str .. ' ' .. num end")); res != lua.OK {
|
||||
c.Printf(c.Str("error: %s\n"), L.ToString(-1))
|
||||
L.Openlibs()
|
||||
if res := L.Dostring(c.Str("function combineParams(num, str) return 'Result: ' .. str .. ' ' .. num end")); res != lua.OK {
|
||||
c.Printf(c.Str("error: %s\n"), L.Tostring(-1))
|
||||
}
|
||||
L.GetGlobal(c.Str("combineParams"))
|
||||
L.PushNumber(3.14159)
|
||||
L.PushString(c.Str("Hello, World!"))
|
||||
if res := L.PCall(2, 1, 0); res != lua.OK {
|
||||
c.Printf(c.Str("error: %s\n"), L.ToString(-1))
|
||||
L.Getglobal(c.Str("combineParams"))
|
||||
L.Pushnumber(3.14159)
|
||||
L.Pushstring(c.Str("Hello, World!"))
|
||||
if res := L.Pcall(2, 1, 0); res != lua.OK {
|
||||
c.Printf(c.Str("error: %s\n"), L.Tostring(-1))
|
||||
}
|
||||
if res := L.IsString(-1); res != 0 {
|
||||
result := L.ToString(-1)
|
||||
if res := L.Isstring(-1); res != 0 {
|
||||
result := L.Tostring(-1)
|
||||
c.Printf(result)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,29 +8,29 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
L := lua.NewState()
|
||||
L := lua.Newstate()
|
||||
defer L.Close()
|
||||
|
||||
L.OpenLibs()
|
||||
if res := L.LoadString(c.Str("function doubleNumber(x) return x * 2 end")); res != lua.OK {
|
||||
c.Printf(c.Str("error: %s\n"), L.ToString(-1))
|
||||
L.Openlibs()
|
||||
if res := L.Loadstring(c.Str("function doubleNumber(x) return x * 2 end")); res != lua.OK {
|
||||
c.Printf(c.Str("error: %s\n"), L.Tostring(-1))
|
||||
}
|
||||
if res := L.PCall(0, 0, 0); res != lua.OK {
|
||||
c.Printf(c.Str("error: %s\n"), L.ToString(-1))
|
||||
if res := L.Pcall(0, 0, 0); res != lua.OK {
|
||||
c.Printf(c.Str("error: %s\n"), L.Tostring(-1))
|
||||
}
|
||||
|
||||
L.GetGlobal(c.Str("doubleNumber"))
|
||||
L.PushNumber(10)
|
||||
L.Getglobal(c.Str("doubleNumber"))
|
||||
L.Pushnumber(10)
|
||||
|
||||
if res := L.PCall(1, 1, 0); res != lua.OK {
|
||||
c.Printf(c.Str("error: %s\n"), L.ToString(-1))
|
||||
if res := L.Pcall(1, 1, 0); res != lua.OK {
|
||||
c.Printf(c.Str("error: %s\n"), L.Tostring(-1))
|
||||
}
|
||||
|
||||
if res := L.IsNumber(-1); res != 0 {
|
||||
result := L.ToInteger(-1)
|
||||
if res := L.Isnumber(-1); res != 0 {
|
||||
result := L.Tointeger(-1)
|
||||
c.Printf(c.Str("result: %lld\n"), result)
|
||||
} else {
|
||||
c.Printf(c.Str("error: %s\n"), L.ToString(-1))
|
||||
c.Printf(c.Str("error: %s\n"), L.Tostring(-1))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,10 +8,10 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
L := lua.NewState()
|
||||
L := lua.Newstate()
|
||||
defer L.Close()
|
||||
|
||||
L.OpenLibs()
|
||||
L.Openlibs()
|
||||
code := c.Str(
|
||||
`function processStrings(a, b, c)
|
||||
print('Received string a: ' .. a)
|
||||
@@ -20,22 +20,22 @@ func main() {
|
||||
return a .. b .. c
|
||||
end`)
|
||||
|
||||
if res := L.DoString(code); res != lua.OK {
|
||||
c.Printf(c.Str("error: %s\n"), L.ToString(-1))
|
||||
if res := L.Dostring(code); res != lua.OK {
|
||||
c.Printf(c.Str("error: %s\n"), L.Tostring(-1))
|
||||
}
|
||||
|
||||
L.GetGlobal(c.Str("processStrings"))
|
||||
L.Getglobal(c.Str("processStrings"))
|
||||
|
||||
L.PushString(c.Str("Hello, World!"))
|
||||
L.PushLString(c.Str(`Hello Lua In LLGO`), 17)
|
||||
L.PushFString(c.Str(`Hello %s In %d`), c.Str("LLGO"), 2024)
|
||||
L.Pushstring(c.Str("Hello, World!"))
|
||||
L.Pushlstring(c.Str(`Hello Lua In LLGO`), 17)
|
||||
L.Pushfstring(c.Str(`Hello %s In %d`), c.Str("LLGO"), 2024)
|
||||
|
||||
if res := L.PCall(3, 1, 0); res != lua.OK {
|
||||
c.Printf(c.Str("error: %s\n"), L.ToString(-1))
|
||||
if res := L.Pcall(3, 1, 0); res != lua.OK {
|
||||
c.Printf(c.Str("error: %s\n"), L.Tostring(-1))
|
||||
}
|
||||
|
||||
if res := L.IsString(-1); res != 0 {
|
||||
result := L.ToString(-1)
|
||||
if res := L.Isstring(-1); res != 0 {
|
||||
result := L.Tostring(-1)
|
||||
c.Printf(c.Str("result: %s\n"), result)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,10 +8,14 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
L := lua.NewState()
|
||||
L := lua.Newstate()
|
||||
defer L.Close()
|
||||
L.OpenLibs()
|
||||
if res := L.DoString(c.Str("print('hello world')")); res != lua.OK {
|
||||
L.Openlibs()
|
||||
if res := L.Dostring(c.Str("print('hello world')")); res != lua.OK {
|
||||
println("error")
|
||||
}
|
||||
}
|
||||
|
||||
/* Expected output:
|
||||
hello world
|
||||
*/
|
||||
|
||||
@@ -8,15 +8,19 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
L := lua.NewState()
|
||||
L := lua.Newstate()
|
||||
defer L.Close()
|
||||
|
||||
L.OpenLibs()
|
||||
if res := L.LoadString(c.Str("print('hello world')")); res != lua.OK {
|
||||
L.Openlibs()
|
||||
if res := L.Loadstring(c.Str("print('hello world')")); res != lua.OK {
|
||||
println("error")
|
||||
}
|
||||
if res := L.PCall(0, 0, 0); res != lua.OK {
|
||||
if res := L.Pcall(0, 0, 0); res != lua.OK {
|
||||
println("error")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Expected output:
|
||||
hello world
|
||||
*/
|
||||
|
||||
125
c/lua/_demo/metatable/metatable.go
Normal file
125
c/lua/_demo/metatable/metatable.go
Normal file
@@ -0,0 +1,125 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/goplus/llgo/c"
|
||||
"github.com/goplus/llgo/c/lua"
|
||||
)
|
||||
|
||||
func toString(L *lua.State) c.Int {
|
||||
L.Pushstring(c.Str("Hello from metatable!"))
|
||||
return 1
|
||||
}
|
||||
|
||||
func printStack(L *lua.State, message string) {
|
||||
top := L.Gettop()
|
||||
c.Printf(c.Str("%s - Stack size: %d\n"), c.AllocaCStr(message), c.Int(top))
|
||||
for i := c.Int(1); i <= top; i++ {
|
||||
t := L.Type(i)
|
||||
switch t {
|
||||
case c.Int(lua.STRING):
|
||||
c.Printf(c.Str(" %d: string: %s\n"), c.Int(i), L.Tostring(i))
|
||||
case c.Int(lua.BOOLEAN):
|
||||
c.Printf(c.Str(" %d: boolean: %v\n"), c.Int(i), L.Toboolean(i))
|
||||
case c.Int(lua.NUMBER):
|
||||
c.Printf(c.Str(" %d: number: %f\n"), c.Int(i), L.Tonumber(i))
|
||||
default:
|
||||
c.Printf(c.Str(" %d: %s\n"), c.Int(i), L.Typename(t))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
L := lua.Newstate()
|
||||
defer L.Close()
|
||||
|
||||
L.Openlibs()
|
||||
|
||||
L.Newtable()
|
||||
printStack(L, "After creating main table")
|
||||
|
||||
L.Newtable()
|
||||
printStack(L, "After creating metatable")
|
||||
|
||||
L.Pushcfunction(toString)
|
||||
printStack(L, "After Push CFunction")
|
||||
|
||||
L.Setfield(-2, c.Str("__tostring"))
|
||||
printStack(L, "After setting __tostring")
|
||||
|
||||
if L.Setmetatable(-2) == 0 {
|
||||
c.Printf(c.Str("Failed to set metatable\n"))
|
||||
}
|
||||
printStack(L, "After setting metatable")
|
||||
|
||||
L.Setglobal(c.Str("obj"))
|
||||
printStack(L, "After setting global obj")
|
||||
|
||||
testcode := c.Str(`
|
||||
if obj == nil then
|
||||
print('obj is not defined')
|
||||
else
|
||||
local mt = getmetatable(obj)
|
||||
if not mt then
|
||||
print('Metatable not set')
|
||||
elseif not mt.__tostring then
|
||||
print('__tostring not set in metatable')
|
||||
else
|
||||
print(mt.__tostring(obj))
|
||||
end
|
||||
end
|
||||
`)
|
||||
|
||||
if L.Dostring(testcode) != lua.OK {
|
||||
c.Printf(c.Str("Error: %s\n"), L.Tostring(-1))
|
||||
}
|
||||
|
||||
L.Getglobal(c.Str("obj"))
|
||||
if L.Getmetatable(-1) != 0 {
|
||||
c.Printf(c.Str("Metatable get success\n"))
|
||||
L.Pushstring(c.Str("__tostring"))
|
||||
L.Gettable(-2)
|
||||
if L.Isfunction(-1) {
|
||||
c.Printf(c.Str("__tostring function found in metatable\n"))
|
||||
if L.Iscfunction(-1) != 0 {
|
||||
c.Printf(c.Str("__tostring is a C function\n"))
|
||||
cfunc := L.Tocfunction(-1)
|
||||
if cfunc != nil {
|
||||
c.Printf(c.Str("Successfully retrieved __tostring C function pointer\n"))
|
||||
L.Pushcfunction(cfunc)
|
||||
if L.Call(0, 1) == lua.OK {
|
||||
result := L.Tostring(-1)
|
||||
c.Printf(c.Str("Result of calling __tostring: %s\n"), result)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
c.Printf(c.Str("__tostring function not found in metatable\n"))
|
||||
}
|
||||
} else {
|
||||
c.Printf(c.Str("No metatable found using GetTable\n"))
|
||||
}
|
||||
}
|
||||
|
||||
/* Expected output:
|
||||
After creating main table - Stack size: 1
|
||||
1: table
|
||||
After creating metatable - Stack size: 2
|
||||
1: table
|
||||
2: table
|
||||
After Push CFunction - Stack size: 3
|
||||
1: table
|
||||
2: table
|
||||
3: function
|
||||
After setting __tostring - Stack size: 2
|
||||
1: table
|
||||
2: table
|
||||
After setting metatable - Stack size: 1
|
||||
1: table
|
||||
After setting global obj - Stack size: 0
|
||||
Hello from metatable!
|
||||
Metatable get success
|
||||
__tostring function found in metatable
|
||||
__tostring is a C function
|
||||
Successfully retrieved __tostring C function pointer
|
||||
Result of calling __tostring: Hello from metatable!
|
||||
*/
|
||||
@@ -7,24 +7,24 @@ import (
|
||||
|
||||
// printStack prints the current stack of the given Lua state.
|
||||
func printStack(L *lua.State, stateName *c.Char) {
|
||||
top := L.GetTop()
|
||||
top := L.Gettop()
|
||||
c.Printf(c.Str("%s stack (top=%d):"), stateName, top)
|
||||
for i := 1; i <= int(top); i++ {
|
||||
c.Printf(c.Str("%s "), L.ToString(c.Int(i)))
|
||||
c.Printf(c.Str("%s "), L.Tostring(c.Int(i)))
|
||||
}
|
||||
c.Printf(c.Str("\n"))
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Create a new Lua state and open libraries
|
||||
L := lua.NewState()
|
||||
L := lua.Newstate()
|
||||
defer L.Close()
|
||||
L.OpenLibs()
|
||||
L.Openlibs()
|
||||
|
||||
// Push initial values onto the stack
|
||||
L.PushString(c.Str("Hello"))
|
||||
L.PushString(c.Str("LLGO"))
|
||||
L.PushNumber(2024)
|
||||
L.Pushstring(c.Str("Hello"))
|
||||
L.Pushstring(c.Str("LLGO"))
|
||||
L.Pushnumber(2024)
|
||||
|
||||
// Print initial stack
|
||||
c.Printf(c.Str("Initial stack:\n"))
|
||||
@@ -32,11 +32,11 @@ func main() {
|
||||
|
||||
// Use absindex to ensure the index is positive
|
||||
idx := -2
|
||||
absIdx := L.AbsIndex(c.Int(idx))
|
||||
absIdx := L.Absindex(c.Int(idx))
|
||||
c.Printf(c.Str("Absolute index of 'LLGO': %d\n"), absIdx)
|
||||
|
||||
// Copy 'LLGO' to the top of the stack
|
||||
L.PushValue(absIdx)
|
||||
L.Pushvalue(absIdx)
|
||||
c.Printf(c.Str("\nAfter pushing 'LLGO' to the top:\n"))
|
||||
printStack(L, c.Str("L1"))
|
||||
|
||||
@@ -51,29 +51,54 @@ func main() {
|
||||
printStack(L, c.Str("L1"))
|
||||
|
||||
// Check if we can grow the stack
|
||||
if L.CheckStack(c.Int(2)) == 0 {
|
||||
if L.Checkstack(c.Int(2)) == 0 {
|
||||
c.Printf(c.Str("Cannot grow stack\n"))
|
||||
return
|
||||
}
|
||||
|
||||
// Push additional elements
|
||||
L.PushNumber(3.14)
|
||||
L.PushString(c.Str("Lua"))
|
||||
L.Pushnumber(3.14)
|
||||
L.Pushstring(c.Str("Lua"))
|
||||
c.Printf(c.Str("\nAfter pushing more elements:\n"))
|
||||
printStack(L, c.Str("L1"))
|
||||
|
||||
// Set the top of the stack, clearing extra elements
|
||||
L.SetTop(c.Int(5))
|
||||
L.Settop(c.Int(5))
|
||||
c.Printf(c.Str("\nAfter setting top to 5:\n"))
|
||||
printStack(L, c.Str("L1"))
|
||||
|
||||
// Create a second Lua state
|
||||
L1 := lua.NewState()
|
||||
L1 := lua.Newstate()
|
||||
defer L1.Close()
|
||||
|
||||
// Move two elements to the new state
|
||||
L.XMove(L1, c.Int(2))
|
||||
L.Xmove(L1, c.Int(2))
|
||||
c.Printf(c.Str("\nAfter moving two elements to L1:\n"))
|
||||
printStack(L, c.Str("L1"))
|
||||
printStack(L1, c.Str("L2"))
|
||||
}
|
||||
|
||||
/* Expected output:
|
||||
Initial stack:
|
||||
L1 stack (top=3):Hello LLGO 2024.0
|
||||
Absolute index of 'LLGO': 2
|
||||
|
||||
After pushing 'LLGO' to the top:
|
||||
L1 stack (top=4):Hello LLGO 2024.0 LLGO
|
||||
|
||||
After rotating the stack:
|
||||
L1 stack (top=4):LLGO 2024.0 LLGO Hello
|
||||
|
||||
After copying the top element to index 2:
|
||||
L1 stack (top=4):LLGO Hello LLGO Hello
|
||||
|
||||
After pushing more elements:
|
||||
L1 stack (top=6):LLGO Hello LLGO Hello 3.14 Lua
|
||||
|
||||
After setting top to 5:
|
||||
L1 stack (top=5):LLGO Hello LLGO Hello 3.14
|
||||
|
||||
After moving two elements to L1:
|
||||
L1 stack (top=3):LLGO Hello LLGO
|
||||
L2 stack (top=2):Hello 3.14
|
||||
*/
|
||||
|
||||
@@ -6,10 +6,10 @@ import (
|
||||
)
|
||||
|
||||
func printTable(L *lua.State) {
|
||||
L.PushNil()
|
||||
L.Pushnil()
|
||||
for L.Next(-2) != 0 {
|
||||
key := L.ToString(-2)
|
||||
value := L.ToString(-1)
|
||||
key := L.Tostring(-2)
|
||||
value := L.Tostring(-1)
|
||||
c.Printf(c.Str("%s - %s\n"), key, value)
|
||||
L.Pop(1)
|
||||
}
|
||||
@@ -17,31 +17,31 @@ func printTable(L *lua.State) {
|
||||
}
|
||||
|
||||
func main() {
|
||||
L := lua.NewState()
|
||||
L := lua.Newstate()
|
||||
defer L.Close()
|
||||
|
||||
L.OpenLibs()
|
||||
L.Openlibs()
|
||||
|
||||
L.NewTable()
|
||||
L.Newtable()
|
||||
|
||||
L.PushString(c.Str("name"))
|
||||
L.PushString(c.Str("John"))
|
||||
L.SetTable(-3)
|
||||
L.Pushstring(c.Str("name"))
|
||||
L.Pushstring(c.Str("John"))
|
||||
L.Settable(-3)
|
||||
|
||||
L.PushString(c.Str("age"))
|
||||
L.PushNumber(30)
|
||||
L.SetTable(-3)
|
||||
L.Pushstring(c.Str("age"))
|
||||
L.Pushnumber(30)
|
||||
L.Settable(-3)
|
||||
|
||||
L.PushString(c.Str("John Doe"))
|
||||
L.SetField(-2, c.Str("fullname"))
|
||||
L.Pushstring(c.Str("John Doe"))
|
||||
L.Setfield(-2, c.Str("fullname"))
|
||||
|
||||
L.GetField(-1, c.Str("name"))
|
||||
c.Printf(c.Str("%s\n"), L.ToString(-1))
|
||||
L.Getfield(-1, c.Str("name"))
|
||||
c.Printf(c.Str("%s\n"), L.Tostring(-1))
|
||||
L.Pop(1)
|
||||
|
||||
L.PushString(c.Str("age"))
|
||||
L.GetTable(-2)
|
||||
age := int(L.ToNumber(-1))
|
||||
L.Pushstring(c.Str("age"))
|
||||
L.Gettable(-2)
|
||||
age := int(L.Tonumber(-1))
|
||||
c.Printf(c.Str("Age: %d\n"), age)
|
||||
L.Pop(1)
|
||||
|
||||
@@ -49,3 +49,12 @@ func main() {
|
||||
printTable(L)
|
||||
|
||||
}
|
||||
|
||||
/* Expected output:
|
||||
John
|
||||
Age: 30
|
||||
All entries in the table:
|
||||
age - 30.0
|
||||
fullname - John Doe
|
||||
name - John
|
||||
*/
|
||||
|
||||
@@ -16,16 +16,16 @@ import (
|
||||
|
||||
// /* predefined references */
|
||||
|
||||
// llgo:link (*State).LoadFilex C.luaL_loadfilex
|
||||
func (L *State) LoadFilex(filename *c.Char, mode *c.Char) c.Int { return 0 }
|
||||
// llgo:link (*State).Loadfilex C.luaL_loadfilex
|
||||
func (L *State) Loadfilex(filename *c.Char, mode *c.Char) c.Int { return 0 }
|
||||
|
||||
func (L *State) LoadFile(filename *c.Char) c.Int { return L.LoadFilex(filename, nil) }
|
||||
func (L *State) Loadfile(filename *c.Char) c.Int { return L.Loadfilex(filename, nil) }
|
||||
|
||||
// llgo:link (*State).LoadString C.luaL_loadstring
|
||||
func (L *State) LoadString(s *c.Char) c.Int { return 0 }
|
||||
// llgo:link (*State).Loadstring C.luaL_loadstring
|
||||
func (L *State) Loadstring(s *c.Char) c.Int { return 0 }
|
||||
|
||||
//go:linkname NewState C.luaL_newstate
|
||||
func NewState() *State
|
||||
//go:linkname Newstate C.luaL_newstate
|
||||
func Newstate() *State
|
||||
|
||||
// /*
|
||||
// ** ===============================================================
|
||||
@@ -33,18 +33,18 @@ func NewState() *State
|
||||
// ** ===============================================================
|
||||
// */
|
||||
|
||||
func (L *State) DoFile(filename *c.Char) c.Int {
|
||||
if loadResult := L.LoadFile(filename); loadResult != 0 {
|
||||
func (L *State) Dofile(filename *c.Char) c.Int {
|
||||
if loadResult := L.Loadfile(filename); loadResult != 0 {
|
||||
return loadResult
|
||||
}
|
||||
return L.PCall(c.Int(0), c.Int(MULTRET), c.Int(0))
|
||||
return L.Pcall(c.Int(0), c.Int(MULTRET), c.Int(0))
|
||||
}
|
||||
|
||||
func (L *State) DoString(str *c.Char) c.Int {
|
||||
if loadResult := L.LoadString(str); loadResult != 0 {
|
||||
func (L *State) Dostring(str *c.Char) c.Int {
|
||||
if loadResult := L.Loadstring(str); loadResult != 0 {
|
||||
return loadResult
|
||||
}
|
||||
return L.PCall(c.Int(0), c.Int(MULTRET), c.Int(0))
|
||||
return L.Pcall(c.Int(0), c.Int(MULTRET), c.Int(0))
|
||||
}
|
||||
|
||||
// /*
|
||||
|
||||
247
c/lua/lua.go
247
c/lua/lua.go
@@ -41,17 +41,17 @@ type State struct {
|
||||
// ** basic types
|
||||
// */
|
||||
const (
|
||||
NONE = int(-1)
|
||||
NIL = int(0)
|
||||
BOOLEAN = int(1)
|
||||
LIGHTUSERDATA = int(2)
|
||||
NUMBER = int(3)
|
||||
STRING = int(4)
|
||||
TABLE = int(5)
|
||||
FUNCTION = int(6)
|
||||
USERDATA = int(7)
|
||||
THREAD = int(8)
|
||||
UMTYPES = int(9)
|
||||
NONE c.Int = -1
|
||||
NIL c.Int = 0
|
||||
BOOLEAN c.Int = 1
|
||||
LIGHTUSERDATA c.Int = 2
|
||||
NUMBER c.Int = 3
|
||||
STRING c.Int = 4
|
||||
TABLE c.Int = 5
|
||||
FUNCTION c.Int = 6
|
||||
USERDATA c.Int = 7
|
||||
THREAD c.Int = 8
|
||||
UMTYPES c.Int = 9
|
||||
)
|
||||
|
||||
// /* minimum Lua stack available to a C function */
|
||||
@@ -78,13 +78,15 @@ type Integer = c.Int
|
||||
type Unsigned = c.Uint
|
||||
|
||||
// /* type for continuation-function contexts */
|
||||
// TODO(zzy): Context may not be c.Int
|
||||
type KContext c.Int
|
||||
type KContext = c.Pointer
|
||||
|
||||
// /*
|
||||
// ** Type for C functions registered with Lua
|
||||
// */
|
||||
|
||||
// llgo:type C
|
||||
type CFunction func(L *State) c.Int
|
||||
|
||||
// /*
|
||||
// ** Type for continuation functions
|
||||
// */
|
||||
@@ -144,10 +146,9 @@ type KFunction func(L *State, status c.Int, ctx KContext) c.Int
|
||||
func (L *State) Close() {}
|
||||
|
||||
// State *(lua_newstate) (lua_Alloc f, void *ud);
|
||||
// State *(lua_newthread) (State *L);
|
||||
|
||||
// llgo:link (*State).NewThread C.lua_newthread
|
||||
func (L *State) NewThread() *State { return nil }
|
||||
// llgo:link (*State).Newthread C.lua_newthread
|
||||
func (L *State) Newthread() *State { return nil }
|
||||
|
||||
// int (lua_closethread) (State *L, State *from);
|
||||
// int (lua_resetthread) (State *L); /* Deprecated! */
|
||||
@@ -158,17 +159,17 @@ func (L *State) NewThread() *State { return nil }
|
||||
// ** basic stack manipulation
|
||||
// */
|
||||
|
||||
// llgo:link (*State).AbsIndex C.lua_absindex
|
||||
func (L *State) AbsIndex(idx c.Int) c.Int { return 0 }
|
||||
// llgo:link (*State).Absindex C.lua_absindex
|
||||
func (L *State) Absindex(idx c.Int) c.Int { return 0 }
|
||||
|
||||
// llgo:link (*State).GetTop C.lua_gettop
|
||||
func (L *State) GetTop() c.Int { return 0 }
|
||||
// llgo:link (*State).Gettop C.lua_gettop
|
||||
func (L *State) Gettop() c.Int { return 0 }
|
||||
|
||||
// llgo:link (*State).SetTop C.lua_settop
|
||||
func (L *State) SetTop(idx c.Int) {}
|
||||
// llgo:link (*State).Settop C.lua_settop
|
||||
func (L *State) Settop(idx c.Int) {}
|
||||
|
||||
// llgo:link (*State).PushValue C.lua_pushvalue
|
||||
func (L *State) PushValue(idx c.Int) {}
|
||||
// llgo:link (*State).Pushvalue C.lua_pushvalue
|
||||
func (L *State) Pushvalue(idx c.Int) {}
|
||||
|
||||
// llgo:link (*State).Rotate C.lua_rotate
|
||||
func (L *State) Rotate(idx c.Int, n c.Int) {}
|
||||
@@ -176,50 +177,53 @@ func (L *State) Rotate(idx c.Int, n c.Int) {}
|
||||
// llgo:link (*State).Copy C.lua_copy
|
||||
func (L *State) Copy(fromidx c.Int, toidx c.Int) {}
|
||||
|
||||
// llgo:link (*State).CheckStack C.lua_checkstack
|
||||
func (L *State) CheckStack(n c.Int) c.Int { return 0 }
|
||||
// llgo:link (*State).Checkstack C.lua_checkstack
|
||||
func (L *State) Checkstack(n c.Int) c.Int { return 0 }
|
||||
|
||||
// llgo:link (*State).XMove C.lua_xmove
|
||||
func (L *State) XMove(to *State, n c.Int) {}
|
||||
// llgo:link (*State).Xmove C.lua_xmove
|
||||
func (L *State) Xmove(to *State, n c.Int) {}
|
||||
|
||||
// /*
|
||||
// ** access functions (stack -> C)
|
||||
// */
|
||||
// LUA_API int (lua_isinteger) (State *L, int idx);
|
||||
// llgo:link (*State).IsInteger C.lua_isinteger
|
||||
func (L *State) IsInteger(idx c.Int) c.Int { return 0 }
|
||||
|
||||
// llgo:link (*State).IsNumber C.lua_isnumber
|
||||
func (L *State) IsNumber(idx c.Int) c.Int { return 0 }
|
||||
// llgo:link (*State).Isnumber C.lua_isnumber
|
||||
func (L *State) Isnumber(idx c.Int) c.Int { return 0 }
|
||||
|
||||
// llgo:link (*State).IsString C.lua_isstring
|
||||
func (L *State) IsString(idx c.Int) c.Int { return 0 }
|
||||
// llgo:link (*State).Isstring C.lua_isstring
|
||||
func (L *State) Isstring(idx c.Int) c.Int { return 0 }
|
||||
|
||||
// llgo:link (*State).Iscfunction C.lua_iscfunction
|
||||
func (L *State) Iscfunction(idx c.Int) c.Int { return 0 }
|
||||
|
||||
// llgo:link (*State).Isinteger C.lua_isinteger
|
||||
func (L *State) Isinteger(idx c.Int) c.Int { return 0 }
|
||||
|
||||
// LUA_API int (lua_isuserdata) (State *L, int idx);
|
||||
|
||||
// TODO(zzy):add to demo
|
||||
// llgo:link (*State).Type C.lua_type
|
||||
func (L *State) Type(idx c.Int) c.Int { return 0 }
|
||||
|
||||
// TODO(zzy)
|
||||
// llgo:link (*State).TypeName C.lua_typename
|
||||
func (L *State) TypeName(tp c.Int) *c.Char { return nil }
|
||||
// llgo:link (*State).Typename C.lua_typename
|
||||
func (L *State) Typename(tp c.Int) *c.Char { return nil }
|
||||
|
||||
// llgo:link (*State).ToNumberx C.lua_tonumberx
|
||||
func (L *State) ToNumberx(idx c.Int, isnum *c.Int) Number { return 0 }
|
||||
// llgo:link (*State).Tonumberx C.lua_tonumberx
|
||||
func (L *State) Tonumberx(idx c.Int, isnum *c.Int) Number { return 0 }
|
||||
|
||||
// llgo:link (*State).ToIntegerx C.lua_tointegerx
|
||||
func (L *State) ToIntegerx(idx c.Int, isnum *c.Int) Integer { return 0 }
|
||||
// llgo:link (*State).Tointegerx C.lua_tointegerx
|
||||
func (L *State) Tointegerx(idx c.Int, isnum *c.Int) Integer { return 0 }
|
||||
|
||||
// llgo:link (*State).ToBoolean C.lua_toboolean
|
||||
func (L *State) ToBoolean(idx c.Int) bool { return false }
|
||||
// llgo:link (*State).Toboolean C.lua_toboolean
|
||||
func (L *State) Toboolean(idx c.Int) bool { return false }
|
||||
|
||||
// llgo:link (*State).ToLString C.lua_tolstring
|
||||
func (L *State) ToLString(idx c.Int, len *c.Ulong) *c.Char { return nil }
|
||||
|
||||
// LUA_API int (lua_iscfunction) (State *L, int idx);
|
||||
// LUA_API int (lua_isuserdata) (State *L, int idx);
|
||||
// llgo:link (*State).Tolstring C.lua_tolstring
|
||||
func (L *State) Tolstring(idx c.Int, len *c.Ulong) *c.Char { return nil }
|
||||
|
||||
// LUA_API lua_Unsigned (lua_rawlen) (State *L, int idx);
|
||||
// LUA_API lua_CFunction (lua_tocfunction) (State *L, int idx);
|
||||
|
||||
// llgo:link (*State).Tocfunction C.lua_tocfunction
|
||||
func (L *State) Tocfunction(idx c.Int) CFunction { return nil }
|
||||
|
||||
// LUA_API void *(lua_touserdata) (State *L, int idx);
|
||||
// LUA_API State *(lua_tothread) (State *L, int idx);
|
||||
// LUA_API const void *(lua_topointer) (State *L, int idx);
|
||||
@@ -231,33 +235,30 @@ func (L *State) ToLString(idx c.Int, len *c.Ulong) *c.Char { return nil }
|
||||
// /*
|
||||
// ** push functions (C -> stack)
|
||||
// */
|
||||
// llgo:link (*State).PushNil C.lua_pushnil
|
||||
func (L *State) PushNil() {}
|
||||
// llgo:link (*State).Pushnil C.lua_pushnil
|
||||
func (L *State) Pushnil() {}
|
||||
|
||||
// llgo:link (*State).PushNumber C.lua_pushnumber
|
||||
func (L *State) PushNumber(n Number) {}
|
||||
// llgo:link (*State).Pushnumber C.lua_pushnumber
|
||||
func (L *State) Pushnumber(n Number) {}
|
||||
|
||||
// llgo:link (*State).PushInteger C.lua_pushinteger
|
||||
func (L *State) PushInteger(n Integer) {}
|
||||
// llgo:link (*State).Pushinteger C.lua_pushinteger
|
||||
func (L *State) Pushinteger(n Integer) {}
|
||||
|
||||
// llgo:link (*State).PushString C.lua_pushstring
|
||||
func (L *State) PushString(s *c.Char) *c.Char {
|
||||
return nil
|
||||
}
|
||||
// llgo:link (*State).Pushlstring C.lua_pushlstring
|
||||
func (L *State) Pushlstring(s *c.Char, len c.Ulong) *c.Char { return nil }
|
||||
|
||||
// llgo:link (*State).PushLString C.lua_pushlstring
|
||||
func (L *State) PushLString(s *c.Char, len c.Ulong) *c.Char {
|
||||
return nil
|
||||
}
|
||||
// llgo:link (*State).Pushstring C.lua_pushstring
|
||||
func (L *State) Pushstring(s *c.Char) *c.Char { return nil }
|
||||
|
||||
// llgo:link (*State).PushFString C.lua_pushfstring
|
||||
func (L *State) PushFString(format *c.Char, __llgo_va_list ...any) *c.Char { return nil }
|
||||
// llgo:link (*State).Pushfstring C.lua_pushfstring
|
||||
func (L *State) Pushfstring(format *c.Char, __llgo_va_list ...any) *c.Char { return nil }
|
||||
|
||||
// llgo:link (*State).PushBoolean C.lua_pushboolean
|
||||
func (L *State) PushBoolean(b c.Int) {}
|
||||
// llgo:link (*State).Pushcclosure C.lua_pushcclosure
|
||||
func (L *State) Pushcclosure(fn CFunction, n c.Int) {}
|
||||
|
||||
// llgo:link (*State).Pushboolean C.lua_pushboolean
|
||||
func (L *State) Pushboolean(b c.Int) {}
|
||||
|
||||
//const char *(lua_pushvfstring) (State *L, const char *fmt,va_list argp);
|
||||
//void (lua_pushcclosure) (State *L, lua_CFunction fn, int n);
|
||||
//void (lua_pushlightuserdata) (State *L, void *p);
|
||||
//int (lua_pushthread) (State *L);
|
||||
|
||||
@@ -265,63 +266,74 @@ func (L *State) PushBoolean(b c.Int) {}
|
||||
// ** get functions (Lua -> stack)
|
||||
// */
|
||||
|
||||
// llgo:link (*State).GetGlobal C.lua_getglobal
|
||||
func (L *State) GetGlobal(name *c.Char) c.Int { return 0 }
|
||||
// llgo:link (*State).Getglobal C.lua_getglobal
|
||||
func (L *State) Getglobal(name *c.Char) c.Int { return 0 }
|
||||
|
||||
// llgo:link (*State).GetTable C.lua_gettable
|
||||
func (L *State) GetTable(idx c.Int) c.Int { return 0 }
|
||||
// llgo:link (*State).Gettable C.lua_gettable
|
||||
func (L *State) Gettable(idx c.Int) c.Int { return 0 }
|
||||
|
||||
// llgo:link (*State).GetField C.lua_getfield
|
||||
func (L *State) GetField(idx c.Int, k *c.Char) c.Int { return 0 }
|
||||
|
||||
// llgo:link (*State).CreateTable C.lua_createtable
|
||||
func (L *State) CreateTable(narr c.Int, nrec c.Int) {}
|
||||
// llgo:link (*State).Getfield C.lua_getfield
|
||||
func (L *State) Getfield(idx c.Int, k *c.Char) c.Int { return 0 }
|
||||
|
||||
// LUA_API int (lua_geti) (State *L, int idx, lua_Integer n);
|
||||
// LUA_API int (lua_rawget) (State *L, int idx);
|
||||
// LUA_API int (lua_rawgeti) (State *L, int idx, lua_Integer n);
|
||||
// LUA_API int (lua_rawgetp) (State *L, int idx, const void *p);
|
||||
|
||||
// llgo:link (*State).Createtable C.lua_createtable
|
||||
func (L *State) Createtable(narr c.Int, nrec c.Int) {}
|
||||
|
||||
// LUA_API void *(lua_newuserdatauv) (State *L, size_t sz, int nuvalue);
|
||||
// LUA_API int (lua_getmetatable) (State *L, int objindex);
|
||||
|
||||
// llgo:link (*State).Getmetatable C.lua_getmetatable
|
||||
func (L *State) Getmetatable(objindex c.Int) c.Int { return 0 }
|
||||
|
||||
// LUA_API int (lua_getiuservalue) (State *L, int idx, int n);
|
||||
|
||||
// /*
|
||||
// ** set functions (stack -> Lua)
|
||||
// */
|
||||
|
||||
// TODO(zzy):add to demo
|
||||
// llgo:link (*State).SetGlobal C.lua_setglobal
|
||||
func (L *State) SetGlobal(name *c.Char) {}
|
||||
// llgo:link (*State).Setglobal C.lua_setglobal
|
||||
func (L *State) Setglobal(name *c.Char) {}
|
||||
|
||||
// llgo:link (*State).SetTable C.lua_settable
|
||||
func (L *State) SetTable(idx c.Int) {}
|
||||
// llgo:link (*State).Settable C.lua_settable
|
||||
func (L *State) Settable(idx c.Int) {}
|
||||
|
||||
// llgo:link (*State).SetField C.lua_setfield
|
||||
func (L *State) SetField(idx c.Int, k *c.Char) {}
|
||||
// llgo:link (*State).Setfield C.lua_setfield
|
||||
func (L *State) Setfield(idx c.Int, k *c.Char) {}
|
||||
|
||||
//void (lua_seti) (State *L, int idx, lua_Integer n);
|
||||
//void (lua_rawset) (State *L, int idx);
|
||||
//void (lua_rawseti) (State *L, int idx, lua_Integer n);
|
||||
//void (lua_rawsetp) (State *L, int idx, const void *p);
|
||||
//int (lua_setmetatable) (State *L, int objindex);
|
||||
|
||||
// llgo:link (*State).Setmetatable C.lua_setmetatable
|
||||
func (L *State) Setmetatable(objindex c.Int) c.Int { return 0 }
|
||||
|
||||
//int (lua_setiuservalue) (State *L, int idx, int n);
|
||||
|
||||
// /*
|
||||
// ** 'load' and 'call' functions (load and run Lua code)
|
||||
// */
|
||||
|
||||
// llgo:link (*State).PCallk C.lua_pcallk
|
||||
func (L *State) PCallk(nargs c.Int, nresults c.Int, errfunc c.Int, ctx KContext, k *KFunction) c.Int {
|
||||
// llgo:link (*State).Callk C.lua_callk
|
||||
func (L *State) Callk(nargs c.Int, nresults c.Int, ctx KContext, k KFunction) c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (L *State) PCall(nargs c.Int, nresults c.Int, errfunc c.Int) c.Int {
|
||||
return L.PCallk(nargs, nresults, errfunc, KContext(c.Int(0)), nil)
|
||||
func (L *State) Call(nargs c.Int, nresults c.Int) c.Int {
|
||||
return L.Callk(nargs, nresults, nil, nil)
|
||||
}
|
||||
|
||||
// void (lua_callk) (State *L, int nargs, int nresults, lua_KContext ctx, lua_KFunction k);
|
||||
// #define lua_call(L,n,r) lua_callk(L, (n), (r), 0, NULL)
|
||||
// llgo:link (*State).Pcallk C.lua_pcallk
|
||||
func (L *State) Pcallk(nargs c.Int, nresults c.Int, errfunc c.Int, ctx KContext, k KFunction) c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (L *State) Pcall(nargs c.Int, nresults c.Int, errfunc c.Int) c.Int {
|
||||
return L.Pcallk(nargs, nresults, errfunc, nil, nil)
|
||||
}
|
||||
|
||||
// int (lua_load) (State *L, lua_Reader reader, void *dt, const char *chunkname, const char *mode);
|
||||
|
||||
@@ -337,12 +349,12 @@ func (L *State) Resume(from *State, narg c.Int, nres *c.Int) c.Int { return 0 }
|
||||
// llgo:link (*State).Status C.lua_status
|
||||
func (L *State) Status() c.Int { return 0 }
|
||||
|
||||
// llgo:link (*State).IsYieldable C.lua_isyieldable
|
||||
func (L *State) IsYieldable() c.Int { return 0 }
|
||||
// llgo:link (*State).Isyieldable C.lua_isyieldable
|
||||
func (L *State) Isyieldable() c.Int { return 0 }
|
||||
|
||||
// TODO(zzy)
|
||||
// int (lua_yieldk) (State *L, int nresults, lua_KContext ctx, lua_KFunction k);
|
||||
// #define lua_yield(L,n) lua_yieldk(L, (n), 0, NULL)
|
||||
// llgo:link (*State).Yieldk C.lua_yieldk
|
||||
func (L *State) Yieldk(nresults c.Int, ctx KContext, k KFunction) c.Int { return 0 }
|
||||
func (L *State) Yield(nresults c.Int) c.Int { return L.Yieldk(nresults, nil, nil) }
|
||||
|
||||
// /*
|
||||
// ** Warning-related functions
|
||||
@@ -396,34 +408,31 @@ func (L *State) Next(idx c.Int) c.Int { return 0 }
|
||||
// ** ===============================================================
|
||||
// */
|
||||
|
||||
func (L *State) ToNumber(idx c.Int) Number { return L.ToNumberx(idx, nil) }
|
||||
func (L *State) ToString(idx c.Int) *c.Char { return L.ToLString(idx, nil) }
|
||||
func (L *State) ToInteger(idx c.Int) Integer { return L.ToIntegerx(idx, nil) }
|
||||
func (L *State) Pop(n c.Int) { L.SetTop(-(n) - 1) }
|
||||
func (L *State) NewTable() { L.CreateTable(0, 0) }
|
||||
func (L *State) IsFunction(n c.Int) bool { return L.Type(n) == c.Int(FUNCTION) }
|
||||
func (L *State) IsTable(n c.Int) bool { return L.Type(n) == c.Int(TABLE) }
|
||||
func (L *State) IsLightUserData(n c.Int) bool { return L.Type(n) == c.Int(LIGHTUSERDATA) }
|
||||
func (L *State) IsNil(n c.Int) bool { return L.Type(n) == c.Int(NIL) }
|
||||
func (L *State) IsBoolean(n c.Int) bool { return L.Type(n) == c.Int(BOOLEAN) }
|
||||
func (L *State) IsThread(n c.Int) bool { return L.Type(n) == c.Int(THREAD) }
|
||||
func (L *State) IsNone(n c.Int) bool { return L.Type(n) == c.Int(NONE) }
|
||||
func (L *State) IsNoneOrNil(n c.Int) bool { return L.Type(n) <= 0 }
|
||||
|
||||
// #define lua_getextraspace(L) ((void *)((char *)(L) - LUA_EXTRASPACE))
|
||||
|
||||
// #define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n)))
|
||||
func (L *State) Tonumber(idx c.Int) Number { return L.Tonumberx(idx, nil) }
|
||||
func (L *State) Tostring(idx c.Int) *c.Char { return L.Tolstring(idx, nil) }
|
||||
func (L *State) Tointeger(idx c.Int) Integer { return L.Tointegerx(idx, nil) }
|
||||
func (L *State) Pop(n c.Int) { L.Settop(-(n) - 1) }
|
||||
func (L *State) Newtable() { L.Createtable(0, 0) }
|
||||
|
||||
// #define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0)
|
||||
// #define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n)))
|
||||
func (L *State) Pushcfunction(f CFunction) { L.Pushcclosure(f, 0) }
|
||||
|
||||
func (L *State) Isfunction(n c.Int) bool { return L.Type(n) == c.Int(FUNCTION) }
|
||||
func (L *State) Istable(n c.Int) bool { return L.Type(n) == c.Int(TABLE) }
|
||||
func (L *State) Islightuserdata(n c.Int) bool { return L.Type(n) == c.Int(LIGHTUSERDATA) }
|
||||
func (L *State) Isnil(n c.Int) bool { return L.Type(n) == c.Int(NIL) }
|
||||
func (L *State) Isboolean(n c.Int) bool { return L.Type(n) == c.Int(BOOLEAN) }
|
||||
func (L *State) Isthread(n c.Int) bool { return L.Type(n) == c.Int(THREAD) }
|
||||
func (L *State) Isnone(n c.Int) bool { return L.Type(n) == c.Int(NONE) }
|
||||
func (L *State) Isnoneornil(n c.Int) bool { return L.Type(n) <= 0 }
|
||||
|
||||
// #define lua_pushliteral(L, s) lua_pushstring(L, "" s)
|
||||
|
||||
// #define lua_pushglobaltable(L) ((void)lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS))
|
||||
|
||||
// #define lua_insert(L,idx) lua_rotate(L, (idx), 1)
|
||||
|
||||
// #define lua_remove(L,idx) (lua_rotate(L, (idx), -1), lua_pop(L, 1))
|
||||
|
||||
// #define lua_replace(L,idx) (lua_copy(L, -1, (idx)), lua_pop(L, 1))
|
||||
|
||||
// /* }============================================================== */
|
||||
|
||||
@@ -4,5 +4,5 @@ import (
|
||||
_ "unsafe"
|
||||
)
|
||||
|
||||
// llgo:link (*State).OpenLibs C.luaL_openlibs
|
||||
func (L *State) OpenLibs() {}
|
||||
// llgo:link (*State).Openlibs C.luaL_openlibs
|
||||
func (L *State) Openlibs() {}
|
||||
|
||||
8
c/neco/README.md
Normal file
8
c/neco/README.md
Normal file
@@ -0,0 +1,8 @@
|
||||
llgo wrapper of tidwall/neco
|
||||
=====
|
||||
|
||||
## How to update source to llgo
|
||||
|
||||
```sh
|
||||
TODO
|
||||
```
|
||||
34
c/neco/_demo/cgen/_c/gen.c
Normal file
34
c/neco/_demo/cgen/_c/gen.c
Normal file
@@ -0,0 +1,34 @@
|
||||
#include "../../../_wrap/neco.h"
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void coroutine(int argc, void *argv[]) {
|
||||
// Yield each int to the caller, one at a time.
|
||||
for (int i = 0; i < 10; i++) {
|
||||
neco_gen_yield(&i);
|
||||
}
|
||||
}
|
||||
|
||||
static int __neco_main() {
|
||||
|
||||
// Create a new generator coroutine that is used to send ints.
|
||||
neco_gen *gen;
|
||||
neco_gen_start(&gen, sizeof(int), coroutine, 0);
|
||||
|
||||
// Iterate over each int until the generator is closed.
|
||||
int i;
|
||||
while (neco_gen_next(gen, &i) != NECO_CLOSED) {
|
||||
printf("%d\n", i);
|
||||
}
|
||||
|
||||
// This coroutine no longer needs the generator.
|
||||
neco_gen_release(gen);
|
||||
return 0;
|
||||
}
|
||||
static void _neco_main() { __neco_exit_prog(__neco_main()); }
|
||||
void run_main() {
|
||||
neco_env_setpaniconerror(true);
|
||||
neco_env_setcanceltype(NECO_CANCEL_ASYNC);
|
||||
int ret = neco_start(_neco_main, 0);
|
||||
fprintf(stderr, "neco_start: %s (code %d)\n", neco_strerror(ret), ret);
|
||||
};
|
||||
19
c/neco/_demo/cgen/cgen.go
Normal file
19
c/neco/_demo/cgen/cgen.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
_ "unsafe"
|
||||
|
||||
_ "github.com/goplus/llgo/c"
|
||||
)
|
||||
|
||||
const (
|
||||
LLGoFiles = "_c/gen.c; ../../_wrap/neco.c"
|
||||
LLGoPackage = "link"
|
||||
)
|
||||
|
||||
func main() {
|
||||
runMain()
|
||||
}
|
||||
|
||||
//go:linkname runMain C.run_main
|
||||
func runMain()
|
||||
37
c/neco/_demo/gen/gen.go
Normal file
37
c/neco/_demo/gen/gen.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/goplus/llgo/c"
|
||||
"github.com/goplus/llgo/c/neco"
|
||||
)
|
||||
|
||||
func coroutine(argc c.Int, argv *c.Pointer) {
|
||||
// Yield each int to the caller, one at a time.
|
||||
for i := 0; i < 10; i++ {
|
||||
neco.GenYield(unsafe.Pointer(&i))
|
||||
}
|
||||
}
|
||||
|
||||
func necoMain(argc c.Int, argv *c.Pointer) {
|
||||
// Create a new generator coroutine that is used to send ints.
|
||||
var gen *neco.Gen
|
||||
neco.GenStart(&gen, unsafe.Sizeof(0), coroutine, 0)
|
||||
|
||||
// Iterate over each int until the generator is closed.
|
||||
var i int
|
||||
for neco.GenNext(gen, unsafe.Pointer(&i)) != neco.CLOSED {
|
||||
c.Printf(c.Str("%d\n"), i)
|
||||
}
|
||||
|
||||
neco.GenRelease(gen)
|
||||
neco.ExitProg(0)
|
||||
}
|
||||
|
||||
func main() {
|
||||
neco.EnvSetpaniconerror(true)
|
||||
neco.EnvSetcanceltype(neco.CANCEL_ASYNC)
|
||||
var ret = neco.Start(necoMain, 0)
|
||||
c.Fprintf(c.Stderr, c.Str("neco_start: %s (code %d)\n"), neco.Strerror(ret), ret)
|
||||
}
|
||||
8762
c/neco/_wrap/neco.c
Normal file
8762
c/neco/_wrap/neco.c
Normal file
File diff suppressed because it is too large
Load Diff
453
c/neco/_wrap/neco.h
Normal file
453
c/neco/_wrap/neco.h
Normal file
@@ -0,0 +1,453 @@
|
||||
// https://github.com/tidwall/neco
|
||||
//
|
||||
// Copyright 2024 Joshua J Baker. All rights reserved.
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
//
|
||||
// Neco -- Coroutine library for C
|
||||
|
||||
#ifndef NECO_H
|
||||
#define NECO_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#ifdef _WIN32
|
||||
#include <ws2tcpip.h>
|
||||
#else
|
||||
#include <netdb.h>
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// basic operations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// @defgroup BasicOperations Basic operations
|
||||
/// Neco provides standard operations for starting a coroutine, sleeping,
|
||||
/// suspending, resuming, yielding to another coroutine, joining/waiting for
|
||||
/// child coroutines, and exiting a running coroutine.
|
||||
/// @{
|
||||
int neco_start(void(*coroutine)(int argc, void *argv[]), int argc, ...);
|
||||
int neco_startv(void(*coroutine)(int argc, void *argv[]), int argc, void *argv[]);
|
||||
int neco_yield(void);
|
||||
int neco_sleep(int64_t nanosecs);
|
||||
int neco_sleep_dl(int64_t deadline);
|
||||
int neco_join(int64_t id);
|
||||
int neco_join_dl(int64_t id, int64_t deadline);
|
||||
int neco_suspend(void);
|
||||
int neco_suspend_dl(int64_t deadline);
|
||||
int neco_resume(int64_t id);
|
||||
void neco_exit(void);
|
||||
int64_t neco_getid(void);
|
||||
int64_t neco_lastid(void);
|
||||
int64_t neco_starterid(void);
|
||||
/// @}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// channels
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// @defgroup Channels Channels
|
||||
/// Channels allow for sending and receiving values between coroutines.
|
||||
/// By default, sends and receives will block until the other side is ready.
|
||||
/// This allows the coroutines to synchronize without using locks or condition
|
||||
/// variables.
|
||||
/// @{
|
||||
typedef struct neco_chan neco_chan;
|
||||
|
||||
int neco_chan_make(neco_chan **chan, size_t data_size, size_t capacity);
|
||||
int neco_chan_retain(neco_chan *chan);
|
||||
int neco_chan_release(neco_chan *chan);
|
||||
int neco_chan_send(neco_chan *chan, void *data);
|
||||
int neco_chan_send_dl(neco_chan *chan, void *data, int64_t deadline);
|
||||
int neco_chan_broadcast(neco_chan *chan, void *data);
|
||||
int neco_chan_recv(neco_chan *chan, void *data);
|
||||
int neco_chan_recv_dl(neco_chan *chan, void *data, int64_t deadline);
|
||||
int neco_chan_tryrecv(neco_chan *chan, void *data);
|
||||
int neco_chan_close(neco_chan *chan);
|
||||
int neco_chan_select(int nchans, ...);
|
||||
int neco_chan_select_dl(int64_t deadline, int nchans, ...);
|
||||
int neco_chan_selectv(int nchans, neco_chan *chans[]);
|
||||
int neco_chan_selectv_dl(int nchans, neco_chan *chans[], int64_t deadline);
|
||||
int neco_chan_tryselect(int nchans, ...);
|
||||
int neco_chan_tryselectv(int nchans, neco_chan *chans[]);
|
||||
int neco_chan_case(neco_chan *chan, void *data);
|
||||
/// @}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// generators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// @defgroup Generators Generators
|
||||
/// A generator is a specialized iterator-bound coroutine that can produce a
|
||||
/// sequence of values to be iterated over.
|
||||
/// @{
|
||||
typedef struct neco_gen neco_gen;
|
||||
|
||||
int neco_gen_start(neco_gen **gen, size_t data_size, void(*coroutine)(int argc, void *argv[]), int argc, ...);
|
||||
int neco_gen_startv(neco_gen **gen, size_t data_size, void(*coroutine)(int argc, void *argv[]), int argc, void *argv[]);
|
||||
int neco_gen_retain(neco_gen *gen);
|
||||
int neco_gen_release(neco_gen *gen);
|
||||
int neco_gen_yield(void *data);
|
||||
int neco_gen_yield_dl(void *data, int64_t deadline);
|
||||
int neco_gen_next(neco_gen *gen, void *data);
|
||||
int neco_gen_next_dl(neco_gen *gen, void *data, int64_t deadline);
|
||||
int neco_gen_close(neco_gen *gen);
|
||||
/// @}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// synchronization mechanisms
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// @defgroup Mutexes Mutexes
|
||||
/// A mutex is synchronization mechanism that blocks access to variables by
|
||||
/// multiple coroutines at once. This enforces exclusive access by a coroutine
|
||||
/// to a variable or set of variables and helps to avoid data inconsistencies
|
||||
/// due to race conditions.
|
||||
/// @{
|
||||
typedef struct { _Alignas(16) char _[48]; } neco_mutex;
|
||||
|
||||
#define NECO_MUTEX_INITIALIZER { 0 }
|
||||
|
||||
int neco_mutex_init(neco_mutex *mutex);
|
||||
int neco_mutex_lock(neco_mutex *mutex);
|
||||
int neco_mutex_lock_dl(neco_mutex *mutex, int64_t deadline);
|
||||
int neco_mutex_trylock(neco_mutex *mutex);
|
||||
int neco_mutex_unlock(neco_mutex *mutex);
|
||||
int neco_mutex_rdlock(neco_mutex *mutex);
|
||||
int neco_mutex_rdlock_dl(neco_mutex *mutex, int64_t deadline);
|
||||
int neco_mutex_tryrdlock(neco_mutex *mutex);
|
||||
/// @}
|
||||
|
||||
/// @defgroup WaitGroups WaitGroups
|
||||
/// A WaitGroup waits for a multiple coroutines to finish.
|
||||
/// The main coroutine calls neco_waitgroup_add() to set the number of
|
||||
/// coroutines to wait for. Then each of the coroutines runs and calls
|
||||
/// neco_waitgroup_done() when complete.
|
||||
/// At the same time, neco_waitgroup_wait() can be used to block until all
|
||||
/// coroutines are completed.
|
||||
/// @{
|
||||
typedef struct { _Alignas(16) char _[48]; } neco_waitgroup;
|
||||
|
||||
#define NECO_WAITGROUP_INITIALIZER { 0 }
|
||||
|
||||
int neco_waitgroup_init(neco_waitgroup *waitgroup);
|
||||
int neco_waitgroup_add(neco_waitgroup *waitgroup, int delta);
|
||||
int neco_waitgroup_done(neco_waitgroup *waitgroup);
|
||||
int neco_waitgroup_wait(neco_waitgroup *waitgroup);
|
||||
int neco_waitgroup_wait_dl(neco_waitgroup *waitgroup, int64_t deadline);
|
||||
/// @}
|
||||
|
||||
/// @defgroup CondVar Condition variables
|
||||
/// A condition variable is a synchronization mechanism that allows coroutines
|
||||
/// to suspend execution until some condition is true.
|
||||
/// @{
|
||||
typedef struct { _Alignas(16) char _[48]; } neco_cond;
|
||||
#define NECO_COND_INITIALIZER { 0 }
|
||||
|
||||
int neco_cond_init(neco_cond *cond);
|
||||
int neco_cond_signal(neco_cond *cond);
|
||||
int neco_cond_broadcast(neco_cond *cond);
|
||||
int neco_cond_wait(neco_cond *cond, neco_mutex *mutex);
|
||||
int neco_cond_wait_dl(neco_cond *cond, neco_mutex *mutex, int64_t deadline);
|
||||
/// @}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// file descriptors
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// @defgroup Posix Posix wrappers
|
||||
/// Functions that work like their Posix counterpart but do not block, allowing
|
||||
/// for usage in a Neco coroutine.
|
||||
/// @{
|
||||
|
||||
// wrappers for various posix operations.
|
||||
ssize_t neco_read(int fd, void *data, size_t nbytes);
|
||||
ssize_t neco_read_dl(int fd, void *data, size_t nbytes, int64_t deadline);
|
||||
ssize_t neco_write(int fd, const void *data, size_t nbytes);
|
||||
ssize_t neco_write_dl(int fd, const void *data, size_t nbytes, int64_t deadline);
|
||||
int neco_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
|
||||
int neco_accept_dl(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int64_t deadline);
|
||||
int neco_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
|
||||
int neco_connect_dl(int sockfd, const struct sockaddr *addr, socklen_t addrlen, int64_t deadline);
|
||||
int neco_getaddrinfo(const char *node, const char *service,
|
||||
const struct addrinfo *hints, struct addrinfo **res);
|
||||
int neco_getaddrinfo_dl(const char *node, const char *service,
|
||||
const struct addrinfo *hints, struct addrinfo **res, int64_t deadline);
|
||||
/// @}
|
||||
|
||||
/// @defgroup Posix2 File descriptor helpers
|
||||
/// Functions for working with file descriptors.
|
||||
/// @{
|
||||
|
||||
// utility for enabling non-blocking on existing file descriptors
|
||||
int neco_setnonblock(int fd, bool nonblock, bool *oldnonblock);
|
||||
|
||||
// wait for a file descriptor to be readable or writeable.
|
||||
#define NECO_WAIT_READ 1
|
||||
#define NECO_WAIT_WRITE 2
|
||||
|
||||
int neco_wait(int fd, int mode);
|
||||
int neco_wait_dl(int fd, int mode, int64_t deadline);
|
||||
|
||||
/// @}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// networking
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// @defgroup Networking Networking utilities
|
||||
/// @{
|
||||
|
||||
int neco_serve(const char *network, const char *address);
|
||||
int neco_serve_dl(const char *network, const char *address, int64_t deadline);
|
||||
int neco_dial(const char *network, const char *address);
|
||||
int neco_dial_dl(const char *network, const char *address, int64_t deadline);
|
||||
|
||||
/// @}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// cancelation
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// @defgroup Cancelation Cancelation
|
||||
/// @{
|
||||
|
||||
int neco_cancel(int64_t id);
|
||||
int neco_cancel_dl(int64_t id, int64_t deadline);
|
||||
|
||||
#define NECO_CANCEL_ASYNC 1
|
||||
#define NECO_CANCEL_INLINE 2
|
||||
#define NECO_CANCEL_ENABLE 3
|
||||
#define NECO_CANCEL_DISABLE 4
|
||||
|
||||
int neco_setcanceltype(int type, int *oldtype);
|
||||
int neco_setcancelstate(int state, int *oldstate);
|
||||
|
||||
#define neco_cleanup_push(routine, arg) {__neco_c0(&(char[32]){0},routine,arg);
|
||||
#define neco_cleanup_pop(execute) __neco_c1(execute);}
|
||||
|
||||
/// @}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// random number generator
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// @defgroup Random Random number generator
|
||||
/// @{
|
||||
|
||||
#define NECO_CSPRNG 0 // Cryptographically secure pseudorandom number generator
|
||||
#define NECO_PRNG 1 // Pseudorandom number generator (non-crypto, faster)
|
||||
|
||||
int neco_rand_setseed(int64_t seed, int64_t *oldseed);
|
||||
int neco_rand(void *data, size_t nbytes, int attr);
|
||||
int neco_rand_dl(void *data, size_t nbytes, int attr, int64_t deadline);
|
||||
|
||||
/// @}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// signal handling
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// @defgroup Signals Signals
|
||||
/// Allows for signals, such as SIGINT (Ctrl-C), to be intercepted or ignored.
|
||||
/// @{
|
||||
|
||||
int neco_signal_watch(int signo);
|
||||
int neco_signal_wait(void);
|
||||
int neco_signal_wait_dl(int64_t deadline);
|
||||
int neco_signal_unwatch(int signo);
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// background worker
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// @defgroup Worker Background worker
|
||||
/// Run arbitrary code in a background worker thread
|
||||
/// @{
|
||||
|
||||
int neco_work(int64_t pin, void(*work)(void *udata), void *udata);
|
||||
|
||||
/// @}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Stats and information
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// @defgroup Stats Stats and information
|
||||
/// @{
|
||||
|
||||
typedef struct neco_stats {
|
||||
size_t coroutines; ///< Number of active coroutines
|
||||
size_t sleepers; ///< Number of sleeping coroutines
|
||||
size_t evwaiters; ///< Number of coroutines waiting on I/O events
|
||||
size_t sigwaiters; ///<
|
||||
size_t senders; ///<
|
||||
size_t receivers; ///<
|
||||
size_t locked; ///<
|
||||
size_t waitgroupers; ///<
|
||||
size_t condwaiters; ///<
|
||||
size_t suspended; ///<
|
||||
size_t workers; ///< Number of background worker threads
|
||||
} neco_stats;
|
||||
|
||||
int neco_getstats(neco_stats *stats);
|
||||
int neco_is_main_thread(void);
|
||||
const char *neco_switch_method(void);
|
||||
|
||||
/// @}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// global behaviors
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// @defgroup GlobalFuncs Global environment
|
||||
/// @{
|
||||
|
||||
void neco_env_setallocator(void *(*malloc)(size_t), void *(*realloc)(void*, size_t), void (*free)(void*));
|
||||
void neco_env_setpaniconerror(bool paniconerror);
|
||||
void neco_env_setcanceltype(int type);
|
||||
void neco_env_setcancelstate(int state);
|
||||
|
||||
/// @}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// time and duration
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// @defgroup Time Time
|
||||
/// Functions for working with time.
|
||||
///
|
||||
/// The following defines are available for convenience.
|
||||
///
|
||||
/// ```c
|
||||
/// #define NECO_NANOSECOND INT64_C(1)
|
||||
/// #define NECO_MICROSECOND INT64_C(1000)
|
||||
/// #define NECO_MILLISECOND INT64_C(1000000)
|
||||
/// #define NECO_SECOND INT64_C(1000000000)
|
||||
/// #define NECO_MINUTE INT64_C(60000000000)
|
||||
/// #define NECO_HOUR INT64_C(3600000000000)
|
||||
/// ```
|
||||
///
|
||||
/// @{
|
||||
|
||||
#define NECO_NANOSECOND INT64_C(1)
|
||||
#define NECO_MICROSECOND INT64_C(1000)
|
||||
#define NECO_MILLISECOND INT64_C(1000000)
|
||||
#define NECO_SECOND INT64_C(1000000000)
|
||||
#define NECO_MINUTE INT64_C(60000000000)
|
||||
#define NECO_HOUR INT64_C(3600000000000)
|
||||
|
||||
int64_t neco_now(void);
|
||||
|
||||
///@}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// errors
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// @defgroup ErrorFuncs Error handling
|
||||
/// Functions for working with [Neco errors](./API.md#neco-errors).
|
||||
/// @{
|
||||
|
||||
#define NECO_OK 0 ///< Successful result (no error)
|
||||
#define NECO_ERROR -1 ///< System error (check errno)
|
||||
#define NECO_INVAL -2 ///< Invalid argument
|
||||
#define NECO_PERM -3 ///< Operation not permitted
|
||||
#define NECO_NOMEM -4 ///< Cannot allocate memory
|
||||
#define NECO_EOF -5 ///< End of file or stream (neco_stream_*)
|
||||
#define NECO_NOTFOUND -6 ///< No such coroutine (neco_cancel)
|
||||
#define NECO_NOSIGWATCH -7 ///< Not watching on a signal
|
||||
#define NECO_CLOSED -8 ///< Channel is closed
|
||||
#define NECO_EMPTY -9 ///< Channel is empty (neco_chan_tryrecv)
|
||||
#define NECO_TIMEDOUT -10 ///< Deadline has elapsed (neco_*_dl)
|
||||
#define NECO_CANCELED -11 ///< Operation canceled (by neco_cancel)
|
||||
#define NECO_BUSY -12 ///< Resource busy (mutex_trylock)
|
||||
#define NECO_NEGWAITGRP -13 ///< Negative waitgroup counter
|
||||
#define NECO_GAIERROR -14 ///< Error with getaddrinfo (check neco_gai_error)
|
||||
#define NECO_UNREADFAIL -15 ///< Failed to unread byte (neco_stream_unread_byte)
|
||||
#define NECO_PARTIALWRITE -16 ///< Failed to write all data (neco_stream_flush)
|
||||
#define NECO_NOTGENERATOR -17 ///< Coroutine is not a generator (neco_gen_yield)
|
||||
#define NECO_NOTSUSPENDED -18 ///< Coroutine is not suspended (neco_resume)
|
||||
|
||||
const char *neco_strerror(ssize_t errcode);
|
||||
int neco_lasterr(void);
|
||||
int neco_gai_lasterr(void);
|
||||
int neco_panic(const char *fmt, ...);
|
||||
|
||||
/// @}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// streama
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// @defgroup Streams Streams and Buffered I/O
|
||||
/// Create a Neco stream from a file descriptor using neco_stream_make() or
|
||||
/// a buffered stream using neco_stream_make_buffered().
|
||||
/// @{
|
||||
|
||||
typedef struct neco_stream neco_stream;
|
||||
|
||||
int neco_stream_make(neco_stream **stream, int fd);
|
||||
int neco_stream_make_buffered(neco_stream **stream, int fd);
|
||||
int neco_stream_close(neco_stream *stream);
|
||||
int neco_stream_close_dl(neco_stream *stream, int64_t deadline);
|
||||
ssize_t neco_stream_read(neco_stream *stream, void *data, size_t nbytes);
|
||||
ssize_t neco_stream_read_dl(neco_stream *stream, void *data, size_t nbytes, int64_t deadline);
|
||||
ssize_t neco_stream_write(neco_stream *stream, const void *data, size_t nbytes);
|
||||
ssize_t neco_stream_write_dl(neco_stream *stream, const void *data, size_t nbytes, int64_t deadline);
|
||||
ssize_t neco_stream_readfull(neco_stream *stream, void *data, size_t nbytes);
|
||||
ssize_t neco_stream_readfull_dl(neco_stream *stream, void *data, size_t nbytes, int64_t deadline);
|
||||
int neco_stream_read_byte(neco_stream *stream);
|
||||
int neco_stream_read_byte_dl(neco_stream *stream, int64_t deadline);
|
||||
int neco_stream_unread_byte(neco_stream *stream);
|
||||
int neco_stream_flush(neco_stream *stream);
|
||||
int neco_stream_flush_dl(neco_stream *stream, int64_t deadline);
|
||||
ssize_t neco_stream_buffered_read_size(neco_stream *stream);
|
||||
ssize_t neco_stream_buffered_write_size(neco_stream *stream);
|
||||
|
||||
/// @}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// happy convenience macro
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// int neco_main(int argc, char *argv[]);
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define neco_main \
|
||||
__neco_main(int argc, char *argv[]); \
|
||||
static void _neco_main(int argc, void *argv[]) { \
|
||||
(void)argc; \
|
||||
__neco_exit_prog(__neco_main(*(int*)argv[0], *(char***)argv[1])); \
|
||||
} \
|
||||
int main(int argc, char *argv[]) { \
|
||||
neco_env_setpaniconerror(true); \
|
||||
neco_env_setcanceltype(NECO_CANCEL_ASYNC); \
|
||||
int ret = neco_start(_neco_main, 2, &argc, &argv); \
|
||||
fprintf(stderr, "neco_start: %s (code %d)\n", neco_strerror(ret), ret); \
|
||||
return -1; \
|
||||
}; \
|
||||
int __neco_main
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// private functions, not to be call directly
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void __neco_c0(void*,void(*)(void*),void*);
|
||||
void __neco_c1(int);
|
||||
void __neco_exit_prog(int);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef EAI_SYSTEM
|
||||
#define EAI_SYSTEM 11
|
||||
#endif
|
||||
|
||||
#endif // NECO_H
|
||||
81
c/neco/neco.go
Normal file
81
c/neco/neco.go
Normal file
@@ -0,0 +1,81 @@
|
||||
package neco
|
||||
|
||||
import (
|
||||
_ "unsafe"
|
||||
|
||||
"github.com/goplus/llgo/c"
|
||||
)
|
||||
|
||||
const (
|
||||
LLGoFiles = "_wrap/neco.c"
|
||||
LLGoPackage = "link"
|
||||
)
|
||||
|
||||
const (
|
||||
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)
|
||||
|
||||
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)
|
||||
)
|
||||
|
||||
// generator
|
||||
type Gen struct{}
|
||||
|
||||
// llgo:type C
|
||||
type Coro = func(argc c.Int, argv *c.Pointer)
|
||||
|
||||
//go:linkname GenYield C.neco_gen_yield
|
||||
func GenYield(data c.Pointer) c.Int
|
||||
|
||||
//go:linkname GenNext C.neco_gen_next
|
||||
func GenNext(gen *Gen, data c.Pointer) c.Int
|
||||
|
||||
//go:linkname GenStart C.neco_gen_start
|
||||
func GenStart(gen **Gen, dataSize uintptr, co Coro, argc c.Int, __llgo_va_list ...any) c.Int
|
||||
|
||||
//go:linkname GenRelease C.neco_gen_release
|
||||
func GenRelease(gen *Gen) c.Int
|
||||
|
||||
//go:linkname ExitProg C.__neco_exit_prog
|
||||
func ExitProg(code c.Int)
|
||||
|
||||
//go:linkname EnvSetpaniconerror C.neco_env_setpaniconerror
|
||||
func EnvSetpaniconerror(paniconerror bool)
|
||||
|
||||
//go:linkname EnvSetcanceltype C.neco_env_setcanceltype
|
||||
func EnvSetcanceltype(type_ c.Int)
|
||||
|
||||
//go:linkname Strerror C.neco_strerror
|
||||
func Strerror(errcode c.Int) *c.Char
|
||||
|
||||
//go:linkname Start C.neco_start
|
||||
func Start(co Coro, argc c.Int, __llgo_va_list ...any) c.Int
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package socket
|
||||
package net
|
||||
|
||||
import (
|
||||
_ "unsafe"
|
||||
@@ -80,6 +80,23 @@ const (
|
||||
SOCK_SEQPACKET = 5 // sequenced packet stream
|
||||
)
|
||||
|
||||
const (
|
||||
EAI_ADDRFAMILY = iota + 1 /* address family for hostname not supported */
|
||||
EAI_AGAIN /* temporary failure in name resolution */
|
||||
EAI_BADFLAGS /* invalid value for ai_flags */
|
||||
EAI_FAIL /* non-recoverable failure in name resolution */
|
||||
EAI_FAMILY /* ai_family not supported */
|
||||
EAI_MEMORY /* memory allocation failure */
|
||||
EAI_NODATA /* no address associated with hostname */
|
||||
EAI_NONAME /* hostname nor servname provided, or not known */
|
||||
EAI_SERVICE /* servname not supported for ai_socktype */
|
||||
EAI_SOCKTYPE /* ai_socktype not supported */
|
||||
EAI_SYSTEM /* system error returned in errno */
|
||||
EAI_BADHINTS /* invalid value for hints */
|
||||
EAI_PROTOCOL /* resolved protocol is unknown */
|
||||
EAI_OVERFLOW /* argument buffer overflow */
|
||||
)
|
||||
|
||||
// (TODO) merge to inet
|
||||
const INET_ADDRSTRLEN = 16
|
||||
|
||||
@@ -91,17 +108,29 @@ type SockaddrIn struct {
|
||||
Zero [8]c.Char
|
||||
}
|
||||
|
||||
type SockaddrIn6 struct {
|
||||
Len uint8
|
||||
Family uint8
|
||||
Port uint16
|
||||
Flowinfo c.Uint
|
||||
Addr In6Addr
|
||||
ScopeId c.Uint
|
||||
}
|
||||
|
||||
type InAddr struct {
|
||||
Addr c.Uint
|
||||
}
|
||||
|
||||
type In6Addr struct {
|
||||
U6Addr [16]uint8
|
||||
}
|
||||
|
||||
type SockAddr struct {
|
||||
Len uint8
|
||||
Family uint8
|
||||
Data [14]c.Char
|
||||
}
|
||||
|
||||
// (TODO) merge to netdb
|
||||
type Hostent struct {
|
||||
Name *c.Char // official name of host
|
||||
Aliases **c.Char // null-terminated array of alternate names for the host
|
||||
@@ -125,8 +154,6 @@ func Listen(sockfd c.Int, backlog c.Int) c.Int
|
||||
//go:linkname Accept C.accept
|
||||
func Accept(sockfd c.Int, addr *SockaddrIn, addrlen *c.Uint) c.Int
|
||||
|
||||
// (TODO) merge to netdb
|
||||
//
|
||||
//go:linkname GetHostByName C.gethostbyname
|
||||
func GetHostByName(name *c.Char) *Hostent
|
||||
|
||||
@@ -135,10 +162,42 @@ func GetHostByName(name *c.Char) *Hostent
|
||||
//go:linkname InetNtop C.inet_ntop
|
||||
func InetNtop(af c.Int, src c.Pointer, dst *c.Char, size c.Uint) *c.Char
|
||||
|
||||
func SwapInt16(data uint16) uint16 {
|
||||
//go:linkname InetAddr C.inet_addr
|
||||
func InetAddr(s *c.Char) c.Uint
|
||||
|
||||
//go:linkname Send C.send
|
||||
func Send(c.Int, c.Pointer, uintptr, c.Int) c.Long
|
||||
|
||||
//go:linkname Recv C.recv
|
||||
func Recv(c.Int, c.Pointer, uintptr, c.Int) c.Long
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
type AddrInfo struct {
|
||||
Flags c.Int
|
||||
Family c.Int
|
||||
SockType c.Int
|
||||
Protocol c.Int
|
||||
AddrLen c.Uint
|
||||
CanOnName *c.Char
|
||||
Addr *SockAddr
|
||||
Next *AddrInfo
|
||||
}
|
||||
|
||||
//go:linkname Getaddrinfo C.getaddrinfo
|
||||
func Getaddrinfo(host *c.Char, port *c.Char, addrInfo *AddrInfo, result **AddrInfo) c.Int
|
||||
|
||||
//go:linkname Freeaddrinfo C.freeaddrinfo
|
||||
func Freeaddrinfo(addrInfo *AddrInfo) c.Int
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
func swapInt16(data uint16) uint16 {
|
||||
return (data << 8) | (data >> 8)
|
||||
}
|
||||
|
||||
func Htons(x uint16) uint16 {
|
||||
return SwapInt16(x)
|
||||
return swapInt16(x)
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
85
c/openssl/md5.go
Normal file
85
c/openssl/md5.go
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package openssl
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/goplus/llgo/c"
|
||||
)
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
const (
|
||||
MD5_CBLOCK = 64
|
||||
MD5_LBLOCK = MD5_CBLOCK / 4
|
||||
)
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
type MD5_LONG = c.Uint
|
||||
|
||||
type MD5_CTX struct {
|
||||
A, B, C, D MD5_LONG
|
||||
Nl, Nh MD5_LONG
|
||||
Data [MD5_LBLOCK]MD5_LONG
|
||||
Num c.Uint
|
||||
}
|
||||
|
||||
// OSSL_DEPRECATEDIN_3_0 int MD5_Init(MD5_CTX *c);
|
||||
//
|
||||
// llgo:link (*MD5_CTX).Init C.MD5_Init
|
||||
func (c *MD5_CTX) Init() c.Int { return 0 }
|
||||
|
||||
// OSSL_DEPRECATEDIN_3_0 int MD5_Update(MD5_CTX *c, const void *data, size_t len);
|
||||
//
|
||||
// llgo:link (*MD5_CTX).Update C.MD5_Update
|
||||
func (c *MD5_CTX) Update(data unsafe.Pointer, n uintptr) c.Int { return 0 }
|
||||
|
||||
func (c *MD5_CTX) UpdateBytes(data []byte) c.Int {
|
||||
return c.Update(unsafe.Pointer(unsafe.SliceData(data)), uintptr(len(data)))
|
||||
}
|
||||
|
||||
func (c *MD5_CTX) UpdateString(data string) c.Int {
|
||||
return c.Update(unsafe.Pointer(unsafe.StringData(data)), uintptr(len(data)))
|
||||
}
|
||||
|
||||
// OSSL_DEPRECATEDIN_3_0 int MD5_Final(unsigned char *md, MD5_CTX *c);
|
||||
//
|
||||
//go:linkname md5Final C.MD5_Final
|
||||
func md5Final(md *byte, c *MD5_CTX) c.Int
|
||||
|
||||
func (c *MD5_CTX) Final(md *byte) c.Int {
|
||||
return md5Final(md, c)
|
||||
}
|
||||
|
||||
// OSSL_DEPRECATEDIN_3_0 unsigned char *MD5(const unsigned char *d, size_t n, unsigned char *md);
|
||||
//
|
||||
//go:linkname MD5 C.MD5
|
||||
func MD5(data unsafe.Pointer, n uintptr, md *byte) *byte
|
||||
|
||||
func MD5Bytes(data []byte, md *byte) *byte {
|
||||
return MD5(unsafe.Pointer(unsafe.SliceData(data)), uintptr(len(data)), md)
|
||||
}
|
||||
|
||||
func MD5String(data string, md *byte) *byte {
|
||||
return MD5(unsafe.Pointer(unsafe.StringData(data)), uintptr(len(data)), md)
|
||||
}
|
||||
|
||||
// OSSL_DEPRECATEDIN_3_0 void MD5_Transform(MD5_CTX *c, const unsigned char *b);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
23
c/openssl/openssl.go
Normal file
23
c/openssl/openssl.go
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package openssl
|
||||
|
||||
const (
|
||||
LLGoPackage = "link: $(pkg-config --libs openssl); -lssl -lcrypto"
|
||||
)
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
94
c/openssl/sha1.go
Normal file
94
c/openssl/sha1.go
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package openssl
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/goplus/llgo/c"
|
||||
)
|
||||
|
||||
const (
|
||||
SHA_DIGEST_LENGTH = 20
|
||||
SHA_LBLOCK = 16
|
||||
SHA_CBLOCK = (SHA_LBLOCK * 4)
|
||||
SHA_LAST_BLOCK = (SHA_CBLOCK - 8)
|
||||
|
||||
SHA256_CBLOCK = (SHA_LBLOCK * 4)
|
||||
SHA256_192_DIGEST_LENGTH = 24
|
||||
SHA224_DIGEST_LENGTH = 28
|
||||
SHA256_DIGEST_LENGTH = 32
|
||||
SHA384_DIGEST_LENGTH = 48
|
||||
SHA512_DIGEST_LENGTH = 64
|
||||
SHA512_CBLOCK = (SHA_LBLOCK * 8)
|
||||
)
|
||||
|
||||
type SHA_LONG64 = c.UlongLong
|
||||
|
||||
type SHA_LONG = c.Uint
|
||||
|
||||
type SHA_CTX struct {
|
||||
H0, H1, H2, H3, H4 SHA_LONG
|
||||
Nl, Nh SHA_LONG
|
||||
Data [SHA_LBLOCK]SHA_LONG
|
||||
Num c.Uint
|
||||
}
|
||||
|
||||
// OSSL_DEPRECATEDIN_3_0 int SHA1_Init(SHA_CTX *c);
|
||||
//
|
||||
// llgo:link (*SHA_CTX).Init C.SHA1_Init
|
||||
func (c *SHA_CTX) Init() c.Int { return 0 }
|
||||
|
||||
// OSSL_DEPRECATEDIN_3_0 int SHA1_Update(SHA_CTX *c, const void *data, size_t len);
|
||||
//
|
||||
// llgo:link (*SHA_CTX).Update C.SHA1_Update
|
||||
func (c *SHA_CTX) Update(data unsafe.Pointer, n uintptr) c.Int { return 0 }
|
||||
|
||||
func (c *SHA_CTX) UpdateBytes(data []byte) c.Int {
|
||||
return c.Update(unsafe.Pointer(unsafe.SliceData(data)), uintptr(len(data)))
|
||||
}
|
||||
|
||||
func (c *SHA_CTX) UpdateString(data string) c.Int {
|
||||
return c.Update(unsafe.Pointer(unsafe.StringData(data)), uintptr(len(data)))
|
||||
}
|
||||
|
||||
// OSSL_DEPRECATEDIN_3_0 int SHA1_Final(unsigned char *md, SHA_CTX *c);
|
||||
//
|
||||
//go:linkname sha1Final C.SHA1_Final
|
||||
func sha1Final(md *byte, c *SHA_CTX) c.Int
|
||||
|
||||
func (c *SHA_CTX) Final(md *byte) c.Int {
|
||||
return sha1Final(md, c)
|
||||
}
|
||||
|
||||
// OSSL_DEPRECATEDIN_3_0 void SHA1_Transform(SHA_CTX *c, const unsigned char *data);
|
||||
//
|
||||
// llgo:link (*SHA_CTX).Transform C.SHA1_Transform
|
||||
func (c *SHA_CTX) Transform(data *byte) {}
|
||||
|
||||
// unsigned char *SHA1(const unsigned char *d, size_t n, unsigned char *md);
|
||||
//
|
||||
//go:linkname SHA1 C.SHA1
|
||||
func SHA1(data unsafe.Pointer, n uintptr, md *byte) *byte
|
||||
|
||||
func SHA1Bytes(data []byte, md *byte) *byte {
|
||||
return SHA1(unsafe.Pointer(unsafe.SliceData(data)), uintptr(len(data)), md)
|
||||
}
|
||||
|
||||
func SHA1String(data string, md *byte) *byte {
|
||||
return SHA1(unsafe.Pointer(unsafe.StringData(data)), uintptr(len(data)), md)
|
||||
}
|
||||
117
c/openssl/sha256.go
Normal file
117
c/openssl/sha256.go
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package openssl
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/goplus/llgo/c"
|
||||
)
|
||||
|
||||
type SHA256_CTX struct {
|
||||
H [8]SHA_LONG
|
||||
Nl, Nh SHA_LONG
|
||||
Data [SHA_LBLOCK]SHA_LONG
|
||||
Num, MdLen c.Uint
|
||||
}
|
||||
|
||||
type SHA224_CTX SHA256_CTX
|
||||
|
||||
// OSSL_DEPRECATEDIN_3_0 int SHA224_Init(SHA256_CTX *c);
|
||||
//
|
||||
// llgo:link (*SHA224_CTX).Init C.SHA224_Init
|
||||
func (c *SHA224_CTX) Init() c.Int { return 0 }
|
||||
|
||||
// OSSL_DEPRECATEDIN_3_0 int SHA224_Update(SHA256_CTX *c, const void *data, size_t len);
|
||||
//
|
||||
// llgo:link (*SHA224_CTX).Update C.SHA224_Update
|
||||
func (c *SHA224_CTX) Update(data unsafe.Pointer, n uintptr) c.Int { return 0 }
|
||||
|
||||
func (c *SHA224_CTX) UpdateBytes(data []byte) c.Int {
|
||||
return c.Update(unsafe.Pointer(unsafe.SliceData(data)), uintptr(len(data)))
|
||||
}
|
||||
|
||||
func (c *SHA224_CTX) UpdateString(data string) c.Int {
|
||||
return c.Update(unsafe.Pointer(unsafe.StringData(data)), uintptr(len(data)))
|
||||
}
|
||||
|
||||
// OSSL_DEPRECATEDIN_3_0 int SHA224_Final(unsigned char *md, SHA256_CTX *c);
|
||||
//
|
||||
//go:linkname sha224Final C.SHA224_Final
|
||||
func sha224Final(md *byte, c *SHA224_CTX) c.Int
|
||||
|
||||
func (c *SHA224_CTX) Final(md *byte) c.Int {
|
||||
return sha224Final(md, c)
|
||||
}
|
||||
|
||||
// OSSL_DEPRECATEDIN_3_0 int SHA256_Init(SHA256_CTX *c);
|
||||
//
|
||||
// llgo:link (*SHA256_CTX).Init C.SHA256_Init
|
||||
func (c *SHA256_CTX) Init() c.Int { return 0 }
|
||||
|
||||
// OSSL_DEPRECATEDIN_3_0 int SHA256_Update(SHA256_CTX *c, const void *data, size_t len);
|
||||
//
|
||||
// llgo:link (*SHA256_CTX).Update C.SHA256_Update
|
||||
func (c *SHA256_CTX) Update(data unsafe.Pointer, n uintptr) c.Int { return 0 }
|
||||
|
||||
func (c *SHA256_CTX) UpdateBytes(data []byte) c.Int {
|
||||
return c.Update(unsafe.Pointer(unsafe.SliceData(data)), uintptr(len(data)))
|
||||
}
|
||||
|
||||
func (c *SHA256_CTX) UpdateString(data string) c.Int {
|
||||
return c.Update(unsafe.Pointer(unsafe.StringData(data)), uintptr(len(data)))
|
||||
}
|
||||
|
||||
// OSSL_DEPRECATEDIN_3_0 int SHA256_Final(unsigned char *md, SHA256_CTX *c);
|
||||
//
|
||||
//go:linkname sha256Final C.SHA256_Final
|
||||
func sha256Final(md *byte, c *SHA256_CTX) c.Int
|
||||
|
||||
func (c *SHA256_CTX) Final(md *byte) c.Int {
|
||||
return sha256Final(md, c)
|
||||
}
|
||||
|
||||
// OSSL_DEPRECATEDIN_3_0 void SHA256_Transform(SHA256_CTX *c, const unsigned char *data);
|
||||
//
|
||||
// llgo:link (*SHA256_CTX).Transform C.SHA256_Transform
|
||||
func (c *SHA256_CTX) Transform(data *byte) {}
|
||||
|
||||
// unsigned char *SHA224(const unsigned char *d, size_t n, unsigned char *md);
|
||||
//
|
||||
//go:linkname SHA224 C.SHA224
|
||||
func SHA224(data unsafe.Pointer, n uintptr, md *byte) *byte
|
||||
|
||||
func SHA224Bytes(data []byte, md *byte) *byte {
|
||||
return SHA224(unsafe.Pointer(unsafe.SliceData(data)), uintptr(len(data)), md)
|
||||
}
|
||||
|
||||
func SHA224String(data string, md *byte) *byte {
|
||||
return SHA224(unsafe.Pointer(unsafe.StringData(data)), uintptr(len(data)), md)
|
||||
}
|
||||
|
||||
// unsigned char *SHA256(const unsigned char *d, size_t n, unsigned char *md);
|
||||
//
|
||||
//go:linkname SHA256 C.SHA256
|
||||
func SHA256(data unsafe.Pointer, n uintptr, md *byte) *byte
|
||||
|
||||
func SHA256Bytes(data []byte, md *byte) *byte {
|
||||
return SHA256(unsafe.Pointer(unsafe.SliceData(data)), uintptr(len(data)), md)
|
||||
}
|
||||
|
||||
func SHA256String(data string, md *byte) *byte {
|
||||
return SHA256(unsafe.Pointer(unsafe.StringData(data)), uintptr(len(data)), md)
|
||||
}
|
||||
115
c/openssl/sha512.go
Normal file
115
c/openssl/sha512.go
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package openssl
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/goplus/llgo/c"
|
||||
)
|
||||
|
||||
type SHA512_CTX struct {
|
||||
H [8]SHA_LONG64
|
||||
N1, Nh SHA_LONG64
|
||||
D [SHA_LBLOCK]SHA_LONG64
|
||||
Num, MdLen c.Uint
|
||||
}
|
||||
|
||||
type SHA384_CTX SHA512_CTX
|
||||
|
||||
// OSSL_DEPRECATEDIN_3_0 int SHA384_Init(SHA512_CTX *c);
|
||||
//
|
||||
// llgo:link (*SHA384_CTX).Init C.SHA384_Init
|
||||
func (c *SHA384_CTX) Init() c.Int { return 0 }
|
||||
|
||||
// OSSL_DEPRECATEDIN_3_0 int SHA384_Update(SHA512_CTX *c, const void *data, size_t len);
|
||||
//
|
||||
// llgo:link (*SHA384_CTX).Update C.SHA384_Update
|
||||
func (c *SHA384_CTX) Update(data unsafe.Pointer, n uintptr) c.Int { return 0 }
|
||||
|
||||
func (c *SHA384_CTX) UpdateBytes(data []byte) c.Int {
|
||||
return c.Update(unsafe.Pointer(unsafe.SliceData(data)), uintptr(len(data)))
|
||||
}
|
||||
|
||||
func (c *SHA384_CTX) UpdateString(data string) c.Int {
|
||||
return c.Update(unsafe.Pointer(unsafe.StringData(data)), uintptr(len(data)))
|
||||
}
|
||||
|
||||
// OSSL_DEPRECATEDIN_3_0 int SHA384_Final(unsigned char *md, SHA512_CTX *c);
|
||||
//
|
||||
//go:linkname sha384Final C.SHA384_Final
|
||||
func sha384Final(md *byte, c *SHA384_CTX) c.Int
|
||||
|
||||
func (c *SHA384_CTX) Final(md *byte) c.Int {
|
||||
return sha384Final(md, c)
|
||||
}
|
||||
|
||||
// OSSL_DEPRECATEDIN_3_0 int SHA512_Init(SHA512_CTX *c);
|
||||
//
|
||||
// llgo:link (*SHA512_CTX).Init C.SHA512_Init
|
||||
func (c *SHA512_CTX) Init() c.Int { return 0 }
|
||||
|
||||
// OSSL_DEPRECATEDIN_3_0 int SHA512_Update(SHA512_CTX *c, const void *data, size_t len);
|
||||
//
|
||||
// llgo:link (*SHA512_CTX).Update C.SHA512_Update
|
||||
func (c *SHA512_CTX) Update(data unsafe.Pointer, n uintptr) c.Int { return 0 }
|
||||
func (c *SHA512_CTX) UpdateBytes(data []byte) c.Int {
|
||||
return c.Update(unsafe.Pointer(unsafe.SliceData(data)), uintptr(len(data)))
|
||||
}
|
||||
func (c *SHA512_CTX) UpdateString(data string) c.Int {
|
||||
return c.Update(unsafe.Pointer(unsafe.StringData(data)), uintptr(len(data)))
|
||||
}
|
||||
|
||||
// OSSL_DEPRECATEDIN_3_0 int SHA512_Final(unsigned char *md, SHA512_CTX *c);
|
||||
//
|
||||
//go:linkname sha512Final C.SHA512_Final
|
||||
func sha512Final(md *byte, c *SHA512_CTX) c.Int
|
||||
|
||||
func (c *SHA512_CTX) Final(md *byte) c.Int {
|
||||
return sha512Final(md, c)
|
||||
}
|
||||
|
||||
// OSSL_DEPRECATEDIN_3_0 void SHA512_Transform(SHA512_CTX *c, const unsigned char *data);
|
||||
//
|
||||
// llgo:link (*SHA512_CTX).Transform C.SHA512_Transform
|
||||
func (c *SHA512_CTX) Transform(data *byte) {}
|
||||
|
||||
// unsigned char *SHA384(const unsigned char *d, size_t n, unsigned char *md);
|
||||
//
|
||||
//go:linkname SHA384 C.SHA384
|
||||
func SHA384(data unsafe.Pointer, n uintptr, md *byte) *byte
|
||||
|
||||
func SHA384Bytes(data []byte, md *byte) *byte {
|
||||
return SHA384(unsafe.Pointer(unsafe.SliceData(data)), uintptr(len(data)), md)
|
||||
}
|
||||
|
||||
func SHA384String(data string, md *byte) *byte {
|
||||
return SHA384(unsafe.Pointer(unsafe.StringData(data)), uintptr(len(data)), md)
|
||||
}
|
||||
|
||||
// unsigned char *SHA512(const unsigned char *d, size_t n, unsigned char *md);
|
||||
//
|
||||
//go:linkname SHA512 C.SHA512
|
||||
func SHA512(data unsafe.Pointer, n uintptr, md *byte) *byte
|
||||
|
||||
func SHA512Bytes(data []byte, md *byte) *byte {
|
||||
return SHA512(unsafe.Pointer(unsafe.SliceData(data)), uintptr(len(data)), md)
|
||||
}
|
||||
|
||||
func SHA512String(data string, md *byte) *byte {
|
||||
return SHA512(unsafe.Pointer(unsafe.StringData(data)), uintptr(len(data)), md)
|
||||
}
|
||||
117
c/os/os.go
117
c/os/os.go
@@ -35,6 +35,33 @@ const (
|
||||
PATH_MAX = C.PATH_MAX
|
||||
)
|
||||
|
||||
const (
|
||||
/* get file status flags */
|
||||
F_GETFL = 3
|
||||
/* set file status flags */
|
||||
F_SETFL = 4
|
||||
|
||||
/* open for reading only */
|
||||
O_RDONLY = 0x0000
|
||||
/* open for writing only */
|
||||
O_WRONLY = 0x0001
|
||||
/* open for reading and writing */
|
||||
O_RDWR = 0x0002
|
||||
/* mask for above modes */
|
||||
O_ACCMODE = 0x0003
|
||||
|
||||
/* no delay */
|
||||
O_NONBLOCK = 0x00000004
|
||||
/* create if nonexistant */
|
||||
O_CREAT = 0x00000200
|
||||
/* truncate to zero length */
|
||||
O_TRUNC = 0x00000400
|
||||
)
|
||||
|
||||
const (
|
||||
EAGAIN = 35
|
||||
)
|
||||
|
||||
type (
|
||||
ModeT C.mode_t
|
||||
UidT C.uid_t
|
||||
@@ -146,7 +173,7 @@ func Fstatat(dirfd c.Int, path *c.Char, buf *StatT, flags c.Int) c.Int
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
//go:linkname Open C.open
|
||||
func Open(path *c.Char, flags c.Int, mode ModeT) c.Int
|
||||
func Open(path *c.Char, flags c.Int, __llgo_va_list ...any) c.Int
|
||||
|
||||
//go:linkname Openat C.openat
|
||||
func Openat(dirfd c.Int, path *c.Char, flags c.Int, mode ModeT) c.Int
|
||||
@@ -154,6 +181,9 @@ func Openat(dirfd c.Int, path *c.Char, flags c.Int, mode ModeT) c.Int
|
||||
//go:linkname Creat C.creat
|
||||
func Creat(path *c.Char, mode ModeT) c.Int
|
||||
|
||||
//go:linkname Fcntl C.fcntl
|
||||
func Fcntl(a c.Int, b c.Int, __llgo_va_list ...any) c.Int
|
||||
|
||||
//go:linkname Dup C.dup
|
||||
func Dup(fd c.Int) c.Int
|
||||
|
||||
@@ -237,21 +267,50 @@ func Execve(path *c.Char, argv **c.Char, envp **c.Char) c.Int
|
||||
//go:linkname Execvp C.execvp
|
||||
func Execvp(file *c.Char, argv **c.Char) c.Int
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
type PidT c.Int
|
||||
|
||||
//go:linkname Fork C.fork
|
||||
func Fork() c.Int
|
||||
func Fork() PidT
|
||||
|
||||
//go:linkname Getpid C.getpid
|
||||
func Getpid() PidT
|
||||
|
||||
//go:linkname Getppid C.getppid
|
||||
func Getppid() PidT
|
||||
|
||||
//go:linkname Kill C.kill
|
||||
func Kill(pid c.Int, sig c.Int) c.Int
|
||||
func Kill(pid PidT, sig c.Int) c.Int
|
||||
|
||||
// If wait() returns due to a stopped or terminated child process, the process ID
|
||||
// of the child is returned to the calling process. Otherwise, a value of -1 is
|
||||
// returned and errno is set to indicate the error.
|
||||
//
|
||||
//go:linkname Wait C.wait
|
||||
func Wait(statLoc *c.Int) PidT
|
||||
|
||||
// If wait3(), wait4(), or waitpid() returns due to a stopped or terminated child
|
||||
// process, the process ID of the child is returned to the calling process. If
|
||||
// there are no children not previously awaited, -1 is returned with errno set to
|
||||
// [ECHILD]. Otherwise, if WNOHANG is specified and there are no stopped or exited
|
||||
// children, 0 is returned. If an error is detected or a caught signal aborts the
|
||||
// call, a value of -1 is returned and errno is set to indicate the error.
|
||||
//
|
||||
//go:linkname Wait3 C.wait3
|
||||
func Wait3(statLoc *c.Int, options c.Int, rusage *syscall.Rusage) PidT
|
||||
|
||||
//go:linkname Wait4 C.wait4
|
||||
func Wait4(pid PidT, statLoc *c.Int, options c.Int, rusage *syscall.Rusage) PidT
|
||||
|
||||
//go:linkname Waitpid C.waitpid
|
||||
func Waitpid(pid PidT, statLoc *c.Int, options c.Int) PidT
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
//go:linkname Exit C.exit
|
||||
func Exit(c.Int)
|
||||
|
||||
//go:linkname Getpid C.getpid
|
||||
func Getpid() c.Int
|
||||
|
||||
//go:linkname Getppid C.getppid
|
||||
func Getppid() c.Int
|
||||
|
||||
//go:linkname Getuid C.getuid
|
||||
func Getuid() UidT
|
||||
|
||||
@@ -265,3 +324,43 @@ func Getgid() GidT
|
||||
func Getegid() GidT
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
//go:linkname Getrlimit C.getrlimit
|
||||
func Getrlimit(resource c.Int, rlp *syscall.Rlimit) c.Int
|
||||
|
||||
//go:linkname Setrlimit C.setrlimit
|
||||
func Setrlimit(resource c.Int, rlp *syscall.Rlimit) c.Int
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// Upon successful completion, the value 0 is returned; otherwise the value -1
|
||||
// is returned and the global variable errno is set to indicate the error.
|
||||
//
|
||||
//go:linkname Sysctl C.sysctl
|
||||
func Sysctl(
|
||||
name *c.Int, namelen c.Uint,
|
||||
oldp c.Pointer, oldlenp *uintptr,
|
||||
newp c.Pointer, newlen uintptr) c.Int
|
||||
|
||||
//go:linkname Sysctlbyname C.sysctlbyname
|
||||
func Sysctlbyname(
|
||||
name *c.Char, oldp c.Pointer, oldlenp *uintptr,
|
||||
newp c.Pointer, newlen uintptr) c.Int
|
||||
|
||||
// The sysctlnametomib() function accepts an ASCII representation of the
|
||||
// name, looks up the integer name vector, and returns the numeric repre-
|
||||
// sentation in the mib array pointed to by mibp. The number of elements
|
||||
// in the mib array is given by the location specified by sizep before the
|
||||
// call, and that location gives the number of entries copied after a suc-
|
||||
// cessful call. The resulting mib and size may be used in subsequent
|
||||
// sysctl() calls to get the data associated with the requested ASCII
|
||||
// name. This interface is intended for use by applications that want to
|
||||
// repeatedly request the same variable (the sysctl() function runs in
|
||||
// about a third the time as the same request made via the sysctlbyname()
|
||||
// function). The sysctlnametomib() function is also useful for fetching
|
||||
// mib prefixes and then adding a final component.
|
||||
//
|
||||
//go:linkname Sysctlnametomib C.sysctlnametomib
|
||||
func Sysctlnametomib(name *c.Char, mibp *c.Int, sizep *uintptr) c.Int
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
@@ -5,3 +5,15 @@
|
||||
pthread_once_t llgoSyncOnceInitVal = PTHREAD_ONCE_INIT;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// wrap return type to void
|
||||
void wrap_pthread_mutex_lock(pthread_mutex_t *mutex) {
|
||||
pthread_mutex_lock(mutex);
|
||||
}
|
||||
|
||||
// wrap return type to void
|
||||
void wrap_pthread_mutex_unlock(pthread_mutex_t *mutex) {
|
||||
pthread_mutex_unlock(mutex);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
@@ -76,13 +76,13 @@ func (m *Mutex) Init(attr *MutexAttr) c.Int { return 0 }
|
||||
// llgo:link (*Mutex).Destroy C.pthread_mutex_destroy
|
||||
func (m *Mutex) Destroy() {}
|
||||
|
||||
// llgo:link (*Mutex).Lock C.pthread_mutex_lock
|
||||
func (m *Mutex) Lock() {}
|
||||
|
||||
// llgo:link (*Mutex).TryLock C.pthread_mutex_trylock
|
||||
func (m *Mutex) TryLock() c.Int { return 0 }
|
||||
|
||||
// llgo:link (*Mutex).Unlock C.pthread_mutex_unlock
|
||||
// llgo:link (*Mutex).Lock C.wrap_pthread_mutex_lock
|
||||
func (m *Mutex) Lock() {}
|
||||
|
||||
// llgo:link (*Mutex).Unlock C.wrap_pthread_mutex_unlock
|
||||
func (m *Mutex) Unlock() {}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
@@ -44,9 +44,6 @@ func Longjmp(env *JmpBuf, val c.Int)
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
//go:linkname Sigsetjmp C.sigsetjmp
|
||||
func Sigsetjmp(env *SigjmpBuf, savemask c.Int) c.Int
|
||||
|
||||
//go:linkname Siglongjmp C.siglongjmp
|
||||
func Siglongjmp(env *SigjmpBuf, val c.Int)
|
||||
|
||||
|
||||
12
c/setjmp/setjmp_linux.go
Normal file
12
c/setjmp/setjmp_linux.go
Normal file
@@ -0,0 +1,12 @@
|
||||
//go:build linux
|
||||
|
||||
package setjmp
|
||||
|
||||
import (
|
||||
_ "unsafe"
|
||||
|
||||
"github.com/goplus/llgo/c"
|
||||
)
|
||||
|
||||
//go:linkname Sigsetjmp C.__sigsetjmp
|
||||
func Sigsetjmp(env *SigjmpBuf, savemask c.Int) c.Int
|
||||
12
c/setjmp/setjmp_other.go
Normal file
12
c/setjmp/setjmp_other.go
Normal file
@@ -0,0 +1,12 @@
|
||||
//go:build !linux
|
||||
|
||||
package setjmp
|
||||
|
||||
import (
|
||||
_ "unsafe"
|
||||
|
||||
"github.com/goplus/llgo/c"
|
||||
)
|
||||
|
||||
//go:linkname Sigsetjmp C.sigsetjmp
|
||||
func Sigsetjmp(env *SigjmpBuf, savemask c.Int) c.Int
|
||||
42
c/sys/_demo/selectdemo/select.go
Normal file
42
c/sys/_demo/selectdemo/select.go
Normal file
@@ -0,0 +1,42 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/goplus/llgo/c"
|
||||
"github.com/goplus/llgo/c/os"
|
||||
"github.com/goplus/llgo/c/sys"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var readFds sys.FdSet
|
||||
sys.FD_ZERO(&readFds)
|
||||
sys.FD_SET(0, &readFds)
|
||||
|
||||
var tv sys.Timeval
|
||||
tv.Sec = 5
|
||||
tv.Usec = 0
|
||||
|
||||
c.Printf(c.Str("Waiting for input on stdin...\n"))
|
||||
ret := sys.Select(1, &readFds, nil, nil, &tv)
|
||||
if ret == -1 {
|
||||
c.Perror(c.Str("select error"))
|
||||
c.Exit(1)
|
||||
} else if ret == 0 {
|
||||
c.Printf(c.Str("Timeout occurred! No data after 5 seconds.\n"))
|
||||
} else {
|
||||
if sys.FD_ISSET(0, &readFds) != 0 {
|
||||
var buffer [100]c.Char
|
||||
n := os.Read(0, c.Pointer(&buffer[:][0]), unsafe.Sizeof(buffer)-1)
|
||||
if n == -1 {
|
||||
c.Perror(c.Str("read error"))
|
||||
c.Exit(1)
|
||||
} else if n == 0 {
|
||||
c.Printf(c.Str("End of file\n"))
|
||||
} else {
|
||||
buffer[n] = c.Char(0)
|
||||
c.Printf(c.Str("Read %ld bytes: %s\n"), n, &buffer[0])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
88
c/sys/_demo/selectdemo2/select2.go
Normal file
88
c/sys/_demo/selectdemo2/select2.go
Normal file
@@ -0,0 +1,88 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/goplus/llgo/c"
|
||||
"github.com/goplus/llgo/c/net"
|
||||
"github.com/goplus/llgo/c/os"
|
||||
"github.com/goplus/llgo/c/sys"
|
||||
)
|
||||
|
||||
const (
|
||||
SERVER_IP = "110.242.68.66" // Get the IP address by ping baidu.com
|
||||
SERVER_PORT = 80
|
||||
BUFFER_SIZE = 4096 * 1024
|
||||
)
|
||||
|
||||
func main() {
|
||||
var server net.SockaddrIn
|
||||
|
||||
sendBuf := c.Str("GET / HTTP/1.1\r\nHost: baidu.com\r\n\r\n")
|
||||
var recvBuf [BUFFER_SIZE]c.Char
|
||||
var bytes_sent, bytes_received c.Int
|
||||
|
||||
// create net
|
||||
sock := net.Socket(net.AF_INET, net.SOCK_STREAM, 0)
|
||||
if sock < 0 {
|
||||
c.Perror(c.Str("Socket creation failed"))
|
||||
return
|
||||
}
|
||||
|
||||
// set server addr
|
||||
c.Memset(c.Pointer(&server), 0, unsafe.Sizeof(server))
|
||||
server.Family = net.AF_INET
|
||||
server.Port = net.Htons(SERVER_PORT)
|
||||
server.Addr.Addr = net.InetAddr(c.Str(SERVER_IP))
|
||||
|
||||
// connect to server
|
||||
if net.Connect(sock, (*net.SockAddr)(c.Pointer(&server)), c.Uint(unsafe.Sizeof(server))) < 0 {
|
||||
c.Perror(c.Str("Connect failed"))
|
||||
return
|
||||
}
|
||||
|
||||
var writefds, readfds sys.FdSet
|
||||
var timeout sys.Timeval
|
||||
|
||||
// Monitor socket writes
|
||||
sys.FD_ZERO(&writefds)
|
||||
sys.FD_SET(sock, &writefds)
|
||||
timeout.Sec = 10
|
||||
timeout.Usec = 0
|
||||
|
||||
// Use select to monitor the readiness of writes
|
||||
if sys.Select(sock+1, nil, &writefds, nil, &timeout) > 0 {
|
||||
if sys.FD_ISSET(sock, &writefds) != 0 {
|
||||
bytes_sent = c.Int(net.Send(sock, c.Pointer(sendBuf), c.Strlen(sendBuf), 0))
|
||||
if bytes_sent < 0 {
|
||||
c.Perror(c.Str("send failed"))
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
c.Perror(c.Str("Select write error"))
|
||||
return
|
||||
}
|
||||
|
||||
// Monitor socket reads
|
||||
sys.FD_ZERO(&readfds)
|
||||
sys.FD_SET(sock, &readfds)
|
||||
|
||||
// Use select to monitor the readiness of the read operation
|
||||
if sys.Select(sock+1, &readfds, nil, nil, &timeout) > 0 {
|
||||
if sys.FD_ISSET(sock, &writefds) != -1 {
|
||||
bytes_received = c.Int(net.Recv(sock, c.Pointer(&recvBuf[:][0]), BUFFER_SIZE-1, 0))
|
||||
if bytes_received < 0 {
|
||||
c.Perror(c.Str("receive failed"))
|
||||
return
|
||||
}
|
||||
recvBuf[bytes_received] = c.Char(0)
|
||||
c.Printf(c.Str("Received:\n%s\n"), &recvBuf[0])
|
||||
}
|
||||
} else {
|
||||
c.Perror(c.Str("Select read error"))
|
||||
return
|
||||
}
|
||||
|
||||
os.Close(sock)
|
||||
}
|
||||
13
c/sys/_wrap/fddef.c
Normal file
13
c/sys/_wrap/fddef.c
Normal file
@@ -0,0 +1,13 @@
|
||||
#include <sys/types.h>
|
||||
|
||||
int llgo_FD_ISSET(int n, fd_set *fd) {
|
||||
return FD_ISSET(n, fd);
|
||||
}
|
||||
|
||||
void llgo_FD_SET(int n, fd_set *fd) {
|
||||
FD_SET(n, fd);
|
||||
}
|
||||
|
||||
void llgo_FD_ZERO(fd_set *fd) {
|
||||
FD_ZERO(fd);
|
||||
}
|
||||
34
c/sys/select.go
Normal file
34
c/sys/select.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package sys
|
||||
|
||||
import (
|
||||
_ "unsafe"
|
||||
|
||||
"github.com/goplus/llgo/c"
|
||||
"github.com/goplus/llgo/c/syscall"
|
||||
)
|
||||
|
||||
const (
|
||||
LLGoFiles = "_wrap/fddef.c"
|
||||
LLGoPackage = "link"
|
||||
)
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
type (
|
||||
FdSet = syscall.FdSet
|
||||
Timeval = syscall.Timeval
|
||||
)
|
||||
|
||||
//go:linkname FD_ZERO C.llgo_FD_ZERO
|
||||
func FD_ZERO(fds *FdSet)
|
||||
|
||||
//go:linkname FD_SET C.llgo_FD_SET
|
||||
func FD_SET(fd c.Int, fds *FdSet)
|
||||
|
||||
//go:linkname FD_ISSET C.llgo_FD_ISSET
|
||||
func FD_ISSET(fd c.Int, fds *FdSet) c.Int
|
||||
|
||||
//go:linkname Select C.select
|
||||
func Select(n c.Int, fdsRead, fdsWrite, fdsError *FdSet, timeout *Timeval) c.Int
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -17,5 +17,16 @@
|
||||
package syscall
|
||||
|
||||
const (
|
||||
LLGoPackage = "decl"
|
||||
LLGoPackage = "noinit"
|
||||
)
|
||||
|
||||
type Errno = uintptr
|
||||
|
||||
// A Signal is a number describing a process signal.
|
||||
// It implements the os.Signal interface.
|
||||
type Signal = int
|
||||
|
||||
// Unix returns the time stored in ts as seconds plus nanoseconds.
|
||||
func (ts *Timespec) Unix() (sec int64, nsec int64) {
|
||||
return int64(ts.Sec), int64(ts.Nsec)
|
||||
}
|
||||
|
||||
1153
c/syscall/zerrors_aix_ppc64.go
Normal file
1153
c/syscall/zerrors_aix_ppc64.go
Normal file
File diff suppressed because it is too large
Load Diff
1279
c/syscall/zerrors_darwin_amd64.go
Normal file
1279
c/syscall/zerrors_darwin_amd64.go
Normal file
File diff suppressed because it is too large
Load Diff
1291
c/syscall/zerrors_darwin_arm64.go
Normal file
1291
c/syscall/zerrors_darwin_arm64.go
Normal file
File diff suppressed because it is too large
Load Diff
1392
c/syscall/zerrors_dragonfly_amd64.go
Normal file
1392
c/syscall/zerrors_dragonfly_amd64.go
Normal file
File diff suppressed because it is too large
Load Diff
1580
c/syscall/zerrors_freebsd_386.go
Normal file
1580
c/syscall/zerrors_freebsd_386.go
Normal file
File diff suppressed because it is too large
Load Diff
1581
c/syscall/zerrors_freebsd_amd64.go
Normal file
1581
c/syscall/zerrors_freebsd_amd64.go
Normal file
File diff suppressed because it is too large
Load Diff
1580
c/syscall/zerrors_freebsd_arm.go
Normal file
1580
c/syscall/zerrors_freebsd_arm.go
Normal file
File diff suppressed because it is too large
Load Diff
1581
c/syscall/zerrors_freebsd_arm64.go
Normal file
1581
c/syscall/zerrors_freebsd_arm64.go
Normal file
File diff suppressed because it is too large
Load Diff
1581
c/syscall/zerrors_freebsd_riscv64.go
Normal file
1581
c/syscall/zerrors_freebsd_riscv64.go
Normal file
File diff suppressed because it is too large
Load Diff
1355
c/syscall/zerrors_linux_386.go
Normal file
1355
c/syscall/zerrors_linux_386.go
Normal file
File diff suppressed because it is too large
Load Diff
1356
c/syscall/zerrors_linux_amd64.go
Normal file
1356
c/syscall/zerrors_linux_amd64.go
Normal file
File diff suppressed because it is too large
Load Diff
1368
c/syscall/zerrors_linux_arm.go
Normal file
1368
c/syscall/zerrors_linux_arm.go
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user