`
oldrev
  • 浏览: 234404 次
  • 性别: Icon_minigender_1
  • 来自: 昆明
社区版块
存档分类
最新评论

简单的 C to D 转换 Ruby 脚本

阅读更多
今天晚上费了点脑筋写了一个简单的 C2D 转换脚本,大致实现了函数申明、全局变量、typedef、enum、struct 和数组的转换,但是还不支持预处理、union、调用约定等。

ruby 代码
 
  1. #!/bin/ruby  
  2. require 'rexml/document'  
  3.   
  4. #TODO:  
  5. # * 调用约定  
  6. # * union  
  7. # # 冲突关键字检查  
  8.   
  9. puts "c2d.rb 0.002 - A C to D Converter"  
  10. puts "Written by Wei Li <oldrev<at>gmail.com>"  
  11. puts "License: GPL"  
  12.   
  13. CFile = "hdr.c" #需要转换的 .h 或 .c 文件  
  14.   
  15. XmlFile = (CFile.map { |fn| fn += ".xml" }).to_s  
  16.   
  17. DVersion2 = false  
  18.   
  19. Cmd= "gccxml --gccxml-compiler \"gcc\" --gccxml-cxxflags \"-x c\" #{CFile} -fxml=#{XmlFile}"  
  20. puts Cmd  
  21. system Cmd  
  22. puts "GCCXML 转换完成"  
  23.   
  24. class Generator  
  25.   
  26.     def initialize(xml_file, writer)  
  27.         @writer = writer  
  28.         puts "正在加载 XML 文档"  
  29.         @xmlroot = REXML::Document.new(File.open(xml_file)).elements["GCC_XML"].elements  
  30.         builitin_ele = @xmlroot["File[contains(@name, 'gccxml_builtins.h')]"].attributes["id"]  
  31.   
  32.         #去掉 GCCXML 内置的东西  
  33.         @xmlroot.delete_all "*[@file='#{builitin_ele}']"  
  34.         puts "完成"  
  35.     end  
  36.   
  37.     def generate_linkage  
  38.         "extern(C)"  
  39.     end  
  40.   
  41.     def generate_fundamental_type(type_ele)  
  42.         case type_ele.attributes["name"]  
  43.         when "short int" :              "short"  
  44.         when "short unsigned int" :     "ushort"  
  45.         when "int" :                    "int"  
  46.         when "long int" :               "int"  
  47.         when "unsigned int" :           "uint"  
  48.         when "long unsigned int" :      "int"  
  49.         when "long long int" :          "long"  
  50.         when "long long unsigned int" : "ulong"  
  51.         when "float" :                  "float"  
  52.         when "double" :                 "double"  
  53.         when "char" :                   "char"  
  54.         when "unsigned char" :          "ubyte"  
  55.         when "signed char" :            "byte"  
  56.         when "void" :                   "void"  
  57.         when "wchar_t" :                if type_ele.attributes["size"] == "32" then "dchar" else "wchar" end  
  58.         when "signed wchar_t" :         if type_ele.attributes["size"] == "32" then "int" else "short" end  
  59.         when "unsigned wchar_t" :       if type_ele.attributes["size"] == "32" then "uint" else "ushort" end  
  60.         end  
  61.     end  
  62.   
  63.     def generate_type(type_id)  
  64.         ele = @xmlroot["*[@id='#{type_id}']"]  
  65.         case ele.name  
  66.   
  67.         when "FundamentalType" :  
  68.             generate_fundamental_type ele  
  69.   
  70.         when "Struct"  
  71.             @xmlroot["*[@id='#{type_id}']"].attributes["name"]  
  72.   
  73.         when "Typedef"  
  74.             @xmlroot["*[@id='#{type_id}']"].attributes["name"]  
  75.   
  76.         when "FunctionType"  
  77.             generate_function_type(ele)  
  78.   
  79.             #下面都是间接类型  
  80.         when "ArrayType"   
  81.             size = ele.attributes["max"].to_i - ele.attributes["min"].to_i + 1  
  82.             indirect_type = ele.attributes["type"]  
  83.             generate_type(indirect_type) + "[#{size}]"  
  84.   
  85.         when "PointerType"  
  86.             indirect_type = ele.attributes["type"]  
  87.             #函数指针需要特殊处理  
  88.             if @xmlroot["*[@id='#{indirect_type}']"].name == "FunctionType"   
  89.                 generate_type(indirect_type)   
  90.             else generate_type(indirect_type) + "*" end  
  91.   
  92.         when "CvQualifiedType"  
  93.             indirect_type = ele.attributes["type"]  
  94.             if @xmlroot["*[@id='#{indirect_type}']"].name == "FundamentalType"   
  95.                 "const " + generate_type(indirect_type)  
  96.             else  
  97.                 if DVersion2 : "const(" + generate_type(indirect_type) + ")"  
  98.                 else generate_type(indirect_type) end  
  99.             end  
  100.         end  
  101.     end  
  102.   
  103.     def generate_parameters(funcEle)  
  104.         params = []  
  105.         funcEle.elements.each("Argument") { |arg|   
  106.             type_id = arg.attributes["type"]  
  107.             type = generate_type(type_id)  
  108.             name = arg.attributes["name"]  
  109.             params << if name : "#{type} #{name}" else "#{type}" end  
  110.         }  
  111.         if params.length == 1 then return params[0]  
  112.         else   
  113.             return params.join(", ")  
  114.         end  
  115.     end  
  116.   
  117.     def generate_function_decl(e)  
  118.         return_type = generate_type(e.attributes["returns"])  
  119.         function_name = e.attributes["name"]  
  120.         parameters = generate_parameters(e)  
  121.         return "#{return_type} #{function_name}(#{parameters});\n"  
  122.     end  
  123.   
  124.     def generate_function_type(e)  
  125.         return_type = generate_type(e.attributes["returns"])  
  126.         parameters = generate_parameters(e)  
  127.         return "#{return_type} function(#{parameters})"  
  128.     end  
  129.   
  130.     def generate_fields(members)  
  131.         dcode = ""  
  132.         field_ids = []  
  133.         @xmlroot.each("Field") { |f| field_ids << f.attributes["id"] }  
  134.   
  135.         members.each { |mid|  
  136.             if field_ids.include? mid then  
  137.                 fe = @xmlroot["*[@id='#{mid}']"]  
  138.                 type = generate_type(fe.attributes["type"])  
  139.                 name = fe.attributes["name"]  
  140.                 dcode << "\t#{type} #{name};\n"  
  141.             end  
  142.         }  
  143.         return dcode  
  144.     end  
  145.   
  146.     def generate_struct(struct_ele)  
  147.         struct_name = struct_ele.attributes["name"]  
  148.         dcode = "\nstruct #{struct_name}\n"  
  149.         dcode << "{\n"  
  150.         dcode << generate_fields(struct_ele.attributes["members"].split(" ") )  
  151.         dcode << "};\n\n"  
  152.         return dcode   
  153.     end  
  154.   
  155.     def generate_typedef_decl(typedef_ele)  
  156.         typedef_name = typedef_ele.attributes["name"]  
  157.         type = generate_type(typedef_ele.attributes["type"])  
  158.         dcode = "alias #{type} #{typedef_name};\n"  
  159.         return dcode  
  160.     end  
  161.   
  162.     def generate_variable(var_ele)  
  163.         var_name = var_ele.attributes["name"]  
  164.         type = generate_type(var_ele.attributes["type"])  
  165.         init = var_ele.attributes["init"]  
  166.         dcode = "#{type} #{var_name}"  
  167.         if var_ele.attributes["extern"then dcode = "extern #{dcode}" end  
  168.         if init then dcode = "#{dcode} = #{init}" end  
  169.         dcode = "#{dcode};\n"  
  170.     end  
  171.   
  172.     def generate_enum(enum_ele)   
  173.         dcode = "enum " << enum_ele.attributes["name"] << " : int \n"  
  174.         dcode << "{\n"  
  175.         members = []  
  176.         enum_ele.elements.each("EnumValue") { |ev|  
  177.             evname = ev.attributes["name"]  
  178.             init = ev.attributes["init"]  
  179.             members << "\t#{evname} = #{init}"  
  180.         }  
  181.         if members.length <= 1  
  182.             dcode << members[0]  
  183.         else   
  184.             dcode << members.join(",\n")  
  185.         end  
  186.   
  187.         dcode << "\n}\n"  
  188.     end  
  189.   
  190.     def parse_node(node)  
  191.         @writer << case node.name  
  192.         when "Enumeration" : generate_enum node  
  193.         when "Function" : generate_function_decl node  
  194.         when "Struct" : generate_struct node  
  195.         when "Typedef" : generate_typedef_decl node  
  196.         when "Variable" : generate_variable node   
  197.         else ""  
  198.         end  
  199.     end  
  200.   
  201.     def parse_all_nodes  
  202.         @xmlroot.each { |node|   
  203.             parse_node node   
  204.         }  
  205.     end  
  206.   
  207. end #end of class Generator  
  208.   
  209. dcode = ""  
  210. gen = Generator.new( XmlFile, dcode)  
  211. gen.parse_all_nodes  
  212.   
  213. puts dcode  

我测试用的C语言头文件 hdr.c:
C代码
  1. #define DEFINE_CONST 123
  2. void foobar(double* x);
  3. double varD;
  4. unsigned long varL;
  5. wchar_t wc;
  6. struct Foo
  7. {
  8. int x;
  9. double y;
  10. long long z;
  11. };
  12. typedef Foo* FooPtr;
  13. typedef const Foo* ConstFooPtr;
  14. FooPtr myptr;
  15. Foo print(int x);
  16. Foo* print2(unsigned x, wchar_t y, long long z);
  17. Foo* print3(short x);
  18. Foo* print4(unsigned char x);
  19. void print5(unsigned x[]);
  20. void print6(FooPtr fp);
  21. void print7(const char* text);
  22. void print8(char** ppText);
  23. extern Foo g_foo;
  24. extern Foo g_foo10[10];
  25. extern int* g_pint20[20];
  26. static Foo s_foo;
  27. extern const double PI = 3.1415926;
  28. extern const char* TestString = "Hello";
  29. typedef void(*MyFuncPtr)(int x, long y, double z);
  30. enum MyEnum
  31. {
  32. Enum1 = 1,
  33. Enum2 = 2
  34. };

输出:
  1. c2d.rb 0.002 - A C to D Converter
  2. Written by Wei Li <oldrev<at>gmail.com>
  3. License: GPL
  4. gccxml --gccxml-compiler "gcc" --gccxml-cxxflags "-x c" hdr.c -fxml=hdr.c.xml
  5. GCCXML 转换完成
  6. 正在加载 XML 文档
  7. 完成
  8. enum MyEnum : int
  9. {
  10. Enum1 = 1,
  11. Enum2 = 2
  12. }
  13. alias void function(int, int, double) MyFuncPtr;
  14. const char* TestString = "Hello";
  15. const double PI = 3.14159260000000006840537025709636509418487548828e+0;
  16. Foo s_foo;
  17. extern int*[20] g_pint20;
  18. extern Foo[10] g_foo10;
  19. extern Foo g_foo;
  20. void print8(char** ppText);
  21. void print7(const char* text);
  22. void print6(FooPtr fp);
  23. void print5(uint* x);
  24. Foo* print4(ubyte x);
  25. Foo* print3(short x);
  26. Foo* print2(uint x, dchar y, long z);
  27. Foo print(int x);
  28. FooPtr myptr;
  29. alias Foo* ConstFooPtr;
  30. alias Foo* FooPtr;
  31. struct Foo
  32. {
  33. int x;
  34. double y;
  35. long z;
  36. };
  37. dchar wc;
  38. int varL;
  39. double varD;
  40. void foobar(double* x);

Requirements

  1. Ruby1.8: 废话
  2. GCCXML: Linux 直接使用包管理系统安装,Windows 可到 www.gccxml.org 下载安装程序

Have fun!
分享到:
评论
9 楼 oldrev 2007-11-03  
官网那个 htod 不开源,只能运行于Windows,这个Ruby程序可以作为一个补充。
8 楼 qiezi 2007-11-03  
头文件转换是比较麻烦的,工具一般不能处理宏函数,这在C里面是很普遍的。而且工具通常需要把宏展开才能得到结果,展开后宏就没剩下原来的信息了。
7 楼 oldrev 2007-11-03  
Ruby 脚本没法做成exe。
Ruby 在大多数 Linux、Mac OSX 都是系统内置的,这个脚本就是可执行文件。Windows 使用者可以自己去下载 gccxml/ruby 然后再设置路径,如果有耐心的话。
6 楼 tuja 2007-11-03  
最好做成可执行文件, 同时用ruby和D的恐怕不是很多
5 楼 oldrev 2007-11-02  
Version 0.005,能够转换 #define 定义的常量了。

下载:
http://dotmars.googlecode.com/svn/trunk/tools/htd/htd.rb
4 楼 oldrev 2007-10-30  
0.004 发布,转换功能基本可用,不支持C++,需要 GCCXML和Ruby1.8。

尚未实现的功能:
* 预处理常量和宏
* 非C调用约定
* 自动生成多模块
* 对齐
* D2

下载:
http://dotmars.googlecode.com/svn/trunk/tools/htd/htd.rb
3 楼 oldrev 2007-10-26  
目前只差宏、预处理常量和调用约定了。
2 楼 ideage 2007-10-25  
不错!支持!
1 楼 oldrev 2007-10-25  
恩,预计这个星期以内就完全可以使用了。

相关推荐

    ruby脚本交互.rar

    在"ruby脚本交互.rar"这个压缩包中,包含的可能是一份使用Ruby语言进行脚本交互的易语言源码。易语言是中国自主研发的一种简单易学的编程语言,它允许程序员用自然语言般的语法编写程序。下面我们将深入探讨Ruby脚本...

    Ruby-ngxruby是嵌入ruby脚本的Nginx模块

    Ruby-ngxruby模块是Nginx服务器中的一个扩展,它允许开发者使用Ruby语言编写服务器端逻辑,从而增强Nginx的功能。Nginx以其高性能、轻量级的特性被广泛用于处理静态内容和反向代理任务,而通过ngx_ruby模块,Nginx...

    ruby脚本编辑器.rar

    Ruby脚本编辑器是一款专为Ruby编程语言设计的文本编辑工具,它提供了丰富的特性来帮助开发者高效地编写、调试和管理Ruby代码。在易语言源码的基础上,我们可以深入理解其功能实现,学习如何构建类似的开发工具。 ...

    Ruby脚本语言经典教程.pdf

    Ruby是一种面向对象的脚本语言,由松本行弘(Yukihiro "Matz" Matsumoto)发明于1993年,并在1995年公开发布。作为一种脚本语言,Ruby主要运行在服务器端进行网页开发、系统编程、命令行工具开发等。Ruby的特点在于...

    易语言ruby脚本交互

    易语言ruby脚本交互源码,ruby脚本交互,信息框_,加载内存DLL,释放内存DLL,取DLL导出函数地址,GetIntegerAddress,GetArrayDataAddress,脚本_直接执行,脚本_定义模块,脚本_初始化,脚本_定义类,脚本_定义类方法,脚本_...

    ruby脚本转二进制可执行程序工具

    这是一个将ruby脚本转换成二进制可执行文件的工具,使用简单方便,功能强大,解压编译后生成rubyc可执行程序!转换ruby脚本时 使用rubyc 脚本.rb即可,可以自动检测依赖关系!使用非常方便!

    这是一个把ruby脚本代码转化为exe可执行文件

    这是一个把ruby脚本代码转化为exe可执行文件转化后文件有点大。ruby2.0有望改进这方面的支持

    redis集群,使用ruby脚本搭建集群

    本教程将深入探讨如何使用 Ruby 脚本搭建 Redis 集群。 首先,了解 Redis 集群的基本概念。Redis 集群是通过数据分片(Sharding)实现的,即将数据分散存储在多个节点上,每个节点负责一部分数据。这种方式能够确保...

    Ruby教程 脚本语言

    Ruby教程 - 动态脚本语言的明珠 Ruby是一种高效且灵活的面向对象编程语言,由日本的松本行弘(Yukihiro Matsumoto)于1995年创建,旨在提供一种易于理解、简洁且强类型的编程体验。它的设计理念是结合Smalltalk的...

    ruby脚本下载

    ruby脚本,用来分析case覆盖率,文件名,文件个数等等

    游戏脚本语言(ruby初步)

    Ruby是一种面向对象的脚本语言,它的设计目标是提供一种简单、易用的语言,以便开发者快速地创建程序。 Ruby的特点包括:动态类型、垃圾回收、闭包、块、Mixin等。 Ruby语言的名称来源于红宝石(Ruby),它是第四...

    建立组织机构的Ruby脚本

    测试用 建立组织机构Ruby脚本 脚本基于GEPS接口,采用Ruby脚本编写;

    易语言源码ruby脚本编辑器易语言源码.rar

    《易语言源码与Ruby脚本编辑器的深度解析》 在编程领域,源码是理解软件工作原理的钥匙,而易语言作为一款中国本土化的编程语言,以其独特的语法和简洁的界面,深受初级和中级程序员的喜爱。同样,Ruby语言以其优雅...

    Ruby脚本编程:动态语言的魅力与实用指南

    Ruby脚本是一种可以在多种操作系统上运行的脚本语言,它结合了命令式、函数式和面向对象编程的最佳特性。本文将深入探讨Ruby脚本的概念、特点,并提供实际的代码示例来展示其实用性。 Ruby脚本是一种灵活、强大且...

    易语言ruby脚本编辑器易语言源码.rar

    易语言ruby脚本编辑器易语言源码.rar 易语言ruby脚本编辑器易语言源码.rar 易语言ruby脚本编辑器易语言源码.rar 易语言ruby脚本编辑器易语言源码.rar 易语言ruby脚本编辑器易语言源码.rar 易语言ruby脚本编辑器...

    易语言源码易语言ruby脚本交互源码.rar

    此压缩包“易语言源码易语言ruby脚本交互源码.rar”显然包含了与易语言相关的代码,特别是涉及到易语言与Ruby脚本之间的交互功能。 在编程领域,不同语言之间的交互是一个常见的需求,比如利用各自语言的优势处理...

    Ruby脚本在Web开发中的多维应用与实践

    本文将深入探讨Ruby脚本在Web开发中的多样化应用,从基础的Web服务器搭建到复杂的Web应用程序开发,以及Ruby脚本在性能优化和数据库操作中的关键作用。 Ruby脚本在Web开发中的应用广泛,从快速搭建Web服务器到开发...

    Ruby脚本hackery手动修复损坏的hbase_Ruby_下载.zip

    在这个场景中,我们面临的是一个特定的问题:如何使用Ruby脚本进行“hackery”来手动修复损坏的HBase。通过分析标题和描述,我们可以推测这是一个关于使用Ruby编写脚本来解决HBase数据恢复的教程或工具包。 首先,...

    mp3-to-hls:Ruby脚本将MP3文件转换为HLS流

    Ruby脚本,用于将MP3文件转换为HLS流。 安装 将此行添加到您的应用程序的Gemfile中: gem 'mp3-to-hls' 然后执行: $ bundle 或将其自己安装为: $ gem install mp3-to-hls 用法 待办事项:在此处写下使用...

    Ruby脚本中的文件操作:深入指南与代码示例

    Ruby,作为一种灵活的脚本语言,提供了丰富的内置方法来处理文件的读写、属性修改以及其他相关的文件系统操作。本文将详细介绍如何在Ruby脚本中进行文件操作,包括文件的打开、读取、写入、关闭以及文件属性的查询等...

Global site tag (gtag.js) - Google Analytics