From 34ce15e84db1868be7a5c29b9c81aa574864bfec Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 5 Oct 2026 10:38:40 +0000 Subject: [PATCH 1/5] Initial plan From be3a0d36c22fb5733be870b8adfaa1f620bcf238 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 5 Oct 2026 10:50:08 +0000 Subject: [PATCH 2/5] Preserve Python header comments in generated bindings Co-authored-by: xushiwei <396972+xushiwei@users.noreply.github.com> --- tool/_testc/python-3.14.8/llcppg.cfg | 1 + tool/_testc/python-3.14.8/pymacro.go | 2 ++ tool/_testc/python-3.14.8/pyport.go | 6 ++++++ tool/_testc/python-3.14.8/pythread.go | 13 +++++++++++++ tool/config.go | 1 + tool/gen.go | 9 ++++++++- 6 files changed, 31 insertions(+), 1 deletion(-) diff --git a/tool/_testc/python-3.14.8/llcppg.cfg b/tool/_testc/python-3.14.8/llcppg.cfg index 998886eec..c206f0a2b 100644 --- a/tool/_testc/python-3.14.8/llcppg.cfg +++ b/tool/_testc/python-3.14.8/llcppg.cfg @@ -20,5 +20,6 @@ "GroupSubdirBy": "fname", "FailFast": 10, "IgnoreInline": true, + "KeepDoc": true, "Language": "c" } diff --git a/tool/_testc/python-3.14.8/pymacro.go b/tool/_testc/python-3.14.8/pymacro.go index 86649218a..62db659ca 100644 --- a/tool/_testc/python-3.14.8/pymacro.go +++ b/tool/_testc/python-3.14.8/pymacro.go @@ -7,6 +7,8 @@ import ( _ "unsafe" ) +// Version helpers. These are primarily macros, but have exported equivalents. +// //go:linkname Py_PACK_FULL_VERSION C.Py_PACK_FULL_VERSION func Py_PACK_FULL_VERSION(x c.Int, y c.Int, z c.Int, level c.Int, serial c.Int) c.Uint32T diff --git a/tool/_testc/python-3.14.8/pyport.go b/tool/_testc/python-3.14.8/pyport.go index e0753aaf1..d4ab1fb3e 100644 --- a/tool/_testc/python-3.14.8/pyport.go +++ b/tool/_testc/python-3.14.8/pyport.go @@ -13,9 +13,15 @@ const PY_BIG_ENDIAN = 0 const PY_LITTLE_ENDIAN = 1 const Py_CAN_START_THREADS = 1 +// uintptr_t is the C9X name for an unsigned integral type such that a +// legitimate void* can be cast to uintptr_t and then back to void* again +// without loss of information. Similarly for intptr_t, wrt a signed +// integral type. type PyUintptrT = c.UintptrT type PyIntptrT = c.IntptrT type PySsizeT = c.SsizeT type PyHashT = PySsizeT type PyUhashT = c.SizeT + +// Now PY_SSIZE_T_CLEAN is mandatory. This is just for backward compatibility. type PySsizeCleanT = PySsizeT diff --git a/tool/_testc/python-3.14.8/pythread.go b/tool/_testc/python-3.14.8/pythread.go index 226402bd6..f3a76117b 100644 --- a/tool/_testc/python-3.14.8/pythread.go +++ b/tool/_testc/python-3.14.8/pythread.go @@ -8,6 +8,8 @@ import ( _ "unsafe" ) +// Return status codes for Python lock acquisition. Chosen for maximum +// backwards compatibility, ie failure -> 0, success -> 1. type PyLockStatus c.Uint const ( @@ -17,11 +19,22 @@ const ( ) type PyThreadTypeLock uintptr + +// When Py_LIMITED_API is not defined, the type layout of Py_tss_t is +// exposed to allow static allocation in the API clients. Even in this case, +// you must handle TSS keys through API functions due to compatibility. type X_PyTssT struct { X_isInitialized c.Int X_key pthread.Key } type PyTssT = X_PyTssT +// PY_TIMEOUT_MAX is the highest usable value (in microseconds) of PY_TIMEOUT_T +// type, and depends on the system threading API. +// +// NOTE: this isn't the same value as `_thread.TIMEOUT_MAX`. The _thread module +// exposes a higher-level API, with timeouts expressed in seconds and +// floating-point numbers allowed. +// //go:linkname PY_TIMEOUT_MAX C.PY_TIMEOUT_MAX var PY_TIMEOUT_MAX c.LongLong diff --git a/tool/config.go b/tool/config.go index 59bc91c71..e41c24dad 100644 --- a/tool/config.go +++ b/tool/config.go @@ -57,6 +57,7 @@ type Config struct { FailFast int `json:"FailFast"` // exit on first N errors, optional IgnoreInline bool `json:"IgnoreInline"` // quietly ignore inline functions NoManglingIgnore bool `json:"NoManglingIgnore"` // quietly ignore functions with no mangled symbol + KeepDoc bool `json:"KeepDoc"` // keeps comments associated with declarations GroupSubdir bool `json:"GroupSubdir"` // treats sub-directory files as a single file. Deprecated: use GroupSubdirBy instead. GroupSubdirBy string `json:"GroupSubdirBy"` // criterion to group sub-directory files by, e.g., "dir" or "fname". `GroupSubdir = true` is equivalent to `GroupSubdirBy = "dir"`. } diff --git a/tool/gen.go b/tool/gen.go index fb5b7362b..a99636d5e 100644 --- a/tool/gen.go +++ b/tool/gen.go @@ -167,7 +167,7 @@ func (cfg *Config) NewPackage(pkgPath, pkgName, workDir string, index clang.Inde } } - files, err := ParseSources(index, topHeaders, incDirs, cfg.Language) + files, err := parseSources(index, topHeaders, incDirs, cfg.Language, cfg.KeepDoc) if err != nil { return } @@ -350,7 +350,14 @@ func ParseFlags(includeDirs []string, lang string) []string { // ParseSources parses the given source files and returns the translation units corresponding // to those files. func ParseSources(index clang.Index, headerFiles, includeDirs []string, lang string) ([]cl.Source, error) { + return parseSources(index, headerFiles, includeDirs, lang, false) +} + +func parseSources(index clang.Index, headerFiles, includeDirs []string, lang string, keepDoc bool) ([]cl.Source, error) { flags := ParseFlags(includeDirs, lang) + if keepDoc { + flags = append(flags, "-fparse-all-comments") + } files := make([]cl.Source, len(headerFiles)) for i, headerFile := range headerFiles { tu, e := index.ParseTranslationUnit(clang.DetailedPreprocessingRecord, headerFile, flags...) From e0fa61ae2eb5c27b0fea189b2efcf79854bc8127 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 5 Oct 2026 10:52:01 +0000 Subject: [PATCH 3/5] Validate preserved Python header documentation Co-authored-by: xushiwei <396972+xushiwei@users.noreply.github.com> --- go.mod | 6 +++++- go.sum | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 9eecb1977..2214bba51 100644 --- a/go.mod +++ b/go.mod @@ -10,4 +10,8 @@ require ( github.com/qiniu/x v1.18.3 ) -require golang.org/x/mod v0.40.0 // indirect +require ( + github.com/llarhub/libcxx/c v0.1.1 // indirect + github.com/llarhub/llvm-c/c v0.2.0 // indirect + golang.org/x/mod v0.40.0 // indirect +) diff --git a/go.sum b/go.sum index d365298d7..01a324631 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,10 @@ github.com/goplus/mod v0.22.1 h1:3GQZqKlcQAiMpRUDAHvFryGYie+mT0JMjguEqOtIjkE= github.com/goplus/mod v0.22.1/go.mod h1:APrczG2FtFcQelU4vTq9xw+GrVs4sPPKnRfGidWBlXY= github.com/llarhub/clang-c v0.7.0 h1:YkO1FR1R1ScKJijF1PUVIpHnIC4uNgsSg/7CLzEBpFE= github.com/llarhub/clang-c v0.7.0/go.mod h1:sZhzXACY6REPetdPrGWcSvRmVkl9RgMHbGWHGeOTchI= +github.com/llarhub/libcxx/c v0.1.1 h1:sKT69wKJPjTgaokhmPM01Lk5PBYGKqRlQaxyl7weMwM= +github.com/llarhub/libcxx/c v0.1.1/go.mod h1:Tix1SwtfMlmDyFghXCjy2tTYW9GG3pvTY7MlYRSrZys= +github.com/llarhub/llvm-c/c v0.2.0 h1:OJTyQvaHVDKv+pM0wCMtj/Qs5pcJtTovOAA3dhUePoU= +github.com/llarhub/llvm-c/c v0.2.0/go.mod h1:vci7IHhvWBfxWRZzV6fBfiIWNMYJja5NNXqR7426XBo= github.com/qiniu/x v1.18.3 h1:trrBKBNszHGwV8XynnbddJr+A7Vca8/xlWP4F/Z4my8= github.com/qiniu/x v1.18.3/go.mod h1:Sx3Wy+0GI9OsX4a53mYj6A0o7mHJ94PUvraqGYb4EIs= golang.org/x/mod v0.40.0 h1:hUv+3cXcdRHz08UmSiOob7sadHig73uo5bkXxQ/tvUs= From d6732116b3874906395ad003e368ce449dbc8d2f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 5 Oct 2026 10:53:31 +0000 Subject: [PATCH 4/5] Revert test-generated module metadata changes Co-authored-by: xushiwei <396972+xushiwei@users.noreply.github.com> --- go.mod | 6 +----- go.sum | 4 ---- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 2214bba51..9eecb1977 100644 --- a/go.mod +++ b/go.mod @@ -10,8 +10,4 @@ require ( github.com/qiniu/x v1.18.3 ) -require ( - github.com/llarhub/libcxx/c v0.1.1 // indirect - github.com/llarhub/llvm-c/c v0.2.0 // indirect - golang.org/x/mod v0.40.0 // indirect -) +require golang.org/x/mod v0.40.0 // indirect diff --git a/go.sum b/go.sum index 01a324631..d365298d7 100644 --- a/go.sum +++ b/go.sum @@ -6,10 +6,6 @@ github.com/goplus/mod v0.22.1 h1:3GQZqKlcQAiMpRUDAHvFryGYie+mT0JMjguEqOtIjkE= github.com/goplus/mod v0.22.1/go.mod h1:APrczG2FtFcQelU4vTq9xw+GrVs4sPPKnRfGidWBlXY= github.com/llarhub/clang-c v0.7.0 h1:YkO1FR1R1ScKJijF1PUVIpHnIC4uNgsSg/7CLzEBpFE= github.com/llarhub/clang-c v0.7.0/go.mod h1:sZhzXACY6REPetdPrGWcSvRmVkl9RgMHbGWHGeOTchI= -github.com/llarhub/libcxx/c v0.1.1 h1:sKT69wKJPjTgaokhmPM01Lk5PBYGKqRlQaxyl7weMwM= -github.com/llarhub/libcxx/c v0.1.1/go.mod h1:Tix1SwtfMlmDyFghXCjy2tTYW9GG3pvTY7MlYRSrZys= -github.com/llarhub/llvm-c/c v0.2.0 h1:OJTyQvaHVDKv+pM0wCMtj/Qs5pcJtTovOAA3dhUePoU= -github.com/llarhub/llvm-c/c v0.2.0/go.mod h1:vci7IHhvWBfxWRZzV6fBfiIWNMYJja5NNXqR7426XBo= github.com/qiniu/x v1.18.3 h1:trrBKBNszHGwV8XynnbddJr+A7Vca8/xlWP4F/Z4my8= github.com/qiniu/x v1.18.3/go.mod h1:Sx3Wy+0GI9OsX4a53mYj6A0o7mHJ94PUvraqGYb4EIs= golang.org/x/mod v0.40.0 h1:hUv+3cXcdRHz08UmSiOob7sadHig73uo5bkXxQ/tvUs= From f04677787bb4a1362c28d4242ee7066c7606d3db Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 5 Oct 2026 11:00:57 +0000 Subject: [PATCH 5/5] Drop KeepDoc option and always parse comments Co-authored-by: xushiwei <396972+xushiwei@users.noreply.github.com> --- tool/_testc/python-3.14.8/llcppg.cfg | 1 - tool/config.go | 1 - tool/gen.go | 10 ++-------- 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/tool/_testc/python-3.14.8/llcppg.cfg b/tool/_testc/python-3.14.8/llcppg.cfg index c206f0a2b..998886eec 100644 --- a/tool/_testc/python-3.14.8/llcppg.cfg +++ b/tool/_testc/python-3.14.8/llcppg.cfg @@ -20,6 +20,5 @@ "GroupSubdirBy": "fname", "FailFast": 10, "IgnoreInline": true, - "KeepDoc": true, "Language": "c" } diff --git a/tool/config.go b/tool/config.go index e41c24dad..59bc91c71 100644 --- a/tool/config.go +++ b/tool/config.go @@ -57,7 +57,6 @@ type Config struct { FailFast int `json:"FailFast"` // exit on first N errors, optional IgnoreInline bool `json:"IgnoreInline"` // quietly ignore inline functions NoManglingIgnore bool `json:"NoManglingIgnore"` // quietly ignore functions with no mangled symbol - KeepDoc bool `json:"KeepDoc"` // keeps comments associated with declarations GroupSubdir bool `json:"GroupSubdir"` // treats sub-directory files as a single file. Deprecated: use GroupSubdirBy instead. GroupSubdirBy string `json:"GroupSubdirBy"` // criterion to group sub-directory files by, e.g., "dir" or "fname". `GroupSubdir = true` is equivalent to `GroupSubdirBy = "dir"`. } diff --git a/tool/gen.go b/tool/gen.go index a99636d5e..f0de094f9 100644 --- a/tool/gen.go +++ b/tool/gen.go @@ -167,7 +167,7 @@ func (cfg *Config) NewPackage(pkgPath, pkgName, workDir string, index clang.Inde } } - files, err := parseSources(index, topHeaders, incDirs, cfg.Language, cfg.KeepDoc) + files, err := ParseSources(index, topHeaders, incDirs, cfg.Language) if err != nil { return } @@ -350,14 +350,8 @@ func ParseFlags(includeDirs []string, lang string) []string { // ParseSources parses the given source files and returns the translation units corresponding // to those files. func ParseSources(index clang.Index, headerFiles, includeDirs []string, lang string) ([]cl.Source, error) { - return parseSources(index, headerFiles, includeDirs, lang, false) -} - -func parseSources(index clang.Index, headerFiles, includeDirs []string, lang string, keepDoc bool) ([]cl.Source, error) { flags := ParseFlags(includeDirs, lang) - if keepDoc { - flags = append(flags, "-fparse-all-comments") - } + flags = append(flags, "-fparse-all-comments") files := make([]cl.Source, len(headerFiles)) for i, headerFile := range headerFiles { tu, e := index.ParseTranslationUnit(clang.DetailedPreprocessingRecord, headerFile, flags...)