ruby 代码
- #!/bin/ruby
- require 'rexml/document'
- #TODO:
- # * 调用约定
- # * union
- # # 冲突关键字检查
- puts "c2d.rb 0.002 - A C to D Converter"
- puts "Written by Wei Li
gmail.com>" - puts "License: GPL"
- CFile = "hdr.c" #需要转换的 .h 或 .c 文件
- XmlFile = (CFile.map { |fn| fn += ".xml" }).to_s
- DVersion2 = false
- Cmd= "gccxml --gccxml-compiler \"gcc\" --gccxml-cxxflags \"-x c\" #{CFile} -fxml=#{XmlFile}"
- puts Cmd
- system Cmd
- puts "GCCXML 转换完成"
- class Generator
- def initialize(xml_file, writer)
- @writer = writer
- puts "正在加载 XML 文档"
- @xmlroot = REXML::Document.new(File.open(xml_file)).elements["GCC_XML"].elements
- builitin_ele = @xmlroot["File[contains(@name, 'gccxml_builtins.h')]"].attributes["id"]
- #去掉 GCCXML 内置的东西
- @xmlroot.delete_all "*[@file='#{builitin_ele}']"
- puts "完成"
- end
- def generate_linkage
- "extern(C)"
- end
- def generate_fundamental_type(type_ele)
- case type_ele.attributes["name"]
- when "short int" : "short"
- when "short unsigned int" : "ushort"
- when "int" : "int"
- when "long int" : "int"
- when "unsigned int" : "uint"
- when "long unsigned int" : "int"
- when "long long int" : "long"
- when "long long unsigned int" : "ulong"
- when "float" : "float"
- when "double" : "double"
- when "char" : "char"
- when "unsigned char" : "ubyte"
- when "signed char" : "byte"
- when "void" : "void"
- when "wchar_t" : if type_ele.attributes["size"] == "32" then "dchar" else "wchar" end
- when "signed wchar_t" : if type_ele.attributes["size"] == "32" then "int" else "short" end
- when "unsigned wchar_t" : if type_ele.attributes["size"] == "32" then "uint" else "ushort" end
- end
- end
- def generate_type(type_id)
- ele = @xmlroot["*[@id='#{type_id}']"]
- case ele.name
- when "FundamentalType" :
- generate_fundamental_type ele
- when "Struct"
- @xmlroot["*[@id='#{type_id}']"].attributes["name"]
- when "Typedef"
- @xmlroot["*[@id='#{type_id}']"].attributes["name"]
- when "FunctionType"
- generate_function_type(ele)
- #下面都是间接类型
- when "ArrayType"
- size = ele.attributes["max"].to_i - ele.attributes["min"].to_i + 1
- indirect_type = ele.attributes["type"]
- generate_type(indirect_type) + "[#{size}]"
- when "PointerType"
- indirect_type = ele.attributes["type"]
- #函数指针需要特殊处理
- if @xmlroot["*[@id='#{indirect_type}']"].name == "FunctionType"
- generate_type(indirect_type)
- else generate_type(indirect_type) + "*" end
- when "CvQualifiedType"
- indirect_type = ele.attributes["type"]
- if @xmlroot["*[@id='#{indirect_type}']"].name == "FundamentalType"
- "const " + generate_type(indirect_type)
- else
- if DVersion2 : "const(" + generate_type(indirect_type) + ")"
- else generate_type(indirect_type) end
- end
- end
- end
- def generate_parameters(funcEle)
- params = []
- funcEle.elements.each("Argument") { |arg|
- type_id = arg.attributes["type"]
- type = generate_type(type_id)
- name = arg.attributes["name"]
- params << if name : "#{type} #{name}" else "#{type}" end
- }
- if params.length == 1 then return params[0]
- else
- return params.join(", ")
- end
- end
- def generate_function_decl(e)
- return_type = generate_type(e.attributes["returns"])
- function_name = e.attributes["name"]
- parameters = generate_parameters(e)
- return "#{return_type} #{function_name}(#{parameters});\n"
- end
- def generate_function_type(e)
- return_type = generate_type(e.attributes["returns"])
- parameters = generate_parameters(e)
- return "#{return_type} function(#{parameters})"
- end
- def generate_fields(members)
- dcode = ""
- field_ids = []
- @xmlroot.each("Field") { |f| field_ids << f.attributes["id"] }
- members.each { |mid|
- if field_ids.include? mid then
- fe = @xmlroot["*[@id='#{mid}']"]
- type = generate_type(fe.attributes["type"])
- name = fe.attributes["name"]
- dcode << "\t#{type} #{name};\n"
- end
- }
- return dcode
- end
- def generate_struct(struct_ele)
- struct_name = struct_ele.attributes["name"]
- dcode = "\nstruct #{struct_name}\n"
- dcode << "{\n"
- dcode << generate_fields(struct_ele.attributes["members"].split(" ") )
- dcode << "};\n\n"
- return dcode
- end
- def generate_typedef_decl(typedef_ele)
- typedef_name = typedef_ele.attributes["name"]
- type = generate_type(typedef_ele.attributes["type"])
- dcode = "alias #{type} #{typedef_name};\n"
- return dcode
- end
- def generate_variable(var_ele)
- var_name = var_ele.attributes["name"]
- type = generate_type(var_ele.attributes["type"])
- init = var_ele.attributes["init"]
- dcode = "#{type} #{var_name}"
- if var_ele.attributes["extern"] then dcode = "extern #{dcode}" end
- if init then dcode = "#{dcode} = #{init}" end
- dcode = "#{dcode};\n"
- end
- def generate_enum(enum_ele)
- dcode = "enum " << enum_ele.attributes["name"] << " : int \n"
- dcode << "{\n"
- members = []
- enum_ele.elements.each("EnumValue") { |ev|
- evname = ev.attributes["name"]
- init = ev.attributes["init"]
- members << "\t#{evname} = #{init}"
- }
- if members.length <= 1
- dcode << members[0]
- else
- dcode << members.join(",\n")
- end
- dcode << "\n}\n"
- end
- def parse_node(node)
- @writer << case node.name
- when "Enumeration" : generate_enum node
- when "Function" : generate_function_decl node
- when "Struct" : generate_struct node
- when "Typedef" : generate_typedef_decl node
- when "Variable" : generate_variable node
- else ""
- end
- end
- def parse_all_nodes
- @xmlroot.each { |node|
- parse_node node
- }
- end
- end #end of class Generator
- dcode = ""
- gen = Generator.new( XmlFile, dcode)
- gen.parse_all_nodes
- puts dcode
我测试用的C语言头文件 hdr.c:
C代码
- #define DEFINE_CONST 123
- void foobar(double* x);
- double varD;
- unsigned long varL;
- wchar_t wc;
- struct Foo
- {
- int x;
- double y;
- long long z;
- };
- typedef Foo* FooPtr;
- typedef const Foo* ConstFooPtr;
- FooPtr myptr;
- Foo print(int x);
- Foo* print2(unsigned x, wchar_t y, long long z);
- Foo* print3(short x);
- Foo* print4(unsigned char x);
- void print5(unsigned x[]);
- void print6(FooPtr fp);
- void print7(const char* text);
- void print8(char** ppText);
- extern Foo g_foo;
- extern Foo g_foo10[10];
- extern int* g_pint20[20];
- static Foo s_foo;
- extern const double PI = 3.1415926;
- extern const char* TestString = "Hello";
- typedef void(*MyFuncPtr)(int x, long y, double z);
- enum MyEnum
- {
- Enum1 = 1,
- Enum2 = 2
- };
输出:
- c2d.rb 0.002 - A C to D Converter
- Written by Wei Li <oldrev<at>gmail.com>
- License: GPL
- gccxml --gccxml-compiler "gcc" --gccxml-cxxflags "-x c" hdr.c -fxml=hdr.c.xml
- GCCXML 转换完成
- 正在加载 XML 文档
- 完成
- enum MyEnum : int
- {
- Enum1 = 1,
- Enum2 = 2
- }
- alias void function(int, int, double) MyFuncPtr;
- const char* TestString = "Hello";
- const double PI = 3.14159260000000006840537025709636509418487548828e+0;
- Foo s_foo;
- extern int*[20] g_pint20;
- extern Foo[10] g_foo10;
- extern Foo g_foo;
- void print8(char** ppText);
- void print7(const char* text);
- void print6(FooPtr fp);
- void print5(uint* x);
- Foo* print4(ubyte x);
- Foo* print3(short x);
- Foo* print2(uint x, dchar y, long z);
- Foo print(int x);
- FooPtr myptr;
- alias Foo* ConstFooPtr;
- alias Foo* FooPtr;
- struct Foo
- {
- int x;
- double y;
- long z;
- };
- dchar wc;
- int varL;
- double varD;
- void foobar(double* x);
Requirements
- Ruby1.8: 废话
- GCCXML: Linux 直接使用包管理系统安装,Windows 可到 www.gccxml.org 下载安装程序
Have fun!