|
| 1 | +struct CProject |
| 2 | + dir::String |
| 3 | + headerbase::String |
| 4 | +end |
| 5 | + |
| 6 | +function wrapper(dest::CProject, entrypoints, typedescs) |
| 7 | + # Write the header file for C |
| 8 | + headerfile = joinpath(dest.dir, dest.headerbase * ".h") |
| 9 | + libvar = "JULIALIB_" * uppercase(dest.headerbase) * "_H" |
| 10 | + open(headerfile, "w") do f |
| 11 | + println(f, "#ifndef $libvar") |
| 12 | + println(f, "#define $libvar") |
| 13 | + println(f, "#include <stddef.h>") |
| 14 | + println(f, "#include <stdint.h>") |
| 15 | + println(f, "#include <stdbool.h>") |
| 16 | + println(f) |
| 17 | + |
| 18 | + typedict = Dict{String, String}() |
| 19 | + for type in values(typedescs) |
| 20 | + println(f, "typedef struct {") |
| 21 | + for field in type.fields |
| 22 | + ft = mangle_c!(typedict, field.type) |
| 23 | + println(f, " ", ft, " ", field.name, ";") |
| 24 | + end |
| 25 | + println(f, "} ", mangle_c!(typedict, type.name), ";") |
| 26 | + end |
| 27 | + println(f) |
| 28 | + |
| 29 | + for method in entrypoints |
| 30 | + args = join(method.args, ", ") |
| 31 | + if !isempty(args) |
| 32 | + args = ", " * args |
| 33 | + end |
| 34 | + print(f, mangle_c!(typedict, method.return_type), " ", method.name, "(") |
| 35 | + isfirst = true |
| 36 | + for arg in method.args |
| 37 | + if isfirst |
| 38 | + isfirst = false |
| 39 | + else |
| 40 | + print(f, ", ") |
| 41 | + end |
| 42 | + ft = mangle_c!(typedict, arg.type) |
| 43 | + print(f, ft, " ", arg.name) |
| 44 | + if arg.isva |
| 45 | + print(f, "...") |
| 46 | + end |
| 47 | + end |
| 48 | + print(f, ");\n") |
| 49 | + end |
| 50 | + |
| 51 | + println(f, "#endif // $libvar") |
| 52 | + end |
| 53 | +end |
| 54 | + |
| 55 | +const ctypes = Dict{String, String}( |
| 56 | + "Int8" => "int8_t", |
| 57 | + "Int16" => "int16_t", |
| 58 | + "Int32" => "int32_t", |
| 59 | + "Int64" => "int64_t", |
| 60 | + "UInt8" => "uint8_t", |
| 61 | + "UInt16" => "uint16_t", |
| 62 | + "UInt32" => "uint32_t", |
| 63 | + "UInt64" => "uint64_t", |
| 64 | + "Float32" => "float", |
| 65 | + "Float64" => "double", |
| 66 | + "Bool" => "_Bool", |
| 67 | + "Cvoid" => "void", |
| 68 | + "Cint" => "int", |
| 69 | + "Cshort" => "short", |
| 70 | + "Clong" => "long", |
| 71 | + "Cuint" => "unsigned int", |
| 72 | + "Cushort" => "unsigned short", |
| 73 | + "Culong" => "unsigned long", |
| 74 | + "Cssize_t" => "ssize_t", |
| 75 | + "Csize_t" => "size_t", |
| 76 | + "Cchar" => "char", |
| 77 | + "Cwchar_t" => "wchar_t", |
| 78 | + "Cstring" => "char *", |
| 79 | + "Cwstring" => "wchar_t *", |
| 80 | + "RawFD" => "int", |
| 81 | +) |
| 82 | + |
| 83 | +function mangle_c!(typedict::Dict{String, String}, type::AbstractString) |
| 84 | + ft = get(typedict, type, nothing) |
| 85 | + ft !== nothing && return ft |
| 86 | + ft = get(ctypes, type, nothing) |
| 87 | + ft !== nothing && return ft |
| 88 | + idxbad = findfirst(r"[^a-zA-Z0-9_\{\}]", type) |
| 89 | + if idxbad !== nothing |
| 90 | + error("Invalid type name: ", type, " (invalid character at position ", idxbad, ")") |
| 91 | + end |
| 92 | + m = match(r"^Ptr\{(.+)\}$", type) |
| 93 | + if m !== nothing |
| 94 | + inner_type = m.captures[1] |
| 95 | + result = mangle_c!(typedict, inner_type) * "*" |
| 96 | + typedict[type] = result |
| 97 | + return result |
| 98 | + end |
| 99 | + m = match(r"^(.+)\{(.+)\}$", type) |
| 100 | + if m !== nothing |
| 101 | + basename, params = m.captures |
| 102 | + params = split(params, ",") |
| 103 | + params = join(map(p -> mangle_c!(typedict, p), params), "_") |
| 104 | + result = basename * "_" * params * "_" |
| 105 | + typedict[type] = result |
| 106 | + return result |
| 107 | + end |
| 108 | + typedict[type] = type |
| 109 | + return type |
| 110 | +end |
0 commit comments