22 auto Indent(
size_t size) -> std::string {
23 std::string indent(size * 4,
' ');
39 out <<
Indent(indent) <<
"namespace " << node.
name() <<
" {\n";
43 out <<
Indent(indent) <<
"} // namespace " << node.
name() <<
'\n';
47 out <<
Indent(indent) <<
"[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit, Size=" << node.
size() <<
", Pack=" << node.
align() <<
")]\n"
48 <<
Indent(indent) <<
"public struct " << node.
name() <<
" {\n";
52 out <<
Indent(indent) <<
"}\n";
58 const auto isMemberFn = std::dynamic_pointer_cast<ObjectDecl>(node.
parent()) !=
nullptr;
64 out <<
"fixed (void* __self = &this) { ";
67 if (
const auto ret = node.
returns(); !(ret.builtin() && ret.terms()[0] ==
"void")) {
77 for (
auto i = 0; i < node.
children().size(); i++) {
87 context.
error(std::format(
"unrecognized return type of function '{}'", node.
symbol()));
98 out <<
Indent(indent) <<
"[System.Runtime.InteropServices.DllImport(\"" << gen.
LibraryName <<
"\", EntryPoint=\"" << node.
symbol() <<
"\", ExactSpelling=true)]\n"
99 <<
Indent(indent) <<
"static extern " << ret.value() <<
" __stub(";
102 out <<
"void* __self, ";
105 for (
auto i = 0; i < node.
children().size(); i++) {
110 gen.
handleParam(context, *std::dynamic_pointer_cast<ParamDecl>(node.
children()[i]), out, indent);
122 for (
const auto &item : node.
children()) {
123 if (
auto arg = std::dynamic_pointer_cast<ParamDecl>(item);
124 arg && arg->type().refs()) {
135 context.
error(std::format(
"unrecognized return type of function '{}'", node.
symbol()));
139 if (!std::dynamic_pointer_cast<ObjectDecl>(node.
parent())) {
140 context.
error(std::format(
"C# doesn't allow out-of-class functions ({})", node.
symbol()));
144 out <<
Indent(indent) <<
"public static ";
145 if (IsUnsafe(node)) {
148 out << ret.value() <<
' ' << node.
name() <<
'(';
154 out <<
Indent(indent + 1) <<
"unsafe {\n";
156 out <<
Indent(indent + 1) <<
"}\n";
157 out <<
Indent(indent) <<
"}\n";
163 context.
error(std::format(
"unrecognized builtin type '{}'", node.
returns().
terms()[0]));
167 out <<
Indent(indent) <<
"public ";
168 if (IsUnsafe(node)) {
171 out << ret.value() <<
' ' << node.
name() <<
'(';
177 context.
error(std::format(
"unrecognized builtin type '{}'", node.
type().
terms()[0]));
181 out << type.value() <<
' ' << node.
name();
const std::shared_ptr< Decl > & parent() const
const std::vector< std::shared_ptr< Decl > > & children() const
const std::string & name() const
const Type & returns() const
const std::string & symbol() const
void error(const std::string &what)
const std::string & align() const
const std::string & size() const
const Type & type() const
const std::vector< std::string > & terms() const
bool handleFunctionBegin(MLLIFContext &context, const FunctionDecl &node, std::ostream &out, std::size_t indent) override
bool handleMethodBegin(MLLIFContext &context, const MethodDecl &node, std::ostream &out, std::size_t indent) override
void writeParamDelimiter(std::ostream &os) override
bool handleObjectBegin(MLLIFContext &context, const ObjectDecl &node, std::ostream &out, std::size_t indent) override
bool handleNamespaceEnd(MLLIFContext &context, const NamespaceDecl &node, std::ostream &out, std::size_t indent) override
bool handleNamespaceBegin(MLLIFContext &context, const NamespaceDecl &node, std::ostream &out, std::size_t indent) override
bool handleAssemblyEnd(MLLIFContext &context, const AssemblyDecl &node, std::ostream &out, std::size_t indent) override
bool handleFunctionEnd(MLLIFContext &context, const FunctionDecl &node, std::ostream &out, std::size_t indent) override
bool handleAssemblyBegin(MLLIFContext &context, const AssemblyDecl &node, std::ostream &out, std::size_t indent) override
bool handleParam(MLLIFContext &context, const ParamDecl &node, std::ostream &out, std::size_t indent) override
bool handleObjectEnd(MLLIFContext &context, const ObjectDecl &node, std::ostream &out, std::size_t indent) override
CsBridgeGen(const std::string &libname)
bool createFunctionStub(CsBridgeGen &gen, MLLIFContext &context, const FunctionDecl &node, std::ostream &out, const std::size_t indent)
std::optional< std::string > TypeToCs(const Type &type)
Gets C#-compliant typename of type.
auto Indent(size_t size) -> std::string