首页
社区
课程
招聘
[原创]ChaiScript 体验手册
发表于: 2009-8-3 18:46 12639

[原创]ChaiScript 体验手册

2009-8-3 18:46
12639

序言

    好长时间以来,一直都想在网上找一个C风格并且可以与C/C++配合良好的脚本语言。可是无奈,用过很多的脚本,lua,Python、 ruby等等,但总是感觉让我不是很满意(自己水平差,没办法),除了LUA一直在使用以外,其它脚本都是一看就放弃了。
       
    越来越感觉用lua不顺手,它的书写风格让我感觉不舒服,可是,功夫不负有心人,7月底的时候,让我找到了ChaiScript,简单的看了介绍就赶紧的用了下试试……

    由于本人菜鸟,有点发现总是不敢独享,于是鉴于chaiScript没有现成的使用文档,所以就写了这个破烂文章,仅为帮助像我一样菜的朋友,故高手略过……

    本人也只是简单的测试和使用了一下,因此很多的东西摸得不是很透,所以,倘若我写的内容有错误或者理解不多的地方,还请各位朋友帮忙指正,以免误人子弟。

帖一下要写的东西的目录吧。

dir /W/S/B *vc80*.lib,*vc80*.dll >liblist
if exist lib (echo exist lib fold) else (mkdir lib)
for /f %%x in (liblist) do @copy "%%x" lib\
del /s/q *.obj
#include <iostream>
#include <string> 
#include <boost/algorithm/string.hpp> 
#include <boost/algorithm/string_regex.hpp>

using namespace std; 
using namespace boost;

int main() 
{   
	string s = "    Hello boost!! ";     trim(s);    
	cout << s << endl; 
	getchar();  

	std::string regstr = "a+"; 
	boost::regex expression(regstr);  
	std::string testString = "aaa";

	// 匹配至少一个a    
	if( boost::regex_match(testString, expression) )     
	{ 
		std::cout<< "Match" << std::endl;   
	}
	else
	{ 
		std::cout<< "Not Match" << std::endl;    
	}
}
var i = 2
if (i < 2)
{
	print("less than 2")
}
else if (i == 2) 
{
	print("equal to 2")
}
else
{
	print("more than 2")
}
for (var i = 0; i < 10; ++i) 
{
	print("i: " + i.to_string())
}
var i = 0
while (i < 10) 
{
	print("i: " + i.to_string())
	++i
}
var x = [1, 2, 3]
print(x[1])
var x = ["bob":1, "fred":2]
print(x["fred"])
var x = [1..10]
print(x)
def add_elems(x, y) 
{
	x + y
}
var add_elems = fun(x, y) { x + y }
print(add_elems(5, 10))
def five() 
{
	return 5
}
print(five())
def five() 
{
	5 
}
print(five())
5.to_string()
to_string(5)
def print_num(x) : x == 0 || x > 1
{
	print(x.to_string() + " units")
}

def print_num(x) : x == 1 
{
	print(x.to_string() + " unit")
}

print_num(2)
print_num(1)
print_num(0)
// TestExample.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>

#include <chaiscript/chaiscript.hpp>
#include <chaiscript/dispatchkit/function_call.hpp>
#include <boost/function.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/regex.hpp>

void log(const std::string &msg)
{
	std::cout << "[" << boost::posix_time::microsec_clock::local_time() << "] " << msg << std::endl;
}

void log(const std::string &module, const std::string &msg)
{
	std::cout << "[" << boost::posix_time::microsec_clock::local_time() << "] <" << module << "> " << msg << std::endl;
}

struct System
{
	std::map<std::string, boost::function<std::string (const std::string &) > > m_callbacks;

	void add_callback(const std::string &t_name, 
		const chaiscript::Proxy_Function &t_func)
	{
		m_callbacks[t_name] = chaiscript::functor<std::string (const std::string &)>(t_func);
	}

	void do_callbacks(const std::string &inp)
	{
		log("Running Callbacks: " + inp);
		for (std::map<std::string, boost::function<std::string (const std::string &)> >::iterator itr = m_callbacks.begin();
			itr != m_callbacks.end();
			++itr)
		{
			log("Callback: " + itr->first, itr->second(inp));
		}
	}
};

int _tmain(int argc, _TCHAR* argv[])
{
	using namespace chaiscript;

	ChaiScript chai;

	//创建一个新的system 对象
	System system;
	//把它添加到chaiscript引擎中
	chai.add(var(&system), "system");

	//注册System结构体的两个方法.
	chai.add(fun(&System::add_callback), "add_callback");
	chai.add(fun(&System::do_callbacks), "do_callbacks");

	// 让我们用chaiscript给我们的system结构添加一个新的回调函数。
	// 在Chaiscript中创建函数"{ 'Callback1' + x }" 并通过我们C++程序System结构中的add_callback函数
	// 将这个chaiscript脚本函数转换到boost::function,
	// so it can be handled and called easily and type-safely
	chai.eval("system.add_callback(\"#1\", fun(x) { \"Callback1 \" + x });");

	// 由于我们在chaiscript引擎中共享了“system”对象
	// 所以我们可以同时在C++代码中和Chaiscript脚本中使用这个对像
	system.do_callbacks("TestString");
	chai.eval("system.do_callbacks(\"TestString\");");

	// 日志函数被(log)重载过了, 因此我们必须得同时C++编译器,我们要注册那个版本的日志函数。
	// 这样,唯一的一个方法就是用typedef创建一个函数指针,然后注册这个函数指针就可以了
	typedef void (*PlainLog)(const std::string &);
	typedef void (*ModuleLog)(const std::string &, const std::string &);
	chai.add(fun(PlainLog(&log)), "log");
	chai.add(fun(ModuleLog(&log)), "log");

	chai.eval("log(\"Test Message\")");

	// 由于eval函数重载了操作符(),因此我们可以直接使用chai关键字而省去eval方法。
	chai("log(\"Test Module\", \"Test Message\");");

	//最后, 我们可以注册任何一个boost::function 作为sys对象的函数, 按照这样来说, 
	//我们可以给system对象添加一个受限的成员函数,例如:
	chai.add(fun(boost::function<void ()>(boost::bind(&System::do_callbacks, boost::ref(system), "Bound Test"))), "do_callbacks");

	//调用限制版本的do_callbacks函数
	chai("do_callbacks()");

	boost::function<void ()> caller = chai.functor<void ()>("fun() { system.do_callbacks(\"From Functor\"); }");
	caller();


	//如果我们想从所有的调用中得到一个类型安全的返回值,那我们可以使用eval的模板,如下:
	int i = chai.eval<int>("5+5");
	std::cout << "5+5: " << i << std::endl;

	//添加一个新的变量
	chai("var scripti = 15");

	//我们甚至可以操作system的变量
	int &scripti = chai.eval<int &>("scripti");

	std::cout << "scripti: " << scripti << std::endl;
	scripti *= 2;
	std::cout << "scripti (updated): " << scripti << std::endl;
	chai("print(\"Scripti from chai: \" + to_string(scripti))");

	//要做到: 在需要时添加一个直接处理Boxed_Values 的实例。

	//在堆栈上创建和使用函数
	int x = chai.functor<int (int, int)>("fun (x, y) { return x + y; }")(5, 6);

	log("Functor test output", boost::lexical_cast<std::string>(x));


	//在需要的时候,可以创建自己的容器. 目前可以支持大多数的std::vector 和std::map 
	chai.add(bootstrap::vector_type<std::vector<int> >("IntVector"));

	return 0;
}
using namespace chaiscript;
ChaiScript chai;
chaiscript::ChaiScript chai; 
//添加一个新的变量
	chai("var scripti = 15");

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 7
支持
分享
最新回复 (9)
雪    币: 193
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
这玩意看起来还不是很成熟啊,用一下Angel Script吧
http://www.angelcode.com/angelscript/
2009-8-3 19:06
0
雪    币: 178
活跃值: (10)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
3
纯友情支持一下
2009-8-3 21:17
0
雪    币: 1844
活跃值: (35)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
4
顶一下,没用过
2009-8-3 21:56
0
雪    币: 334
活跃值: (22)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
5
帅,都很帅....
非常支持开源的..
2009-8-3 22:01
0
雪    币: 260
活跃值: (102)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
6
好像不错!
不过就是太庞大了,需要boost支持应该比较大吧?
Lua挺好的,Lua的好就在于它实在是太小巧了!
2009-8-3 23:03
0
雪    币: 242
活跃值: (14)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
7
我想要的嵌入脚本特性:
1)完全的线程安全和可控。PYTHON不符合,LUA不错。
2)速度快。虽然说脚本速度跟写脚本人有关,不过还是不能跟蜗牛一样。
3)字符串操作简便,支持集合操作。PYTHON不错,LUA逊色点
4)标准C完成。C++实现的解释器不方便推广使用。LUA如果能把那些可恶的setjmp用返回值换掉,应该就比较完美了;现在就不敢在在内核程序里面用。PYTHON忽略
5)可以较方便跟宿主语言交互,包括函数调用、变量访问。

其他:如果能的话,当然希望仿C的语法;如果能支持OO并且粘合时较为方便从宿主获得这些继承,当然最好。

不知道这个脚本对这些特性的支持如何
2009-8-4 16:36
0
雪    币: 204
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
看起来很不错啊. 谢谢 lz 推荐.
2009-8-5 00:29
0
雪    币: 210
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
请教lz。

为什么我在C++把脚本中的函数转化为boost::function的时候functor中抛出这样的异常:chaiscript::bad_boxed_cast。

代码:
boost::function<void()> invoker = c_script.functor<void()>("initialize");
2010-7-1 14:18
0
雪    币: 168
活跃值: (152)
能力值: ( LV11,RANK:180 )
在线值:
发帖
回帖
粉丝
10
抱歉,这个我也好久没用它了,忘的差不多了……,现在环境什么的都没有,无法测试……
抱歉……
2010-8-30 05:40
0
游客
登录 | 注册 方可回帖
返回
//