前段时间用vala开发了一个很小的程序,体验了一把vala的使用,网上关于vala的文章比较少,所以写一篇博客,如果你有相同的使用经验可以交流下.

  根据百度百科的解释,vala是一种新的、为GNOME开发者提供的具有现代化编程语言功能的一种编程语言。Vala是一种和C#极度类似的语言。

  众所周知,C是一门古老而落后的语言,虽然由于历史原因,大量的操作系统底层仍然在使用C(毕竟最早写底层的那批人早就退休甚至不在人世了,谁又愿意没事找事去重构呢.不过,还别说,Google就在干这种事,开发全新的操作系统),但并不适用于大型项目和协作开发.尽管Linux的作者Linus极度憎恨C++这样的面向对象的语言,并拒绝C++在Linux内核的使用.但是,Linux的其它开发者也心知肚明,C并不是一切,并且在Linux的各个方面大量使用C++和面向对象的开发模式.知名的KDE桌面就是基于QT来构建的,而QT是对C++的一个扩展,Linux上的大部分可用的应用都是基于QT来构建的,而另一个桌面环境Gnome则使用了GTK绑定,同时也大量使用了面向对象的特性和组件,比如Gobject,Vala.Vala的一个重要使用场景就是Gnome环境的GUI开发.

  Vala语言的主要特点:支持lambda表达式;支持对象反射与内省;使用引用计数进行内存管理,计数嵌入在对象内;使用Glib和Gobject的主循环、事件回调系统。

安装

  在Ubuntu/Debian下安装很简单,使用命令sudo apt-get install valac,测试valac编译器的版本号,可以输入valac –version命令。 我现在使用的是0.36版本,最新版本应该是0.40 Beta.

HelloWorld程序

class Demo.HelloWorld : GLib.Object {
	public static int main(string[] args)
	{
		stdout.printf("Hello, World\n");
		return 0;
	}
}

其实在Vala里,类并不是必须的.类名和文件名并不需要一致,并且一个类里允许多个类.

编译运行

编译这个程序使用命令valac hello.vala,编译成功之后生成hello这个可执行程序,运行这个程序,输入结果为: Hello, World

Vala一个比较有趣的地方就是可以直接从Vala源码编译成C源码,比如上面的代码可以使用如下的命令编译成C源码

valac -C ./hello.vala

生成的C源码如下:

/* hello.c generated by valac 0.36.5, the Vala compiler
 * generated from hello.vala, do not modify */


#include <glib.h>
#include <glib-object.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>


#define DEMO_TYPE_HELLO_WORLD (demo_hello_world_get_type ())
#define DEMO_HELLO_WORLD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DEMO_TYPE_HELLO_WORLD, DemoHelloWorld))
#define DEMO_HELLO_WORLD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DEMO_TYPE_HELLO_WORLD, DemoHelloWorldClass))
#define DEMO_IS_HELLO_WORLD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DEMO_TYPE_HELLO_WORLD))
#define DEMO_IS_HELLO_WORLD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DEMO_TYPE_HELLO_WORLD))
#define DEMO_HELLO_WORLD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DEMO_TYPE_HELLO_WORLD, DemoHelloWorldClass))

typedef struct _DemoHelloWorld DemoHelloWorld;
typedef struct _DemoHelloWorldClass DemoHelloWorldClass;
typedef struct _DemoHelloWorldPrivate DemoHelloWorldPrivate;

struct _DemoHelloWorld {
	GObject parent_instance;
	DemoHelloWorldPrivate * priv;
};

struct _DemoHelloWorldClass {
	GObjectClass parent_class;
};


static gpointer demo_hello_world_parent_class = NULL;

GType demo_hello_world_get_type (void) G_GNUC_CONST;
enum  {
	DEMO_HELLO_WORLD_DUMMY_PROPERTY
};
gint demo_hello_world_main (gchar** args, int args_length1);
DemoHelloWorld* demo_hello_world_new (void);
DemoHelloWorld* demo_hello_world_construct (GType object_type);


gint demo_hello_world_main (gchar** args, int args_length1) {
	gint result = 0;
	FILE* _tmp0_;
	_tmp0_ = stdout;
	fprintf (_tmp0_, "Hello, World\n");
	result = 0;
	return result;
}


int main (int argc, char ** argv) {
#if !GLIB_CHECK_VERSION (2,35,0)
	g_type_init ();
#endif
	return demo_hello_world_main (argv, argc);
}


DemoHelloWorld* demo_hello_world_construct (GType object_type) {
	DemoHelloWorld * self = NULL;
	self = (DemoHelloWorld*) g_object_new (object_type, NULL);
	return self;
}


DemoHelloWorld* demo_hello_world_new (void) {
	return demo_hello_world_construct (DEMO_TYPE_HELLO_WORLD);
}


static void demo_hello_world_class_init (DemoHelloWorldClass * klass) {
	demo_hello_world_parent_class = g_type_class_peek_parent (klass);
}


static void demo_hello_world_instance_init (DemoHelloWorld * self) {
}


GType demo_hello_world_get_type (void) {
	static volatile gsize demo_hello_world_type_id__volatile = 0;
	if (g_once_init_enter (&demo_hello_world_type_id__volatile)) {
		static const GTypeInfo g_define_type_info = { sizeof (DemoHelloWorldClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) demo_hello_world_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (DemoHelloWorld), 0, (GInstanceInitFunc) demo_hello_world_instance_init, NULL };
		GType demo_hello_world_type_id;
		demo_hello_world_type_id = g_type_register_static (G_TYPE_OBJECT, "DemoHelloWorld", &g_define_type_info, 0);
		g_once_init_leave (&demo_hello_world_type_id__volatile, demo_hello_world_type_id);
	}
	return demo_hello_world_type_id__volatile;
}

  可以看出 vala实际是把vala源码编译成GObject的语法,并且加入了很多语法糖.由于vala的这个特性,从而也决定了vala是一种性能比较高的语言.既能获得面向对象的便利,又能获得接近于C语言的性能.

  vala可以大量使用glib的库,具有比较强的表现力和较高的开发效率.然而由于其定位的问题,不能在服务端市场分得一杯羹,导致发展极为有限,可惜了这门在我看来,在Linux上开发体验仅次于C++和Java的语言.如果你接触过C++ 17 以上标准的C++,你就会感觉到C++的表现能力和开发效率,已经是一门比较现代化的语言了,并不会比脚本语言低多少.