C#和C/C++混合编程系列3-绑定自动生成代码

梦想游戏人
目录:
C#

在C++导出native code绑定到C#时,大量代码是可以进行自动生成的。

这里 生成工具是利用C#和反射RTTI信息来生成。通过一些标签来告知生成器。

需要吧自动生成的cs代码的 InternalCall 进行打标签。

自动生成的cpp文件。

BuildTool.cs

/*
* Author:  caoshanshan
* Email:   me@dreamyouxi.com

*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.IO;
using System.Reflection;

using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;


namespace StickEngine.Build
{
    [System.AttributeUsage(AttributeTargets.All)]
    public class NativeClassAttribute : System.Attribute
    {
        public string class_name;

        public NativeClassAttribute(string class_name)
        {
            this.class_name = class_name;
        }
    }
    [System.AttributeUsage(AttributeTargets.All)]
    public class NativePropertiesAttribute : System.Attribute
    {
        public enum MethodType
        {
            getter_setter = 0,
        }

        public string cpp_set_method_name;
        public string cpp_get_method_name;
        public int gen_type = (int)MethodType.getter_setter;

        public NativePropertiesAttribute(int gen_type, string cpp_set_method_name, string cpp_get_method_name)
        {
            this.gen_type = gen_type;
            this.cpp_set_method_name = cpp_set_method_name;
            this.cpp_get_method_name = cpp_get_method_name;
        }
    }




    //自动生成 绑定脚本
    public static class BindingsFileAutoGenerator
    {

    }

    public static class BuildEntry
    {

        public static string GetTypeCode(Type cls, PropertyInfo pro, NativePropertiesAttribute attr, ref string _add_call)
        {
            //    Debug.Log(pro.GetGetMethod().Name);
            //getter
            if (pro.GetGetMethod().Name.IndexOf("get_") >= 0)
            {
                string return_type_name = "Vector3f";

                var returntype = pro.GetGetMethod().ReturnType;
                if (returntype == typeof(Vector3))
                {
                    return_type_name = "Vector3f";
                }
                else if (returntype == typeof(Quaternion))
                {
                    return_type_name = "Quaternionf";
                }

                var text_get =
@"
inline void NATIVE_CLASS_NAME_internal_IMPL_METHOD_NAME(MonoObject*  _this, RETURN_TYPE_NAME *ptr)
{
    auto * obj = NativePtrCast<NATIVE_CLASS_NAME>(_this);
    if (obj)
    {
        *ptr = obj->NATIVE_CPP_METHOD();
    }
}
";
                text_get = text_get.Replace("NATIVE_CPP_METHOD", attr.cpp_get_method_name);
                text_get = text_get.Replace("NATIVE_CLASS_NAME", cls.Name);
                text_get = text_get.Replace("IMPL_METHOD_NAME", pro.GetGetMethod().Name);
                text_get = text_get.Replace("RETURN_TYPE_NAME", return_type_name);


                var text_set =
@"
inline void NATIVE_CLASS_NAME_internal_IMPL_METHOD_NAME(MonoObject*  _this, RETURN_TYPE_NAME *ptr)
{
    auto * obj = NativePtrCast<NATIVE_CLASS_NAME>(_this);
    if (obj)
    {
        obj->NATIVE_CPP_METHOD(*ptr);
    }
}
";
                text_set = text_set.Replace("NATIVE_CPP_METHOD", attr.cpp_set_method_name);
                text_set = text_set.Replace("NATIVE_CLASS_NAME", cls.Name);
                text_set = text_set.Replace("IMPL_METHOD_NAME", pro.GetGetMethod().Name.Replace("get_", "set_"));
                text_set = text_set.Replace("RETURN_TYPE_NAME", return_type_name);

                //	mono_add_internal_call("StickEngine.Transform::internal_get_position", &internal_get_position);

                _add_call = string.Format("    mono_add_internal_call(\"{0}:internal_{1}\", &{2}_internal_{1});", cls.FullName, pro.GetGetMethod().Name, cls.Name);

                _add_call += "\n";

                _add_call += string.Format("    mono_add_internal_call(\"{0}::internal_{1}\", &{2}_internal_{1});\n", cls.FullName,
                    pro.GetGetMethod().Name.Replace("get_", "set_"), cls.Name);

                //     Debug.Log(_add_call);


                return text_get + text_set;
            }
            return "";
        }

        public static void Gen()
        {
            System.Console.WriteLine("StickEngine.BuildTool gen bindings files BEGIN");
            var assembly = StickEngine.CppEntry.CurrentAssembly;
            StringBuilder output = new StringBuilder();
            {
                output.Append("#include\"auto_gen_bindings.h\"\n");
                output.Append("//this file was auto generate by BuildTool.cs do not modify\n");
                output.Append("//this file manual.");
            }
            string code_2 = "";//mono_add_xxxx

            foreach (var cls in assembly.GetTypes())
            {
                if (cls.IsDefined(typeof(NativeClassAttribute), false))
                {
                    NativeClassAttribute cls_attr = null;
                    foreach (var p in cls.GetCustomAttributes(false))
                    {
                        if (p.GetType() == typeof(NativeClassAttribute))
                        {
                            cls_attr = (NativeClassAttribute)p;
                            break;
                        }
                    }
                    if (cls_attr == null) continue;
                    Debug.Log("#Scanning:" + cls);
                    string code_1 = "";//function
                    foreach (var pro in cls.GetProperties())
                    {
                        {
                            NativePropertiesAttribute method_attr = null;
                            foreach (var p in pro.GetCustomAttributes(false))
                            {
                                if (p.GetType() == typeof(NativePropertiesAttribute))
                                {
                                    method_attr = (NativePropertiesAttribute)p;
                                    break;
                                }
                            }
                            if (method_attr == null) continue;

                            if (method_attr.gen_type == (int)NativePropertiesAttribute.MethodType.getter_setter)
                            {
                                string oil = "";
                                code_1 += GetTypeCode(cls, pro, method_attr, ref oil);
                                code_2 += oil;
                            }
                        }
                    }
                    output.Append(code_1);
                }
            }
            {
                output.Append("\n\nvoid AutoGenBindings::Bind()\n");
                output.Append("{\n");

                output.Append(code_2);
                output.Append("}\n");
            }
            File.WriteAllText("../src/stick_engine/mono/auto_gen_bindings.cpp", output.ToString(), Encoding.UTF8);

            System.Console.WriteLine("StickEngine.BuildTool gen bindings files DONE");
            System.Console.ReadKey();
        }
    }
}

Scroll Up