add bindings

This commit is contained in:
2026-06-29 16:34:42 +02:00
commit 42045742df
12 changed files with 14760 additions and 0 deletions
+9
View File
@@ -0,0 +1,9 @@
FileVersion = 1
[Project]
Name = "TinyglTF.Setup"
StartupObject = "TinyglTF.Setup.Program"
[Dependencies]
corlib = "*"
"Cpp2Beef.git" = {Git = "https://git.unicon-gmbh.de/Rune/Cpp2Beef.git"}
+8
View File
@@ -0,0 +1,8 @@
FileVersion = 1
[Workspace]
StartupProject = "TinyglTF.Setup"
[Projects]
"TinyglTF.Setup" = {Path = "."}
"Cpp2Beef.git" = {Git = "https://git.unicon-gmbh.de/Rune/Cpp2Beef.git"}
+11
View File
@@ -0,0 +1,11 @@
FileVersion = 1
[Locks."Clang-C.git".Git]
URL = "https://git.unicon-gmbh.de/BeefBindings/Clang-C.git"
Tag = ""
Hash = "86db0167f15d08a63a91a19e46f983a5511bac1a"
[Locks."Cpp2Beef.git".Git]
URL = "https://git.unicon-gmbh.de/Rune/Cpp2Beef.git"
Tag = ""
Hash = "e9242f157093963d56a16382fad9ca654e3d86ce"
+204
View File
@@ -0,0 +1,204 @@
using System;
using System.IO;
using System.Collections;
using System.Diagnostics;
using Cpp2Beef;
using LibClang;
namespace TinyglTF.Setup;
class TinyglTFGenerator : Cpp2BeefGenerator, this(Span<char8*> args)
{
protected override Span<char8*> Args => args;
protected override Flags Flags => .None;
// You can have your binding in one file or in multiple, file management is up to you
StreamWriter writer = new .()..Create("../src/TinyglTF_v3.bf")..Write("""
// This file was generated by Cpp2Beef
using System;
using System.Interop;
namespace TinyglTF;
""") ~ delete _;
protected override StreamWriter GetWriterForHeader(StringView header)
{
if (header.EndsWith("tiny_gltf_v3.h"))
return writer;
return null;
}
protected override Block GetCursorBlock(CXCursor cursor)
{
if (cursor.kind == .FunctionDecl)
return .CustomBlock("TinyglTF");
if (cursor.kind == .MacroDefinition && GetMacroEnum(GetCursorSpelling!(cursor)) != -1)
return .NoBlock;
return base.GetCursorBlock(cursor);
}
protected override void Record(CXCursor cursor, bool attributes = true)
{
base.Record(cursor, attributes);
StringView spelling = GetCursorSpelling!(cursor);
bool isStr = spelling == "tg3_str";
if (isStr || spelling.StartsWith("tg3_span_"))
{
str.Append("\n", cursorIndent, "public static operator ");
if (isStr)
str.Append("StringView");
else
{
str.Append("Span<");
Clang.VisitChildren(cursor, (cursor, parent, client_data) =>
{
Self self = (.)Internal.UnsafeCastToObject(client_data);
self.Type(Clang.GetPointeeType(Clang.GetCursorType(cursor)));
return .Break;
}, Internal.UnsafeCastToPtr(this));
str.Append('>');
}
str.Append("(Self self) => .(self.data, (.)self.", isStr ? "len" : "count", ");");
}
}
const String[?] macroEnumNames = .("tg3_PrimitiveMode", "tg3_ComponentType", "tg3_AccessorType", "tg3_TextureFilter", "tg3_TextureWrapMode",
"tg3_ImageFormat", "tg3_TextureFormat", "tg3_BufferTarget", "tg3_SectionCheckFlags");
const String[?] macroEnumPrefixes = .("mode", "component_type", "type", "texture_filter", "texture_wrap", "image_format", "texture_format", "target", "required_sections");
StringView currentMacroEnum = null;
static int GetMacroEnum(StringView spelling)
{
if (!spelling.StartsWith("TG3_"))
return -1;
if (spelling == "TG3_NO_REQUIRE" || spelling.StartsWith("TG3_REQUIRE_"))
return macroEnumPrefixes.Count-1;
var spelling;
spelling.RemoveFromStart(4);
for (let prefix in macroEnumPrefixes)
if (spelling.StartsWith(prefix, .OrdinalIgnoreCase) && spelling[prefix.Length] == '_')
return @prefix;
return -1;
}
protected override void MacroDefinition(CXCursor cursor)
{
StringView spelling = GetCursorSpelling!(cursor);
int idx = GetMacroEnum(spelling);
if (idx == -1)
{
if (!currentMacroEnum.IsNull)
{
str.Insert(0, "\n}");
currentMacroEnum = null;
}
base.MacroDefinition(cursor);
return;
}
if (currentMacroEnum != macroEnumNames[idx])
{
if (!currentMacroEnum.IsNull) str.Insert(0, "\n}");
str.Append("[CRepr] enum ", macroEnumNames[idx], "\n{\n");
currentMacroEnum = macroEnumNames[idx];
}
int prefixLen = macroEnumPrefixes[idx].Length + 5;
if (idx == macroEnumPrefixes.Count-1)
prefixLen = 4;
str.Append('\t');
UpperSnakeCase2PascalCase(spelling[prefixLen...], str);
str.Append(" = ");
WriteTokens(ScopeTokenize!(cursor, unit)[1...], Clang.GetNullLocation(), .Punctuation);
str.Append(',');
}
protected override void Type(CXType type, TypeParamMode paramMode = .None)
{
if (currentCursor.kind == .FieldDecl && GetTypeSpelling!(type) == "int32_t")
{
let spelling = GetCursorSpelling!(currentCursor);
if (spelling.StartsWith("wrap_"))
{
str.Append("tg3_TextureWrapMode");
return;
}
for (let prefix in macroEnumPrefixes)
if (prefix == spelling)
{
str.Append(macroEnumNames[@prefix]);
return;
}
}
base.Type(type, paramMode);
}
protected override void Enum(CXCursor cursor)
{
if (!currentMacroEnum.IsNull)
{
str.Insert(0, "\n}");
currentMacroEnum = null;
}
base.Enum(cursor);
}
protected override void GetNameInBindings(CXCursor cursor, String outString)
{
switch (cursor.kind)
{
case .EnumConstantDecl:
StringView parent = GetCursorSpelling!(Clang.GetCursorSemanticParent(cursor));
StringView spelling = GetCursorSpelling!(cursor);
int index = parent[4...].IndexOf('_');
if (index >= 0) parent = parent[...(index + 4)];
if (spelling.StartsWith(parent, .OrdinalIgnoreCase))
spelling.RemoveFromStart(parent.Length);
else if (spelling.StartsWith("TG3_"))
spelling.RemoveFromStart(4);
if (spelling.StartsWith('_'))
spelling.RemoveFromStart(1);
UpperSnakeCase2PascalCase(spelling, outString);
return;
case .EnumDecl, .StructDecl, .UnionDecl, .TypedefDecl:
if (!GetCursorSpelling!(cursor).StartsWith("tg3_"))
break;
outString.Append("tg3_");
fallthrough;
case .FunctionDecl:
StringView spelling = GetCursorSpelling!(cursor);
Runtime.Assert(spelling.StartsWith("tg3_"));
spelling.RemoveFromStart(4);
UpperSnakeCase2PascalCase(spelling, outString);
return;
default:
}
base.GetNameInBindings(cursor, outString);
}
}
class Program
{
[CLink] static extern int32 system(char8*);
public static int Main(String[] args)
{
void Download(String file)
{
if (system(scope $"wget -O ../src/{file} https://raw.githubusercontent.com/syoyo/tinygltf/refs/heads/release/{file}") != 0)
Runtime.FatalError(scope $"Failed to download {file}");
}
Download("tiny_gltf_v3.h");
Download("tiny_gltf_v3.c");
Download("tinygltf_json_c.h");
scope TinyglTFGenerator(char8*[?]("--language=c")).Generate("../src/tiny_gltf_v3.h");
return 0;
}
}