add bindings
This commit is contained in:
@@ -0,0 +1,297 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections;
|
||||
using System.Diagnostics;
|
||||
|
||||
using Cpp2Beef;
|
||||
using LibClang;
|
||||
|
||||
namespace KTX.Setup;
|
||||
|
||||
class ExampleGenerator : Cpp2BeefGenerator, this(Span<char8*> args)
|
||||
{
|
||||
protected override Span<char8*> Args => args;
|
||||
protected override Flags Flags => .None;
|
||||
|
||||
StreamWriter ktxWriter = new .()..Create("../src/KTX.bf")..Write("""
|
||||
// This file was generated by Cpp2Beef
|
||||
|
||||
using System;
|
||||
using System.Interop;
|
||||
|
||||
namespace KTX;
|
||||
|
||||
|
||||
""") ~ delete _;
|
||||
StreamWriter ktxVulkanWriter = new .()..Create("../src/KTXVulkan.bf")..Write("""
|
||||
// This file was generated by Cpp2Beef
|
||||
|
||||
using System;
|
||||
using System.Interop;
|
||||
|
||||
namespace KTX;
|
||||
|
||||
|
||||
""") ~ delete _;
|
||||
StreamWriter khrDfWriter = new .()..Create("../src/KHR_df.bf")..Write("""
|
||||
// This file was generated by Cpp2Beef
|
||||
|
||||
using System;
|
||||
using System.Interop;
|
||||
|
||||
namespace KTX;
|
||||
|
||||
|
||||
""") ~ delete _;
|
||||
|
||||
protected override StreamWriter GetWriterForHeader(StringView header)
|
||||
{
|
||||
if (header.EndsWith("ktx.h"))
|
||||
return ktxWriter;
|
||||
if (header.EndsWith("ktxvulkan.h"))
|
||||
return ktxVulkanWriter;
|
||||
if (header.EndsWith("khr_df.h"))
|
||||
return khrDfWriter;
|
||||
return null;
|
||||
}
|
||||
|
||||
Dictionary<String, CXType> vtblPfns = new .(24) ~ DeleteDictionaryAndKeys!(_);
|
||||
|
||||
protected override void HandleCursor(CXCursor cursor)
|
||||
{
|
||||
switch (cursor.kind)
|
||||
{
|
||||
case .TypedefDecl:
|
||||
let spelling = GetCursorSpelling!(cursor);
|
||||
if (spelling == "ktxHashList" || spelling == "ktxHashListEntry" || spelling == "ktxStream")
|
||||
return;
|
||||
case .MacroDefinition:
|
||||
let spelling = GetCursorSpelling!(cursor);
|
||||
if (spelling == "KTXTEXTURECLASSDEFN" || spelling == "KTX_APIENTRYP" || spelling == "KTX_API" ||
|
||||
spelling == "KTX_APIENTRY" || spelling == "KTX_error_code")
|
||||
return;
|
||||
|
||||
if (Clang.Cursor_IsMacroFunctionLike(cursor) == 0 || !spelling.StartsWith("ktx")) break;
|
||||
BeginCursor(cursor);
|
||||
AccessSpecifier(cursor);
|
||||
str.Append("static ");
|
||||
let nameInBindings = spelling[(spelling.IndexOf('_')+1)...];
|
||||
Runtime.Assert(vtblPfns.TryGetAlt(nameInBindings, ?, let pfnType));
|
||||
Type(Clang.GetResultType(pfnType));
|
||||
str.Append(' ');
|
||||
str.Append(nameInBindings);
|
||||
Flush();
|
||||
let tokens = ScopeTokenize!(cursor, unit);
|
||||
WriteTokens(tokens[1...], Clang.GetRangeEnd(Clang.Cursor_GetSpellingNameRange(cursor, 0, 0)), .Identifier);
|
||||
String buffer = scope .(256)..Append(str);
|
||||
uint32 argI = 0;
|
||||
insert: for (int i = 0; i < buffer.Length; i++)
|
||||
{
|
||||
switch (buffer[i])
|
||||
{
|
||||
case '(', ',':
|
||||
str.Clear();
|
||||
Type(Clang.GetArgType(pfnType, argI++));
|
||||
str.Append(' ');
|
||||
int idx = i+1 + (_ == ',' ? 1 : 0);
|
||||
buffer.Insert(idx, str);
|
||||
case ')':
|
||||
buffer.Insert(i+1, " =>");
|
||||
break insert;
|
||||
}
|
||||
}
|
||||
buffer.Replace("->", ".");
|
||||
str.Set(buffer);
|
||||
str.Append(';');
|
||||
return;
|
||||
case .StructDecl:
|
||||
if (Clang.Cursor_IsAnonymous(cursor) != 0)
|
||||
return;
|
||||
if (Clang.GetCursorLexicalParent(cursor).kind == .StructDecl)
|
||||
return;
|
||||
let spelling = GetCursorSpelling!(cursor);
|
||||
if (spelling == "ktxKVListEntry" || (spelling == "ktxStream" && Clang.EqualCursors(cursor, Clang.GetTypeDeclaration(Clang.GetCursorType(cursor))) != 0))
|
||||
return;
|
||||
BeginCursor(cursor);
|
||||
Record(cursor);
|
||||
return;
|
||||
case .FieldDecl:
|
||||
if (GetCursorSpelling!(Clang.GetCursorSemanticParent(cursor)) == "ktxTexture_vtbl")
|
||||
vtblPfns.Add(new .(GetCursorSpelling!(cursor)),
|
||||
Clang.GetPointeeType(Clang.GetTypedefDeclUnderlyingType(Clang.GetTypeDeclaration(Clang.GetCursorType(cursor))))
|
||||
);
|
||||
default:
|
||||
}
|
||||
base.HandleCursor(cursor);
|
||||
if (fileInfo.prevEnd == default)
|
||||
fileInfo.prevEnd = GetCursorAnchor(cursor);
|
||||
}
|
||||
|
||||
append String blockBuffer;
|
||||
protected override Block GetCursorBlock(CXCursor cursor)
|
||||
{
|
||||
if (cursor.kind == .FunctionDecl || cursor.kind == .MacroDefinition) do
|
||||
{
|
||||
let spelling = GetCursorSpelling!(cursor);
|
||||
if (!spelling.StartsWith("ktx")) break;
|
||||
int index = spelling.IndexOf('_');
|
||||
if (index < 0) break;
|
||||
blockBuffer.Set(spelling[..<index]);
|
||||
return .CustomBlock(blockBuffer);
|
||||
}
|
||||
return base.GetCursorBlock(cursor);
|
||||
}
|
||||
|
||||
protected override void WriteCustomAttributes(CXCursor cursor)
|
||||
{
|
||||
if (cursor.kind == .FunctionDecl || (cursor.kind == .TypedefDecl &&
|
||||
{
|
||||
let type = Clang.GetTypedefDeclUnderlyingType(cursor);
|
||||
let pointee = Clang.GetPointeeType(type).kind;
|
||||
type.kind == .Pointer && (pointee == .FunctionNoProto || pointee == .FunctionProto)
|
||||
}))
|
||||
{
|
||||
str.Append("[CallingConvention(KTX_APIENTRYP)] ");
|
||||
}
|
||||
base.WriteCustomAttributes(cursor);
|
||||
}
|
||||
|
||||
protected override void WriteTokensAfterEquals(CXCursor cursor)
|
||||
{
|
||||
if (cursor.kind == .ParmDecl)
|
||||
return; // avoid clang compiler bug
|
||||
base.WriteTokensAfterEquals(cursor);
|
||||
}
|
||||
|
||||
protected override void WriteToken(CXToken token)
|
||||
{
|
||||
if (currentCursor.kind == .MacroDefinition)
|
||||
{
|
||||
let cursorSpelling = GetCursorSpelling!(currentCursor);
|
||||
if (Clang.GetTokenKind(token) == .Punctuation && cursorSpelling == "KTX_IDENTIFIER_REF")
|
||||
switch (GetTokenSpelling!(token))
|
||||
{
|
||||
case "{": str.Append("uint8[?]("); return;
|
||||
case "}": str.Append(')'); return;
|
||||
}
|
||||
else if (cursorSpelling == "KTX_TRUE" || cursorSpelling == "KTX_FALSE")
|
||||
{
|
||||
str.Append(GetTokenSpelling!(token));
|
||||
return;
|
||||
}
|
||||
else if (cursorSpelling == "KTX_FACESLICE_WHOLE_LEVEL")
|
||||
{
|
||||
str.Append("uint32.MaxValue");
|
||||
return;
|
||||
}
|
||||
}
|
||||
base.WriteToken(token);
|
||||
}
|
||||
|
||||
protected override void Type(CXType type, TypeParamMode paramMode = .None)
|
||||
{
|
||||
if (currentCursor.kind == .TypedefDecl && Clang.EqualTypes(Clang.GetCursorType(currentCursor), type) != 0 && GetTypeSpelling!(type) == "ktx_uint32_t")
|
||||
{
|
||||
let cursorSpelling = GetCursorSpelling!(currentCursor);
|
||||
str.Append(cursorSpelling);
|
||||
if (cursorSpelling.EndsWith("_flags"))
|
||||
{
|
||||
str.Length--;
|
||||
str.Append("_bits");
|
||||
}
|
||||
str.Append("_e");
|
||||
return;
|
||||
}
|
||||
base.Type(type, paramMode);
|
||||
}
|
||||
|
||||
protected override void GetNameInBindings(CXCursor cursor, String outString)
|
||||
{
|
||||
switch (cursor.kind)
|
||||
{
|
||||
case .EnumDecl:
|
||||
var spelling = GetCursorSpelling!(cursor);
|
||||
if (spelling.StartsWith("_khr"))
|
||||
spelling.RemoveFromStart(1);
|
||||
outString.Append(spelling);
|
||||
return;
|
||||
case .EnumConstantDecl:
|
||||
var parent = GetCursorSpelling!(Clang.GetCursorSemanticParent(cursor));
|
||||
if (parent == "ktx_error_code_e") break;
|
||||
if (parent == "_khr_word_e")
|
||||
parent = "khr_df_word_e";
|
||||
var spelling = GetCursorSpelling!(cursor);
|
||||
if (parent == "_khr_df_model_channels_e")
|
||||
{
|
||||
spelling.RemoveFromStart("KHR_DF_CHANNEL_".Length);
|
||||
outString.Append(spelling);
|
||||
return;
|
||||
}
|
||||
if (parent == "ktxSupercmpScheme")
|
||||
{
|
||||
spelling.RemoveFromStart("KTX_SS_".Length);
|
||||
UpperSnakeCase2PascalCase(spelling, outString);
|
||||
return;
|
||||
}
|
||||
if (parent == "ktxTextureCreateStorageEnum")
|
||||
{
|
||||
spelling.RemoveFromStart("KTX_TEXTURE_CREATE_".Length);
|
||||
UpperSnakeCase2PascalCase(spelling, outString);
|
||||
return;
|
||||
}
|
||||
if (parent == "ktxTextureCreateFlagBits")
|
||||
{
|
||||
spelling.RemoveFromStart("KTX_TEXTURE_CREATE_".Length);
|
||||
if (spelling.EndsWith("_BIT"))
|
||||
spelling.RemoveFromEnd(4);
|
||||
UpperSnakeCase2PascalCase(spelling, outString);
|
||||
return;
|
||||
}
|
||||
for (var part in parent.Split('_', .RemoveEmptyEntries))
|
||||
{
|
||||
if (part == "e") break;
|
||||
part.Length++;
|
||||
if (!spelling.StartsWith(part, .OrdinalIgnoreCase))
|
||||
{
|
||||
if (part.EndsWith("s_") && spelling.StartsWith(part[..<^2], .OrdinalIgnoreCase))
|
||||
part.Length--;
|
||||
else
|
||||
break;
|
||||
}
|
||||
spelling.RemoveFromStart(part.Length);
|
||||
}
|
||||
if (spelling[0].IsDigit)
|
||||
outString.Append('_');
|
||||
UpperSnakeCase2PascalCase(spelling, outString);
|
||||
return;
|
||||
case .FunctionDecl:
|
||||
let spelling = GetCursorSpelling!(cursor);
|
||||
int index = spelling.IndexOf('_');
|
||||
if (index < 0) break;
|
||||
outString.Append(spelling[(index+1)...]);
|
||||
return;
|
||||
default:
|
||||
}
|
||||
base.GetNameInBindings(cursor, outString);
|
||||
}
|
||||
}
|
||||
|
||||
class Program
|
||||
{
|
||||
[CLink] static extern int32 system(char8*);
|
||||
|
||||
public static int Main(String[] args)
|
||||
{
|
||||
if (system("git -C .. submodule init") != 0)
|
||||
Runtime.FatalError("Failed to fetch KTX-Software");
|
||||
/*if (system(scope $"wget -O include/KHR/khr_df.h https://registry.khronos.org/DataFormat/api/1.3/khr_df.h") != 0)
|
||||
Runtime.FatalError("Failed to download khr_df.h");
|
||||
if (system(scope $"wget -O include/vulkan_core.h https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/refs/heads/main/include/vulkan/vulkan_core.h") != 0)
|
||||
Runtime.FatalError("Failed to download vulkan_core.h");
|
||||
if (system(scope $"wget -O include/vk_platform.h https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/refs/heads/main/include/vulkan/vk_platform.h") != 0)
|
||||
Runtime.FatalError("Failed to download vk_platform.h");*/
|
||||
|
||||
scope ExampleGenerator(char8*[?]("--language=c", "-I../KTX-Software/lib/include", "-I../KTX-Software/external/dfdutils", "-DKTX_DOXYGEN_SKIP")).Generate("include/all.h");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user