New auto-generated D bindings (#3114)

* Added shaderc default defines to docs

* Update tools.rst

* Update tools.rst

* WIP new D bindings

* New bindings "nearly done"

* More unfinished changes

* Nearly done; ctors still don't work

* Bindings auto-generation is done

* New auto-generated D bindings

* Reduced D bindings file count back to 2

---------

Co-authored-by: Бранимир Караџић <branimirkaradzic@gmail.com>
This commit is contained in:
IchorDev 2023-06-27 01:21:22 +07:00 committed by GitHub
parent c913c2e76a
commit cbd83f57ca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 4381 additions and 5979 deletions

View File

@ -72,7 +72,7 @@ Languages:
* [C/C++ API documentation](https://bkaradzic.github.io/bgfx/bgfx.html)
* [Beef API bindings](https://github.com/bkaradzic/bgfx/tree/master/bindings/bf)
* [C# language API bindings #1](https://github.com/bkaradzic/bgfx/tree/master/bindings/cs)
* [D language API bindings](https://github.com/GoaLitiuM/bindbc-bgfx)
* [D language API bindings](https://github.com/BindBC/bindbc-bgfx)
* [Go language API bindings](https://github.com/james4k/go-bgfx)
* [Haskell language API bindings](https://github.com/haskell-game/bgfx)
* [Lightweight Java Game Library 3 bindings](https://github.com/LWJGL/lwjgl3)

79
bindings/d/fakeenum.d Normal file
View File

@ -0,0 +1,79 @@
/+
+ ==============================
+ AUTO GENERATED! DO NOT EDIT!
+ ==============================
+/
module bgfx.fakeenum;
//NOTE: Do NOT use this module! Use the enums with the same names in `bgfx/package.d` instead.
package:
extern(C++, "bgfx") package final abstract class Fatal{
enum Enum{
debugCheck,invalidShader,unableToInitialize,unableToCreateTexture,deviceLost,count
}
}
extern(C++, "bgfx") package final abstract class RendererType{
enum Enum{
noop,agc,direct3D9,direct3D11,direct3D12,gnm,metal,nvn,openGLES,openGL,vulkan,webGPU,count
}
}
extern(C++, "bgfx") package final abstract class Access{
enum Enum{
read,write,readWrite,count
}
}
extern(C++, "bgfx") package final abstract class Attrib{
enum Enum{
position,normal,tangent,bitangent,color0,color1,color2,color3,indices,weight,texCoord0,texCoord1,texCoord2,texCoord3,texCoord4,texCoord5,texCoord6,texCoord7,count
}
}
extern(C++, "bgfx") package final abstract class AttribType{
enum Enum{
uint8,uint10,int16,half,float_,count
}
}
extern(C++, "bgfx") package final abstract class TextureFormat{
enum Enum{
bc1,bc2,bc3,bc4,bc5,bc6h,bc7,etc1,etc2,etc2a,etc2a1,ptc12,ptc14,ptc12a,ptc14a,ptc22,ptc24,atc,atce,atci,astc4x4,astc5x4,astc5x5,astc6x5,astc6x6,astc8x5,astc8x6,astc8x8,astc10x5,astc10x6,astc10x8,astc10x10,astc12x10,astc12x12,unknown,r1,a8,r8,r8i,r8u,r8s,r16,r16i,r16u,r16f,r16s,r32i,r32u,r32f,rg8,rg8i,rg8u,rg8s,rg16,rg16i,rg16u,rg16f,rg16s,rg32i,rg32u,rg32f,rgb8,rgb8i,rgb8u,rgb8s,rgb9e5f,bgra8,rgba8,rgba8i,rgba8u,rgba8s,rgba16,rgba16i,rgba16u,rgba16f,rgba16s,rgba32i,rgba32u,rgba32f,b5g6r5,r5g6b5,bgra4,rgba4,bgr5a1,rgb5a1,rgb10a2,rg11b10f,unknownDepth,d16,d24,d24s8,d32,d16f,d24f,d32f,d0s8,count
}
}
extern(C++, "bgfx") package final abstract class UniformType{
enum Enum{
sampler,end,vec4,mat3,mat4,count
}
}
extern(C++, "bgfx") package final abstract class BackbufferRatio{
enum Enum{
equal,half,quarter,eighth,sixteenth,double_,count
}
}
extern(C++, "bgfx") package final abstract class OcclusionQueryResult{
enum Enum{
invisible,visible,noResult,count
}
}
extern(C++, "bgfx") package final abstract class Topology{
enum Enum{
triList,triStrip,lineList,lineStrip,pointList,count
}
}
extern(C++, "bgfx") package final abstract class TopologyConvert{
enum Enum{
triListFlipWinding,triStripFlipWinding,triListToLineList,triStripToTriList,lineStripToLineList,count
}
}
extern(C++, "bgfx") package final abstract class TopologySort{
enum Enum{
directionFrontToBackMin,directionFrontToBackAvg,directionFrontToBackMax,directionBackToFrontMin,directionBackToFrontAvg,directionBackToFrontMax,distanceFrontToBackMin,distanceFrontToBackAvg,distanceFrontToBackMax,distanceBackToFrontMin,distanceBackToFrontAvg,distanceBackToFrontMax,count
}
}
extern(C++, "bgfx") package final abstract class ViewMode{
enum Enum{
default_,sequential,depthAscending,depthDescending,count
}
}
extern(C++, "bgfx") package final abstract class RenderFrame{
enum Enum{
noContext,render,timeout,exiting,count
}
}

File diff suppressed because it is too large Load Diff

3608
bindings/d/package.d Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -60,7 +60,7 @@ Supported Languages
- `C/C++ API documentation <https://bkaradzic.github.io/bgfx/bgfx.html>`__
- `Beef API bindings <https://github.com/bkaradzic/bgfx/tree/master/bindings/bf>`__
- `C# language API bindings #1 <https://github.com/bkaradzic/bgfx/tree/master/bindings/cs>`__
- `D language API bindings <https://github.com/GoaLitiuM/bindbc-bgfx>`__
- `D language API bindings <https://github.com/BindBC/bindbc-bgfx>`__
- `Go language API bindings <https://github.com/james4k/go-bgfx>`__
- `Haskell language API bindings <https://github.com/haskell-game/bgfx>`__
- `Lightweight Java Game Library 3 bindings <https://github.com/LWJGL/lwjgl3#lwjgl---lightweight-java-game-library-3>`__

View File

@ -1,85 +1,123 @@
local codegen = require "codegen"
local idl = codegen.idl "bgfx.idl"
local d_types_template = [[
/*
*
* AUTO GENERATED! DO NOT EDIT!
*
*/
local template = [[
/+
+ ==============================
+ AUTO GENERATED! DO NOT EDIT!
+ ==============================
+/
module bgfx;
module bindbc.bgfx.types;
import bindbc.bgfx.config;
public import core.stdc.stdarg : va_list;
enum expandEnum(EnumType, string fqnEnumType = EnumType.stringof) = (){
string expandEnum;
foreach(m; __traits(allMembers, EnumType)){
expandEnum ~= "alias " ~ m ~ " = " ~ fqnEnumType ~ "." ~ m ~ ";";
}
return expandEnum;
}();
extern(C) @nogc nothrow:
import bindbc.common.types: va_list;
static import bgfx.fakeenum;
$version
alias bgfx_view_id_t = ushort;
alias ViewId = ushort;
enum invalidHandle(T) = T(ushort.max);
//NOTE: TEMPORARY fix to some missing preprocessor function-macros...
static BGFX_STATE_BLEND_FUNC_SEPARATE(ulong _srcRGB, ulong _dstRGB, ulong _srcA, ulong _dstA){
return (0UL
| ( ( cast(ulong)_srcRGB | ( cast(ulong)_dstRGB<<4) ) )
| ( ( cast(ulong)_srcA | ( cast(ulong)_dstA <<4) )<<8)
);
alias ReleaseFn = void function(void* _ptr, void* _userData);
$types
pragma(inline,true) nothrow @nogc pure @safe{
StateBlend_ blendFuncSeparate(StateBlend_ srcRGB, StateBlend_ dstRGB, StateBlend_ srcA, StateBlend_ dstA){
return (srcRGB | ((dstRGB) << 4)) | ((srcA | (dstA << 4)) << 8);
}
///Blend equation separate.
static BGFX_STATE_BLEND_EQUATION_SEPARATE(ulong _equationRGB, ulong _equationA){ return ( cast(ulong)_equationRGB | (cast(ulong)_equationA<<3) ); }
StateBlendEquation_ blendEquationSeparate(StateBlendEquation_ equationRGB, StateBlendEquation_ equationA){
return equationRGB | (equationA << 3);
}
///Blend function.
static BGFX_STATE_BLEND_FUNC(ulong _src, ulong _dst){ return BGFX_STATE_BLEND_FUNC_SEPARATE(_src, _dst, _src, _dst); }
StateBlend_ blendFunc(StateBlend_ src, StateBlend_ dst){ return blendFuncSeparate(src, dst, src, dst); }
///Blend equation.
static BGFX_STATE_BLEND_EQUATION(ulong _equation){ return BGFX_STATE_BLEND_EQUATION_SEPARATE(_equation, _equation); }
StateBlendEquation_ blendEquation(StateBlendEquation_ equation){ return blendEquationSeparate(equation, equation); }
///Utility predefined blend modes.
enum StateBlendFunc: StateBlend_{
///Additive blending.
static BGFX_STATE_BLEND_ADD(){ return (0 | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_ONE, BGFX_STATE_BLEND_ONE)); }
add = blendFunc(StateBlend.one, StateBlend.one),
///Alpha blend.
static BGFX_STATE_BLEND_ALPHA(){ return (0 | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA)); }
alpha = blendFunc(StateBlend.srcAlpha, StateBlend.invSrcAlpha),
$types
]]
///Selects darker color of blend.
darken = blendFunc(StateBlend.one, StateBlend.one) | blendEquation(StateBlendEquation.min),
local d_funcs_template = [[
/*
*
* AUTO GENERATED! DO NOT EDIT!
*
*/
///Selects lighter color of blend.
lighten = blendFunc(StateBlend.one, StateBlend.one) | blendEquation(StateBlendEquation.max),
module bindbc.bgfx.funcs;
///Multiplies colors.
multiply = blendFunc(StateBlend.dstColor, StateBlend.zero),
private import bindbc.bgfx.types;
///Opaque pixels will cover the pixels directly below them without any math or algorithm applied to them.
normal = blendFunc(StateBlend.one, StateBlend.invSrcAlpha),
extern(C) @nogc nothrow:
///Multiplies the inverse of the blend and base colors.
screen = blendFunc(StateBlend.one, StateBlend.invSrcColor),
version(BindBgfx_Static)
{
$funcs_static
///Decreases the brightness of the base color based on the value of the blend color.
linearBurn = blendFunc(StateBlend.dstColor, StateBlend.invDstColor) | blendEquation(StateBlendEquation.sub),
}
else
{
__gshared
{
$funcs_dynamic
StateBlend_ blendFuncRTx(StateBlend_ src, StateBlend_ dst){
return cast(uint)(src >> StateBlend.shift) | (cast(uint)(dst >> StateBlend.shift) << 4);
}
StateBlend_ blendFuncRTxE(StateBlend_ src, StateBlend_ dst, StateBlendEquation_ equation){
return blendFuncRTx(src, dst) | (cast(uint)(equation >> StateBlendEquation.shift) << 8);
}
StateBlend_ blendFuncRT1(StateBlend_ src, StateBlend_ dst){ return blendFuncRTx(src, dst) << 0; }
StateBlend_ blendFuncRT2(StateBlend_ src, StateBlend_ dst){ return blendFuncRTx(src, dst) << 11; }
StateBlend_ blendFuncRT3(StateBlend_ src, StateBlend_ dst){ return blendFuncRTx(src, dst) << 22; }
StateBlend_ blendFuncRT1E(StateBlend_ src, StateBlend_ dst, StateBlendEquation_ equation){
return blendFuncRTxE(src, dst, equation) << 0;
}
StateBlend_ blendFuncRT2E(StateBlend_ src, StateBlend_ dst, StateBlendEquation_ equation){
return blendFuncRTxE(src, dst, equation) << 11;
}
StateBlend_ blendFuncRT3E(StateBlend_ src, StateBlend_ dst, StateBlendEquation_ equation){
return blendFuncRTxE(src, dst, equation) << 22;
}
}
$structs
mixin(joinFnBinds((){
string[][] ret;
ret ~= makeFnBinds([
$funcs
]);
return ret;
}(), __MODULE__, $membersWithFns));
static if(!staticBinding):
import bindbc.loader;
debug{
mixin(makeDynloadFns("Bgfx", makeLibPaths(["bgfx-shared-libDebug", "bgfxDebug", "bgfx"]), [__MODULE__]));
}else{
mixin(makeDynloadFns("Bgfx", makeLibPaths(["bgfx-shared-libRelease", "bgfxRelease", "bgfx"]), [__MODULE__]));
}
]]
local dKeywords = {"abstract", "alias", "align", "asm", "assert", "auto", "bool", "break", "byte", "case", "cast", "catch", "char", "class", "const", "continue", "dchar", "debug", "default", "delegate", "deprecated", "do", "double", "else", "enum", "export", "extern", "false", "final", "finally", "float", "for", "foreach", "foreach_reverse", "function", "goto", "if", "immutable", "import", "in", "inout", "int", "interface", "invariant", "is", "lazy", "long", "macro", "mixin", "module", "new", "nothrow", "null", "out", "override", "package", "pragma", "private", "protected", "public", "pure", "real", "ref", "return", "scope", "shared", "short", "static", "struct", "super", "switch", "synchronized", "template", "this", "throw", "true", "try", "typeid", "typeof", "ubyte", "uint", "ulong", "union", "unittest", "ushort", "version", "void", "wchar", "while", "with"}
local function contains(table, val)
for i=1,#table do
if table[i] == val then
return true
end
end
return false
end
local function hasPrefix(str, prefix)
return prefix == "" or str:sub(1, #prefix) == prefix
end
@ -88,83 +126,288 @@ local function hasSuffix(str, suffix)
return suffix == "" or str:sub(-#suffix) == suffix
end
local function to_underscorecase(name)
local tmp = {}
for v in name:gmatch "[_%u][%l%d]*" do
if v:byte() == 95 then -- '_'
v = v:sub(2) -- remove _
local enumTypes = {}
local membersWithFns = ""
local capsWords = {"Mip", "Id", "Rw", "Rt", "Pci", "Srgb", "Pt", "Ccw", "2d", "3d", "Msaa"}
local capsRepl = {
hidpi = "hiDPI", lineaa = "lineAA", maxanisotropy = "maxAnisotropy",
notequal = "notEqual", gequal = "gEqual", lequal = "lEqual",
decrsat = "decrSat", incrsat = "incrSat", revsub = "revSub",
linestrip = "lineStrip", tristrip = "triStrip",
}
local function abbrevsToUpper(name)
if name:len() >= 3 then
for _, abbrev in pairs(capsWords) do
name = name:gsub(abbrev, function(s0)
return s0:upper()
end)
end
tmp[#tmp+1] = v
for from, to in pairs(capsRepl) do
name = name:gsub(from, to)
end
return table.concat(tmp, "_")
end
return name
end
local function convert_array(member)
if string.find(member.array, "::") then
local name = "bgfx_" .. to_underscorecase(string.gsub(member.array, "::.*", "")):lower() .. "_t"
return "[" .. name .. ".BGFX_" .. to_underscorecase(member.array):upper() .. "]"
local function toCamelCase(name)
if name:len() >= 3 then
name = name:sub(0, 1) .. name:sub(2, -2):gsub("_", "") .. name:sub(-1)
end
if name:find("%u%u+%l") then
name = name:gsub("(%u-)(%u%l)", function(s0, s1)
return s0:lower() .. s1
end)
else
return member.array
name = (name:gsub("^([^%l]*)(%l?)", function(s0, s1)
if s1 ~= nil then
return s0:lower() .. s1
end
return s0:lower()
end))
end
return abbrevsToUpper(name)
end
-- local function toPascalCase(name)
-- return (name:gsub("^%l", string.upper))
-- end
local usEnSubs = {Color = "Colour", Rasterize = "Rasterise", Initialize = "Initialise"}
local function toIntlEn(name)
local change = false
for us, intl in pairs(usEnSubs) do
if name:find(us) then
name = (name:gsub(us, intl))
change = true
end
end
if change then
return name
else
return nil
end
end
local function convert_type(arg)
local ctype = arg.ctype:gsub("%s%*", "*")
if arg.fulltype == "bx::AllocatorI*" or arg.fulltype == "CallbackI*" or arg.fulltype == "ReleaseFn" then
ctype = "void*"
elseif hasPrefix(ctype, "uint64_t") then
ctype = ctype:gsub("uint64_t", "ulong")
elseif hasPrefix(ctype, "int64_t") then
ctype = ctype:gsub("int64_t", "long")
elseif hasPrefix(ctype, "uint32_t") then
ctype = ctype:gsub("uint32_t", "uint")
elseif hasPrefix(ctype, "int32_t") then
ctype = ctype:gsub("int32_t", "int")
elseif hasPrefix(ctype, "uint16_t") then
ctype = ctype:gsub("uint16_t", "ushort")
elseif hasPrefix(ctype, "uint8_t") then
ctype = ctype:gsub("uint8_t", "ubyte")
elseif hasPrefix(ctype, "uintptr_t") then
ctype = ctype:gsub("uintptr_t", "ulong")
elseif hasPrefix(ctype, "const ") and hasSuffix(ctype, "*") then
ctype = "const(" .. string.sub(ctype:gsub("const ", "", 1), 1, -2) .. ")*"
local function hexStr(val, bits)
local digits = bits / 4
local str = string.format(string.format("%%0%iX", digits), val)
local i = 4
while i < str:len() do
str = str:sub(0, i) .. "_" .. str:sub(i+1)
i = i + 5
end
return "0x" .. str
end
local function convArray(array)
if string.find(array, "::") then
return string.gsub(array, "::.*", ".") .. toCamelCase(string.gsub(array, ".-::", ""))
else
return array
end
end
local typeSubs = {
uint32_t = "uint", int32_t = "int",
uint16_t = "ushort", int16_t = "short",
uint64_t = "ulong", int64_t = "long",
uint8_t = "ubyte", int8_t = "byte",
uintptr_t = "size_t"
}
local function convSomeType(arg, isFnArg)
local type = arg.fulltype
if type == "bx::AllocatorI*" or type == "CallbackI*" then
type = "void*"
else
for from, to in pairs(typeSubs) do
if type:find(from) then
type = type:gsub(from, to)
break
end
end
type = type:gsub("::Enum", "") --fix enums
type = type:gsub("%s+%*", "*") --remove spacing before `*`
if isFnArg then
for _, enum in pairs(enumTypes) do --fix C++ linkage errors
if type == enum then
type = string.format("bgfx.fakeenum.%s.Enum", enum)
else
type = (type:gsub("(" .. enum .. ")([^A-Za-z0-9_])", function(s0, s1)
return string.format("bgfx.fakeenum.%s.Enum", enum) .. s1
end))
end
end
type = type:gsub("([^&]-)%s?&", "ref %1") --change `&` suffix to `ref` prefix
if arg.array ~= nil then
ctype = ctype .. convert_array(arg)
type = type .. "*" --append *
end
else
type = type:gsub("([^&]-)%s?&", "%1*") --change `&` to `*`
if arg.array ~= nil then
type = type .. convArray(arg.array) --append [n]
end
end
type = type:gsub("const%s+([A-Za-z_][A-Za-z0-9_]*)%s*%*", "const(%1)*") --change `const x*` to `const(x)*`
end
return ctype
return type
end
local function convert_struct_type(arg)
return convert_type(arg)
local function convType(arg)
return convSomeType(arg, false)
end
local function convert_ret_type(arg)
return convert_type(arg)
local function convFnArgType(arg)
return convSomeType(arg, true)
end
local function convert_name(arg)
if arg == "debug" then
return arg .. "_"
local valSubs = {
NULL = "null",
UINT8_MAX = "ubyte.max",
UINT16_MAX = "ushort.max",
UINT32_MAX = "uint.max",
BGFX_INVALID_HANDLE = "invalidHandle",
BGFX_DISCARD_ALL = "Discard.all",
BGFX_BUFFER_NONE = "Buffer.none",
BGFX_STENCIL_NONE = "Stencil.none",
BGFX_TEXTURE_NONE = "Texture.none",
BGFX_SAMPLER_NONE = "Sampler.none",
BGFX_RESET_NONE = "Reset.none",
BGFX_SAMPLER_U_CLAMP = "SamplerU.clamp",
BGFX_SAMPLER_V_CLAMP = "SamplerV.clamp",
BGFX_RESOLVE_AUTO_GEN_MIPS = "Resolve.autoGenMIPs",
["ViewMode::Default"] = "ViewMode.default_",
}
local function convVal(arg, type)
local val = string.format("%s", arg)
for from, to in pairs(valSubs) do
if val:find(from) then
if from == "BGFX_INVALID_HANDLE" then
val = val:gsub(from, to .. "!" .. type)
else
val = val:gsub(from, to)
end
return arg
end
end
if val:find("INT32_MAX") then
val = val:gsub("INT32_MAX", "int.max")
end
val = convArray(val)
return val
end
local function convert_struct_member(member)
return convert_struct_type(member) .. " " .. convert_name(member.name)
local function convStructType(arg)
return convType(arg)
end
local function gen_version()
return "enum uint BGFX_API_VERSION = " .. (idl._version or 0) .. ";"
local function convName(name)
name = abbrevsToUpper(name)
if contains(dKeywords, name) then
return name .. "_"
end
return name
end
local function convStructMember(member)
return convStructType(member) .. " " .. convName(member.name)
end
local allStructs = {}
local function genVersion()
return "enum uint apiVersion = " .. (idl._version or 0) .. ";"
end
local function genStructMemberFn(func) --NOTE: this does not work on nested structs
if func.class ~= nil and func.conly == nil then
local st = allStructs[func.class]
local attribs = ""
if func.comments ~= nil then
if #st.fns > 0 then
table.insert(st.fns, "")
end
table.insert(st.fns, "/**")
for _, line in ipairs(func.comments) do
local line = line:gsub("@remarks", "Remarks:")
line = line:gsub("@remark", "Remarks:")
line = line:gsub("@(%l)(%l+)", function(a, b) return a:upper() .. b .. ":" end)
table.insert(st.fns, line)
end
local hasParamsComments = false
for _, arg in ipairs(func.args) do
if arg.comment ~= nil then
hasParamsComments = true
break
end
end
if hasParamsComments then
table.insert(st.fns, "Params:")
end
for _, arg in ipairs(func.args) do
if arg.comment ~= nil then
table.insert(st.fns, "\t" .. convName(arg.name:sub(2)) .. " = " .. arg.comment[1])
for i, comment in ipairs(arg.comment) do
if i > 1 then
table.insert(st.fns, comment)
end
end
end
end
table.insert(st.fns, "*/")
end
local args = {}
for _, arg in ipairs(func.args) do
local def = ""
if arg.default ~= nil then
def = string.format("=%s", convVal(arg.default, convFnArgType(arg)))
end
if arg.fulltype == "..." then
table.insert(args, "..." .. def)
else
table.insert(args, convFnArgType(arg) .. " " .. convName(arg.name:sub(2)) .. def)
end
end
if func.const ~= nil then
attribs = "const"
end
if attribs ~= "" then
attribs = ", q{" .. attribs .. "}"
end
table.insert(st.fns, string.format("[q{%s}, q{%s}, q{%s}, `C++`%s],", convType(func.ret), func.name, table.concat(args, ", "), attribs))
end
end
local converter = {}
local yield = coroutine.yield
local gen = {}
function gen.gen(template)
gen.fakeEnumFile = [[
/+
+ ==============================
+ AUTO GENERATED! DO NOT EDIT!
+ ==============================
+/
module bgfx.fakeenum;
//NOTE: Do NOT use this module! Use the enums with the same names in `bgfx/package.d` instead.
package:
]]
function gen.gen()
local indent = ""
local idx = 1;
local r = template:gsub("$([a-zA-Z_]+)", function(what)
@ -183,13 +426,32 @@ function gen.gen(template)
indent = string.sub(template, ind_start+1, ind_end-1)
local what_idl = what:gsub("funcs_dynamic", "funcs"):gsub("funcs_static", "funcs")
if (what == "version") then
return gen_version()
if what == "version" then
return genVersion()
elseif what == "structs" then
for _, fn in ipairs(idl.funcs) do
genStructMemberFn(fn)
end
for _, object in ipairs(idl[what_idl]) do
for name, object in pairs(allStructs) do
local co = coroutine.create(converter[what])
local any
while true do
local ok, v = coroutine.resume(co, object, name, indent:len())
assert(ok, debug.traceback(co, v))
if not v then
break
end
table.insert(tmp, v)
any = true
end
if any and tmp[#tmp] ~= "" then
table.insert(tmp, "")
end
end
elseif what == "membersWithFns" then
table.insert(tmp, "\"" .. membersWithFns .. "\"")
else
for _, object in ipairs(idl[what]) do
local co = coroutine.create(converter[what])
local any
while true do
@ -205,21 +467,58 @@ function gen.gen(template)
table.insert(tmp, "")
end
end
end
return table.concat(tmp, "\n" .. indent)
end)
return r
end
function gen.gen_types()
return gen.gen(d_types_template)
function converter.structs(st, name)
for _, line in ipairs(st.comments) do
yield(line)
end
function gen.gen_funcs()
return gen.gen(d_funcs_template)
yield("extern(C++, \"bgfx\") struct " .. name .. "{")
local subN = 0
for subName, subStruct in pairs(st.subs) do
subN = subN + 1
local co = coroutine.create(converter.structs)
while true do
local ok, v = coroutine.resume(co, subStruct, subName)
assert(ok, debug.traceback(co, v))
if not v then
break
end
yield("\t" .. v)
end
end
if subN > 0 then
yield("\t")
end
for _, line in ipairs(st.fields) do
yield(line)
end
if #st.fns > 0 then
membersWithFns = membersWithFns .. name .. ", "
yield("\textern(D) mixin(joinFnBinds((){")
yield("\t\tstring[][] ret;")
yield("\t\tret ~= makeFnBinds([")
for _, line in ipairs(st.fns) do
yield("\t\t\t" .. line)
end
yield("\t\t], true);")
yield("\t\treturn ret;")
yield("\t}(), typeof(this).stringof));")
end
yield("}")
end
function converter.types(typ)
if typ.comments ~= nil then
if typ.comments ~= nil and not typ.struct then
if #typ.comments == 1 then
yield("///" .. typ.comments[1])
else
@ -231,12 +530,33 @@ function converter.types(typ)
end
end
if typ.handle then
yield("struct " .. typ.cname .. " { ushort idx; }")
if typ.handle then ---hnadle
yield("extern(C++, \"bgfx\") struct " .. typ.name .. "{")
yield("\tushort idx;")
yield("}")
--yield(typ.name .. " invalidHandle(){ return " .. typ.name .. "(ushort.max); }")
elseif typ.funcptr then
local args = {}
for _, arg in ipairs(func.args) do
if arg.fulltype == "..." then
table.insert(args, "..." .. def)
else
table.insert(args, convFnArgType(arg) .. " " .. convName(arg.name:sub(2)) .. def)
end
end
yield(string.format("alias %s = extern(C++) %s function(%s);", func.name, convType(func.ret), table.concat(args, ", ")))
elseif typ.enum then
local prefix = "BGFX_" .. to_underscorecase(string.gsub(typ.name, "::Enum", "")):upper()
yield("enum " .. typ.cname)
yield("{")
local typeName = abbrevsToUpper(typ.name:gsub("::Enum", ""))
local otherName = string.format("bgfx.fakeenum.%s.Enum", typeName)
yield("")
yield("enum " .. typeName .. ": " .. otherName .. "{")
table.insert(enumTypes, typeName)
local vals = ""
for idx, enum in ipairs(typ.enum) do
local comments = ""
if enum.comment ~= nil then
@ -245,59 +565,116 @@ function converter.types(typ)
else
yield("\t/**")
for _, comment in ipairs(enum.comment) do
yield("\t * " .. comment)
yield("\t" .. comment)
end
yield("\t*/")
end
end
local name = convName(toCamelCase(enum.name))
yield("\t" .. name .. " = " .. otherName .. "." .. name .. ",")
vals = vals .. name .. ","
local enumname
if enum.underscore then
enumname = to_underscorecase(enum.name):upper()
else
enumname = enum.name:upper()
local intlName = toIntlEn(enum.name)
if intlName ~= nil then
yield("\t" .. convName(toCamelCase(intlName)) .. " = " .. otherName .. "." .. name .. ",")
end
end
yield("\t" .. prefix .. "_" .. enumname .. "," .. comments)
end
yield("");
--yield("\t" .. prefix .. "_COUNT = " .. #typ.enum)
yield("\t" .. prefix .. "_COUNT")
gen.fakeEnumFile = gen.fakeEnumFile .. string.format([[
extern(C++, "bgfx") package final abstract class %s{
enum Enum{
%scount
}
}
]], typeName, vals)
yield("\t" .. "count = " .. otherName .. ".count,")
yield("}")
yield("mixin(expandEnum!" .. typ.cname .. ");")
elseif typ.bits ~= nil then
local prefix = "BGFX_" .. to_underscorecase(typ.name):upper()
local typeName = convName(typ.name)
if typeName == "Caps" then
typeName = "CapFlags"
end
local enumType = "uint"
format = "%u"
if typ.bits == 64 then
format = "0x%016x"
enumType = "ulong"
elseif typ.bits == 32 then
format = "0x%08x"
enumType = "uint"
elseif typ.bits == 16 then
format = "0x%04x"
enumType = "ushort"
elseif typ.bits == 8 then
format = "0x%02x"
enumType = "ubyte"
end
local maxLen = 0
if typ.shift then
maxLen = string.len("shift")
elseif typ.range then
maxLen = string.len("mask")
end
for _, flag in ipairs(typ.flag) do
maxLen = math.max(maxLen, flag.name:len())
end
yield("alias " .. typeName .. "_ = " .. enumType .. ";")
yield("enum " .. typeName .. ": " .. typeName .. "_{")
local function getValOr(name)
local t = typeName
if typeName == "State" then
if hasPrefix(name, "Write") then
t = t .. name:sub(1, 5)
name = name:sub(6)
elseif hasPrefix(name, "DepthTest") then
t = t .. name:sub(1, 9)
name = name:sub(10)
elseif hasPrefix(name, "Cull") then
t = t .. name:sub(1, 4)
name = name:sub(5)
end
elseif typeName == "Sampler" then
if hasPrefix(name, "Min") then
t = t .. name:sub(1, 3)
name = name:sub(4)
elseif hasPrefix(name, "Mag") then
t = t .. name:sub(1, 3)
name = name:sub(4)
elseif hasPrefix(name, "Mip") then
t = t .. name:sub(1, 3)
name = name:sub(4)
elseif hasPrefix(name, "U") then
t = t .. name:sub(1, 1)
name = name:sub(2)
elseif hasPrefix(name, "V") then
t = t .. name:sub(1, 1)
name = name:sub(2)
elseif hasPrefix(name, "W") then
t = t .. name:sub(1, 1)
name = name:sub(2)
elseif hasPrefix(name, "Compare") then
t = t .. name:sub(1, 7)
name = name:sub(8)
end
end
return abbrevsToUpper(t) .. "." .. convName(toCamelCase(name))
end
for idx, flag in ipairs(typ.flag) do
local value = flag.value
if value ~= nil then
value = string.format(flag.format or format, value)
value = hexStr(value, typ.bits)
else
for _, name in ipairs(flag) do
local fixedname = prefix .. "_" .. to_underscorecase(name):upper()
if value ~= nil then
value = value .. " | " .. fixedname
value = value .. " | " .. getValOr(name)
else
value = fixedname
value = getValOr(name)
end
end
end
local comments = ""
if flag.comment ~= nil then
if #flag.comment == 1 then
@ -305,45 +682,73 @@ function converter.types(typ)
else
yield("/**")
for _, comment in ipairs(flag.comment) do
yield(" * " .. comment)
yield(comment)
end
yield("*/")
end
end
yield("enum " .. enumType .. " " .. prefix .. "_" .. to_underscorecase(flag.name):upper() .. " = " .. value .. ";" .. comments)
local name = convName(toCamelCase(flag.name))
yield("\t" .. name .. string.rep(" ", maxLen+2 - name:len()) .. "= " .. value .. "," .. comments)
local intlName = toIntlEn(flag.name)
if intlName ~= nil then
intlName = convName(toCamelCase(intlName))
yield("\t" .. intlName .. string.rep(" ", maxLen+2 - intlName:len()) .. "= " .. name .. ",")
end
end
if typ.shift then
local name = prefix .. "_SHIFT"
local name = convName("shift")
local value = typ.shift
local comments = ""
if typ.desc then
comments = string.format(" ///%s bit shift", typ.desc)
end
yield("enum " .. enumType .. " " .. name .. " = " .. value .. ";" .. comments)
yield("\t" .. name .. string.rep(" ", maxLen+2 - name:len()) .. "= " .. value .. "," .. comments)
end
if typ.range then
local name = prefix .. "_MASK"
local value = string.format(format, typ.mask)
local name = convName("mask")
local value = hexStr(typ.mask, typ.bits)
local comments = ""
if typ.desc then
comments = string.format(" ///%s bit mask", typ.desc)
end
yield("enum " .. enumType .. " " .. name .. " = " .. value .. ";" .. comments)
yield("\t" .. name .. string.rep(" ", maxLen+2 - name:len()) .. "= " .. value .. "," .. comments)
end
yield("}")
local intlName = toIntlEn(typeName)
if intlName ~= nil then
yield("alias " .. intlName .. " = " .. typeName .. ";")
end
if typ.helper then
yield(string.format(
"%s %s (%s v) { return (v << %s) & %s; }",
"%s_ to%s(%s v){ return (v << %s) & %s; }",
typeName,
typeName,
enumType,
prefix,
enumType,
(prefix .. "_SHIFT"),
(prefix .. "_MASK")))
(typeName .. ".shift"),
(typeName .. ".mask")))
if intlName ~= nil then
yield("alias to" .. intlName .. " = to" .. typeName .. ";")
end
end
elseif typ.struct ~= nil then
yield("struct " .. typ.cname)
yield("{")
local st = {comments = {}, fields = {}, fns = {}, subs = {}}
if typ.comments ~= nil then
if #typ.comments == 1 then
table.insert(st.comments, "///" .. typ.comments[1])
else
table.insert(st.comments, "/**")
for _, comment in ipairs(typ.comments) do
table.insert(st.comments, comment)
end
table.insert(st.comments, "*/")
end
end
for _, member in ipairs(typ.struct) do
local comments = ""
@ -351,33 +756,45 @@ function converter.types(typ)
if #member.comment == 1 then
comments = " ///" .. member.comment[1]
else
yield("\n\t/**")
if #st.fields > 0 then
table.insert(st.fields, "\t")
end
table.insert(st.fields, "\t/**")
for _, comment in ipairs(member.comment) do
yield("\t * " .. comment)
table.insert(st.fields, "\t" .. comment)
end
yield("\t */")
table.insert(st.fields, "\t*/")
end
end
yield("\t" .. convert_struct_member(member) .. ";" .. comments)
table.insert(st.fields, "\t" .. convStructMember(member) .. ";" .. comments)
end
yield("}")
if typ.ctor ~= nil and typ.name ~= "PlatformData" then
table.insert(st.fns, "[q{void}, q{this}, q{}, `C++`],")
end
if typ.namespace ~= nil then
if allStructs[typ.namespace] ~= nil then
allStructs[typ.namespace].subs[typ.name] = st
else
allStructs[typ.namespace] = {subs = {[typ.name] = st}}
end
else
if allStructs[typ.name] ~= nil then
st.subs = allStructs[typ.name].subs
end
allStructs[typ.name] = st
end
end
end
function converter.funcs_static(func)
return converter.funcs(func, true)
end
function converter.funcs_dynamic(func)
return converter.funcs(func, false)
end
function converter.funcs(func, static)
if func.cpponly then
function converter.funcs(func)
if func.class == nil and func.conly == nil then
local extern = "C++, \"bgfx\""
local attribs = ""
if func.cfunc ~= nil and func.name ~= "init" then --what the is "cfunc" even meant to mean?
return
end
if func.comments ~= nil then
yield("/**")
for _, line in ipairs(func.comments) do
@ -396,15 +813,15 @@ function converter.funcs(func, static)
end
if hasParamsComments then
yield(" * Params:")
yield("Params:")
end
for _, arg in ipairs(func.args) do
if arg.comment ~= nil then
yield(" * " .. convert_name(arg.name) .. " = " .. arg.comment[1])
yield("\t" .. convName(arg.name:sub(2)) .. " = " .. arg.comment[1])
for i, comment in ipairs(arg.comment) do
if (i > 1) then
yield(" * " .. comment)
if i > 1 then
yield(comment)
end
end
end
@ -414,18 +831,23 @@ function converter.funcs(func, static)
end
local args = {}
if func.this ~= nil then
args[1] = convert_type(func.this_type) .. " _this"
end
for _, arg in ipairs(func.args) do
table.insert(args, convert_type(arg) .. " " .. convert_name(arg.name))
local def = ""
if arg.default ~= nil then
def = string.format("=%s", convVal(arg.default, convFnArgType(arg)))
end
if arg.fulltype == "..." then
table.insert(args, "..." .. def)
else
table.insert(args, convFnArgType(arg) .. " " .. convName(arg.name:sub(2)) .. def)
end
end
if static then
yield(convert_ret_type(func.ret) .. " bgfx_" .. func.cname .. "(" .. table.concat(args, ", ") .. ");")
else
yield("alias da_bgfx_" .. func.cname .. " = " .. convert_ret_type(func.ret) .. " function(" .. table.concat(args, ", ") .. ");")
yield("da_bgfx_" .. func.cname .. " bgfx_" .. func.cname .. ";")
if attribs ~= "" then
attribs = ", q{" .. attribs .. "}"
end
yield(string.format("[q{%s}, q{%s}, q{%s}, `%s`%s],", convType(func.ret), func.name, table.concat(args, ", "), extern, attribs))
end
end
@ -441,8 +863,7 @@ end
if (...) == nil then
-- run `lua bindings-d.lua` in command line
print(gen.gen_types())
print(gen.gen_funcs())
print(gen.gen(dTemplate))
end
return gen

View File

@ -79,8 +79,8 @@ newaction {
csgen.write(csgen.gen_dllname(), "../bindings/cs/bgfx_dllname.cs")
local dgen = require "bindings-d"
dgen.write(dgen.gen_types(), "../bindings/d/types.d")
dgen.write(dgen.gen_funcs(), "../bindings/d/funcs.d")
dgen.write(dgen.gen(), "../bindings/d/package.d")
dgen.write(dgen.fakeEnumFile, "../bindings/d/fakeenum.d")
local csgen = require "bindings-bf"
csgen.write(csgen.gen(), "../bindings/bf/bgfx.bf")