Skip to content

tsbindgen: nullable pointers, and C++ structs in namespaces as tuples - #563

Merged
ASDAlexander77 merged 1 commit into
mainfrom
tsbindgen-nullable-namespaced
Oct 12, 2026
Merged

ASDAlexander77 merged 1 commit into
mainfrom
tsbindgen-nullable-namespaced

Conversation

@ASDAlexander77

Copy link
Copy Markdown
Owner

Fixes two tsbindgen gaps found while generating NVRHI's bindings in native_ts_graphics.

Nullable pointers

A pointer parameter or struct field is now T | null — Opaque, Reference<T>, a @cpp class, string, a function pointer. C lets these be null (an optional out-parameter, queryFeatureSupport(f, null, 0), a desc's unused buffer). tslang lowers T | null to the same pointer (checked: call arguments and tuple sizes are unchanged). A C++ reference stays non-null, and so does a result, so call sites aren't forced into null checks.

C++ structs in namespaces

  • A struct in a namespace or nested in a class (nvrhi::Color, nvrhi::TextureSubresourceSet) is declared under its own name, keyed by its qualified name; --filter matches either.
  • A C++ struct with constructors, methods or member initializers is a tuple when its fields are where a tuple's are. A polymorphic or derived one, or one with a field tsbindgen can't spell (std::string, a container, an array, a bitfield), is type X = Opaque; with the reason in a // skipped: line.
  • Of two structs of one name in different namespaces, the second is named with its namespaces, minus --namespace (rt_Desc), with a warning.
  • Templates, their specializations (including one only named, which is TSK_Undeclared), classes inside them, local classes and lambdas still get no declaration: a pointer to one stays a plain Opaque /* C++ type */.

Visible change: a field-less class in the main file now prints // skipped: Widget — empty struct / type Widget = Opaque; where it used to be silent (README example updated).

Tests

  • New unittests/TsClangImporter/NamespacedStructTest.cpp; pointer expectations in the existing unit tests updated — 67/67 pass.
  • test-bindgen-cpp: the fixture gains fx::Extent (a namespaced struct with a constructor) and Shape::fits(const Extent &, const Extent *), called from TS with a reference, a pointer and null against real compiled C++ (exe and JIT).
  • ctest -R "test-bindgen|cppvtable|cpp_slot": 46/46 on Windows.
  • Stress: NVRHI (MSVC, Android x86_64 + aarch64), the whole MSVC STL and libc++ with --filter 'std::*', windows.h + d3d12.h — no crash, and the output compiles with tslang.

Downstream

native_ts_graphics#52 (merged) already accepts this output in tools/gen_nvrhi_classes.py; its NVRHI tests pass with this tsbindgen on Windows and Android.

🤖 Generated with Claude Code

- A pointer parameter or struct field is `T | null` (Opaque, a Reference, a @cpp class, a string,
  a function pointer): C lets it be null, and tslang lowers the union to the same pointer. A C++
  reference and a result stay non-null.
- A C++ struct in a namespace or a class (nvrhi::Color, nvrhi::TextureSubresourceSet) is declared
  under its own name, keyed by its qualified name; --filter matches either. Of two of one name,
  the next is named with its namespaces, less --namespace (`rt_Desc`), with a warning.
- A C++ struct with constructors, methods or member initializers is a tuple when its fields are
  where a tuple's are; a polymorphic or derived one, or one with a field tsbindgen can't spell
  (std::string, a container), is `type X = Opaque;` with the reason.
- Templates, their specializations (also one only named) and the classes inside them, local
  classes and lambdas still have no declaration: a pointer to one stays a plain Opaque.

Tests: NamespacedStructTest.cpp; the unit tests' pointer expectations; test-bindgen-cpp passes a
namespaced struct by reference and a null pointer to a virtual method of real C++. Checked on
NVRHI (MSVC, Android x86_64 and aarch64), the whole MSVC STL and libc++ (--filter 'std::*') and
windows.h + d3d12.h: no crash, and the output compiles.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ASDAlexander77
ASDAlexander77 merged commit 9f21c6e into main Oct 12, 2026
2 checks passed
@ASDAlexander77
ASDAlexander77 deleted the tsbindgen-nullable-namespaced branch October 12, 2026 22:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant