- 浏览: 498450 次
- 性别:
- 来自: 上海
文章分类
最新评论
-
hypercube:
markin'
配置D语言编程环境 -
qiezi:
qiezi 写道yangyang_08 写道1 ...
我的编程语言学习经历 -
qiezi:
yangyang_08 写道1、现在如果做并发服务器,楼主选用 ...
我的编程语言学习经历 -
yangyang_08:
1、现在如果做并发服务器,楼主选用什么样的语言架构?2、lua ...
我的编程语言学习经历 -
dearplain:
我也是语言爱好者,不过我一直坚持使用c。
我的编程语言学习经历
Ruby语言的官方解释程序是使用C语言开发的,一般用C语言来编写扩展。D语言和C语言是二进制兼容的,所以可以使用D语言编写Ruby扩展。
一、移植C库到D的一般过程
C使用头文件来处理符号依赖,在D里面链接外部库文件时,要使用extern (C)声明来引入符号,这是一个转换过程。
如何转换一个C头文件到D文件?D文档的htomodule.html有详尽说明。一般的转换过程如下:
1、运行预处理程序处理掉头文件里面的宏。
2、删除经过预处理以后的多余信息。由于C的头文件包含,每个头文件经过预处理以后都会包含一些重复内容,我们需要剔除这部分内容,通过查找行号即可完成。
3、转换相应声明到D声明,这一步可以使用一个c2h程序来完成。
注意预处理程序处理完毕以后,宏函数以及宏定义的常量会被去除,这可能不是你想要的,所以最好的办法可能是手工转换。
另一种调用是在D里面调用动态链接库,这需要你使用implib工具从动态链接库产生一个.lib导入库文件,然后生成D声明,再编译链接即可。如果是在linux下使用共享库,则只需要编写D声明文件,然后直接链接即可。
二、调用C库
转换完毕以后,就可以调用了。如果你只是要测试一下,就可以只声明使用过的外部函数、变量即可。
例如我们要编写Programming Ruby里面的一个Ruby Extension例子,相应的D代码如下:
module test;
import ruby;
extern (C)
VALUE t_init(VALUE self)
{
VALUE arr = rb_ary_new();
rb_iv_set(self, " @arr " , arr);
return self;
}
extern (C)
VALUE t_add(VALUE self, VALUE anObject)
{
VALUE arr = rb_iv_get(self, " @arr " );
rb_ary_push(arr, anObject);
return arr;
}
extern (C){
VALUE cTest;
alias VALUE( * func_type)();
export void Init_Test()
{
cTest = rb_define_class( " Test " , rb_cObject);
rb_define_method(cTest, " initialize " , cast(func_type) & t_init, 0 );
rb_define_method(cTest, " add " , cast(func_type) & t_add, 1 );
}
} // extern(C)
和C代码很相似。由于我们只使用了几个外部函数、变量,所以只需要声明这几个符号即可:
module ruby;
extern (C){
alias ulong VALUE;
VALUE rb_cObject;
VALUE rb_ary_new ();
VALUE rb_ary_push (VALUE, VALUE);
VALUE rb_iv_set (VALUE, char * , VALUE);
VALUE rb_iv_get (VALUE, char * );
VALUE rb_define_class ( char * ,VALUE);
void rb_define_method (VALUE, char * ,VALUE( * )(), int );
}
三、生成动态链接库(Windows DLL)或共享库(Linux so文件)
D语言在Windows上编写DLL,除了要有D源文件以外,还要有DLL定义文件:
LIBRARY Test
DESCRIPTION ' Test written in D '
EXETYPE NT
CODE PRELOAD DISCARDABLE
DATA PRELOAD SINGLE
这是一个通用的格式,只是一些描述信息,因为D中可以使用export关键字导出符号,所以不需要在这里声明导出函数,只有在编写COM DLL时才会增加其它一些信息。
另外由于D语言要初始化GC以及其它一些信息,所以还需要在DllMain里面调用初始化及终止代码。由于不同平台的初始化过程不完全相同,这里我简单封闭了一下不同平台的初始化代码:
module os.library;
extern (C){
void gc_init();
void gc_term();
version(Windows) void _minit();
void _moduleCtor();
void _moduleDtor();
void _moduleUnitTests();
version(linux) void _STI_monitor_staticctor();
version(linux) void _STI_critical_init();
version(linux) void _STD_monitor_staticdtor();
version(linux) void _STD_critical_term();
}
extern (C)
void d_init()
{
// writefln("Start init D runtime");
version(linux) _STI_monitor_staticctor();
version(linux) _STI_critical_init();
gc_init();
version(Windows) _minit();
_moduleCtor();
_moduleUnitTests();
// writefln("init finished");
}
extern (C)
void d_fini()
{
// writefln("Start term D runtime");
_moduleDtor();
gc_term();
version(linux) _STD_critical_term();
version(linux) _STD_monitor_staticdtor();
// writefln("term finished");
}
现在可以为Windows编写初始化及终止代码:
module os.dll;
private import os.library;
private import std.c.windows.windows;
HINSTANCE g_hInst;
extern (Windows)
BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved)
{
switch (ulReason)
{
case DLL_PROCESS_ATTACH:
d_init();
break ;
case DLL_PROCESS_DETACH:
d_fini();
break ;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
// Multiple threads not supported yet
return false ;
}
g_hInst = hInstance;
return true ;
}
由于Linux共享库并没有标准的入口函数(或是我不知道它),这里使用gcc扩展的初始、终止代码,不过是以C语言实现的:
#include < ruby.h >
static void so_init( void ) __attribute__((constructor));
static void so_fini( void ) __attribute__((destructor));
extern void d_init( void );
extern void d_fini( void );
void so_init( void )
{
d_init();
}
void so_fini( void )
{
d_fini();
}
现在可以尝试编译链接,在Linux上编译命令如下:
gdc - o Test.so test.d os / so.o ruby.d - shared - fPIC - lruby
你可以在irb下测试:
test = Test. new
test.add( 1 )
test.add( 2 )
test.add( " a " )
可以看到add总是返回一个array,与期望结果一致。
使用gdc是因为dmd在linux上无法生成共享库。
在Windows上的编译命令如下:
ruby18.lib是使用implib从msvcrt-ruby18.dll导出的,这个编译过程很顺利,不过不幸的是它运行有一些问题,大概是一些初始值错误,我暂时还没有找到原因。或许也应该尝试一下gdc,不过我不知道如何从.DLL文件导出一个gdc支持的ELF格式的导入库文件。
四、项目打算
打算建立一个rubyd项目,除了转换ruby头文件以外,还要作一些扩展,比如转换D类到ruby类,这方面已有借鉴,比如dsource.org上的pyd项目。
由于以前在建立项目方面有过失败经历(asgard项目由于兴趣转移和其它原因比如语法丑陋等而未能进行),这次还是保守一些,先完成D声明的转换,我已经使用工具转换了所有头文件,不过正如前面所说,宏函数和宏常量都丢失了,所以需要重新手工转换。
五、其它问题
1、如何从.DLL文件导出一个gdc支持的ELF格式的导入库文件?如果你知道可以告诉我,先谢过了。
2、dmd生成可执行文件问题不大,生成动态链接库或共享库有很大缺陷,特别是不能生成共享库,我可不想再找一个只能再Windows上正常运行的编译器。如何让它改进这些方面?
3、gdc使用dmd前端和gcc后端,应该会成熟一些,不过一般会比dmd前端版本稍低,而且gdc发布版本不是很频繁,大概4-5个dmd版本才会有一个gdc版本(初略计算),所以一些新特性不能够及时加入进来。
发表评论
-
D语言模板和编译期执行
2012-07-29 00:15 0D语言模板继承了C++模板的基本用法,在其上做了相当多扩充,近 ... -
Generator
2008-04-09 13:46 2013几种并发编程模型开销(从大到小): Process > ... -
lambda之路...
2007-11-09 22:57 2868DMD最近的版本号加入了闭包,感觉非常有用,虽然有些背后动作, ... -
像Erlang一样写D程序
2007-09-15 10:23 6734琢磨了好久,一直没时间来做它。在讨论这个问题的时候就已经有这想 ... -
[D语言] qsort的尴尬
2007-05-06 21:31 5082phobos里面在stc.c.stdlib里提供了qsort, ... -
强类型数值计算
2007-04-10 21:45 4724以前曾经讨论过使用typedef来完成强类型的数值计算,最终遇 ... -
简单的单元测试框架
2007-04-10 21:20 3149做了个简单的单元测试框架,只算个毛坯,遇到一些问题。 1、由 ... -
仿STL的vector,写了一组array操作方法。
2007-04-05 23:55 12040文档从MSDN抄过来的,稍稍改了一下。 module ar ... -
编译期执行的效率
2007-03-15 15:58 4230写了一个编译期执行的fibonacci模板: templ ... -
D语言编译期生成和编译期执行技术
2007-02-24 14:35 4127借助D语言新的mixin表达式,可以完成一些代码生成功能,比如 ... -
如何获得一个方法的名字?
2007-01-15 19:24 3493在D语言中,一个方法你可以得到它的指针(函数指针或委托),但不 ... -
D语言的函数编程
2007-01-07 11:17 3865前阵子论坛上有人问我D语言做函数编程怎样,老实说我没怎么想过这 ... -
D语言和python的差异
2007-01-07 10:12 6557这2个语言的比较怪怪的,我最近转换了一些twisted的源文件 ... -
从简单测试看D数组内存分配策略
2007-01-07 09:43 3231D语言动态数组可以在运行期改变大小,这和C++的vector相 ... -
DMD 0.178发布
2006-12-24 15:32 4604What's New for D 0.178 ... -
GDC 0.20发布
2006-12-17 14:35 2803引用 * Updated to DMD 0.177 * Fix ... -
DMD 0.177发布
2006-12-09 18:47 2277没什么亮点,BUG修复得也不多,BUG数量始终保持在250-2 ... -
DMD 0.176发布
2006-12-03 14:22 3079引用 What's New for D 0.176 Dec ... -
D语言的成员函数模板
2006-12-02 20:29 3078DMD 0.166 特性列表中有一条: * ncorp ... -
D语言 在栈上分配对象 以及 无需GC拖管对象
2006-11-28 13:18 2816一、栈上分配对象 C++可以轻易实现在栈上和堆上分配对象,例 ...
相关推荐
在提供的压缩包文件中,"Premier.Press.Game.Programming.with.Python.Lua.and.Ruby.ebook-LiB.chm"很可能是一本关于使用这三种语言进行游戏编程的电子书,它可能会详细介绍如何利用这些语言来开发游戏,涵盖从基础...
标题提到的"用Python, Lua 和 Ruby语言设计游戏",这三种动态语言各自拥有独特的优点,适用于不同的游戏开发场景。接下来,我们将深入探讨每种语言在游戏开发中的应用、特点以及它们如何协同工作。 **Lua** Lua 是...
本资源主要涵盖了使用Python、Lua和Ruby这三种编程语言进行游戏设计的知识。这三种语言各有特点,适用于不同的游戏开发场景,下面将详细探讨每种语言在游戏编程中的应用及其优势。 1. Python Python是一种高级、...
3. **模板系统的扩展**:D语言在C++模板的基础上进行了大幅度的改进,提供了更加灵活和强大的模板系统,支持类型推导、模板元编程等功能。 4. **模板元编程**:D语言的模板系统支持复杂的类型推导和元编程技术,...
3. 创建一个新的D源代码文件(扩展名为.d),并使用D语言编写你的程序。 4. 使用dmd命令编译你的源代码,生成可执行文件。 5. 运行生成的可执行文件,测试你的程序。 此外,你可能还需要IDE或代码编辑器的支持,如...
然而,由于其原生解释器是用C语言编写的,它在某些场景下可能无法充分利用现代多核处理器的性能,或者无法很好地融入Java平台的生态系统。这就是JRuby的出现原因,它是一个将Ruby语言实现于Java虚拟机(JVM)上的...
《用Python,Lua和Ruby语言设计游戏-Game.Programming.with.Python.Lua.And.Ruby》这本书深入探讨了如何利用这些语言的优势来构建游戏。 Python在游戏开发中的应用主要体现在其强大的库支持和清晰的语法结构上。例如...
1. **兼容性**:D语言与C语言二进制兼容,但并不完全,这意味着可以直接使用部分C语言编写的库。 2. **编译方式**:支持编译成本地机器码,提高执行效率。 3. **内存管理**:提供垃圾回收机制的同时也支持手动管理...
为了编写和运行Ruby代码,可以使用内置的`irb`交互式环境,或者使用文本编辑器(如VSCode、Atom等)配合插件进行开发。 Ruby 3.1.1不仅适用于初学者,也是经验丰富的开发者升级现有项目的理想选择。它提供了更好的...
通过以上对Ruby编程语言的深入介绍,可以看出Ruby不仅具备简洁优雅的语法和强大的功能,而且在Web开发、脚本编写等多个领域都具有广泛的应用价值。学习和掌握Ruby,将有助于开发者在软件开发领域取得更多的成就。
为了更好地编写Ruby代码,推荐使用以下编辑器: - **Visual Studio Code**:通过安装Ruby插件来支持Ruby开发。 - **Sublime Text**:同样可以通过插件支持Ruby开发。 - **Atom**:社区活跃,插件丰富。 - **RubyMine...
- **可扩展性**:Ruby具备良好的可扩展性,适合编写大型项目并且易于维护。 - **多用途开发**:Ruby可以用于开发各种Internet和Intranet应用程序。 - **跨平台**:Ruby能够在Windows和POSIX环境中安装和运行。 - **...
D语言是一种新兴的系统编程语言,它旨在结合C语言的强大性能和脚本语言如Python或Ruby的高效开发特性。这种语言的设计目标非常明确:既要保持底层系统的高效运行能力,又要提供现代高级语言的便利性。 #### 二、...
- **调用约定**:D语言支持多种调用约定,以便与不同语言编写的库进行交互。 - **可执行文件格式**:D语言编译的程序可以直接生成Win32平台下的可执行文件。 - **DLL编程**:D语言可以用于创建DLL文件,并支持通过C...
- **游戏开发**:虽然Ruby不是专门的游戏开发语言,但通过Gosu这样的库,开发者也可以用Ruby进行2D游戏的开发。 - **工具开发**:Ruby因其强大的元编程能力和简洁的语法,非常适合用于开发各种命令行工具和实用程序...