step1 use anglescript invoke cpp class member function

以前从未接触过脚本引擎,只是知道有vbscript和jscript其他的一概不知,由于工作需要对脚本做了一些了解,发现这个东西原来是这么的美好,我非常喜欢python,并且把它定为我以后必须掌握的一门动态语言。

最先看到的是python,后来发现他很庞大,对我的程序来说,不是很适合。然后又找到了lua,发现他非常适合我的需求,研究了一下发现他对C++的支持不是很好,于是找了几个封装类,tolua++,luaplus,luabind,等等,大概用了一下感觉不舒服,在搜寻怎么访问C++类成员函数的时候无意中发现了一个叫angelScript的脚本引擎,看了一下非常的棒,和C++的结合是无缝的,使用起来也很舒服,语法是类C/C++的,不用学习新的语法结构更是舒服。就是例子少了点,上网一通搜索也没有找到完整的例子,都是一些片段,下面我就总结一下我学习的成果,如果哪位朋友,有更好的相关的任何资料希望能够共享一下,共同进步。

关于该脚本的详细介绍还要看他的官方网站,我就不做翻译了:这是他的官方网站 http://www.angelcode.com/angelscript/  主要特点: Script language: 语法和C/C++极为相似,仅仅有很少的差异静态编译,可以注册新的类型面向对象,sandboxing Engine: Run-time compiled Step by step execution - The scripts may be executed line by line, for controlled execution and debugging. Detailed exceptions - When an exception occurs information about why and where can easily be obtained. Line interpretation - The engine can interpret separate script lines using the currently compiled script. Useful for Quake like consoles. Saving/loading byte code - The compiled bytecode can be saved and reloaded at a later time. Modular - Scripts can be compiled into modules that can be dynamically linked with each other. Concurrent scripts - Several scripts can be executed in parallel, by suspending and resuming them one by one. This allows for easy implementation of multi-tasking schemes, or even co-routines. Debugging support - The application can examine the call stack and the value of local variables while running the scripts. The line callback feature allows the application to use breakpoints, do profiling, etc.

Integration Direct access - The script engine can directly access and use registered functions, objects, and object members without the need to write proxy functions (where native calling conventions are supported). C and C++ interface - There is a flat C interface that can be used by languages that don't interact well with C++ interfaces. It is successfully being used in Delphi projects. Multithreading - The library can be used in a multithreaded environment. Memory management - Objects are reference counted for easy management of objects that pass between script and application. An iterative garbage collector is used where circular references can occur. The application can also completely control the library's memory usage.

Portability

下面是测试代码 ,仅仅是向脚本注册一个类的实例scard,然后可以在脚本里面调用他的方法。我目前就需要这些使用mfc新建一个对话框程序,然后用下面的代码替换即可

包含头文件和lib库,生成lib库的时候要注意编译条件是否和你的需求一样比如,c++/code generation/runtime library的选项要符合你要编写的程序

#include <angelscript.h> #include "scriptstring.h"

 #pragma comment(lib, "angelscriptd.lib")

 

脚本代码:

/*

	main entry for script file

*/

void main()

{

	astest();

}



void astest()

{

	//call c function

	scard.reconnect();	

}
C++测试代码:

int LoadScript(asIScriptEngine * pScriptEngine, const char *filename, const char * module);





void MessageCallback(const asSMessageInfo *msg, void *param)

{

	const char *type = "ERR ";

	if( msg->type == asMSGTYPE_WARNING ) 

		type = "WARN";

	else if( msg->type == asMSGTYPE_INFORMATION ) 

		type = "INFO";

	CStringA str;

	str.Format("%s (%d, %d) : %s : %s/n", msg->section, msg->row, msg->col, type, msg->message);

	AfxMessageBox(CString(str));

}







void CangelTestDlg::OnBnClickedOk()

{

	// TODO: Add your control notification handler code here

	

	// Create the AngelScript script engine

 	asIScriptEngine * pScriptEngine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

	if( pScriptEngine == 0 )

	{

		AfxMessageBox( _T("Failed to create Angel Script engine.") );

		return;

	}

	// Set the message callback

	pScriptEngine->SetMessageCallback(asFUNCTION(MessageCallback), NULL, asCALL_CDECL);



	// Register AngelScript Plugins

	RegisterScriptString(pScriptEngine);



	// Local function used to load a script file into memory

	// A separate function was created to unclutter this main function

	// a bit.

	if (LoadScript( pScriptEngine, "script.as","myModol" ) < 0)

	{

		pScriptEngine->Release();

		AfxMessageBox(L"Failed to load script file.");

		return;

	}



	int s = pScriptEngine->RegisterObjectType("c_scard", sizeof(c_scard), asOBJ_REF);

	if(s < 0)

		AfxMessageBox( L"register c_scard failed" );



	s = pScriptEngine->RegisterObjectBehaviour("c_scard", asBEHAVE_ADDREF, "void f()", asMETHOD(c_scard, AddRef), asCALL_THISCALL);

	if(s<0)

		AfxMessageBox( L"register behaviour ref failed" );

	s = pScriptEngine->RegisterObjectBehaviour("c_scard", asBEHAVE_RELEASE, "void f()", asMETHOD(c_scard, Release), asCALL_THISCALL);

	if(s<0)

		AfxMessageBox( L"register behaviour release failed" );



	// Register the function that the scripts will be allowed to use.

	// This also MUST be done BEFORE we build the script! Or you will get a runtime error.

	int ret = pScriptEngine->RegisterObjectMethod("c_scard", "void reconnect()", asMETHOD(c_scard,reconnect), asCALL_THISCALL); 

	//int nRet = pScriptEngine->RegisterObjectMethod("myType","void ctest()", asFUNCTION(&CangelTestDlg::c_test), asCALL_CDECL);

	if(ret < 0)

		AfxMessageBox( L"register function failed" );



	s = pScriptEngine->RegisterGlobalProperty("c_scard scard" , &m_scard);

	if(s<0)

		AfxMessageBox( L"register object failed" );



 	

	// Why do we need to build the script?

	// Scripts need to be compiled into byte code, that the virtual machine understands.

	asIScriptContext * pContext = NULL;



	ret = pScriptEngine->Build( "myModol" );

	if( ret < 0 )

	{

		printf("Failed to compile script/n");

		goto skip_return;

	}



	// Create a context that will execute the script.

	// What is a "context" you ask?  Well go read the documentation

	// for this tutorial and find out. :)

	pContext = pScriptEngine->CreateContext();

	if( pContext == 0 ) 

	{

		printf("Failed to create the context.");

		pScriptEngine->Release();

		return;

	}



	// Register Script Function

	// If we had more functions in the module (script file) then we could register those

	// as well.  Notice that our module is currently NULL which means we only have one 

	// and don't intend to name it.

	int nFunctionID = pScriptEngine->GetFunctionIDByName("myModol", "main");



	// Must "prepare" the function for execution

	// Prepare must be called to allow the context to prepare the function stack

	pContext->Prepare( nFunctionID );



	// Execute the script function

	pContext->Execute( );



skip_return:

	// Release the engine

	pScriptEngine->Release();



	// We must release the context(s) when no longer using them

	if ( pContext )

	{

		pContext->Release();

	}



	//OnOK();

}



//-----------------------------------------------------------------------------

// Name:	LoadScript()	[global function]

// Desc:	Reads a file specified by "filename" parameter and creates a new 

//			Angelscript Section with the name specified by "module" parameter.

//-----------------------------------------------------------------------------

int LoadScript(asIScriptEngine * pScriptEngine, const char *filename, const char * module)

{

	// Read the entire script file

	FILE * pFile = fopen(filename, "rb");

	if( pFile == 0 )

	{

		printf("Failed to open the script file./n");

		return -1;

	}



	// Find the length of the script file

	fseek(pFile, 0, SEEK_END);

	int len = ftell(pFile);

	fseek(pFile, 0, SEEK_SET);



	// On Win32 it is possible to do the following instead

	// int len = _filelength(_fileno(f));



	std::string code;

	code.resize(len);



	// Read length of script file

	size_t c = fread(&code[0], len, 1, pFile);

	fclose(pFile);



	if( c == 0 ) 

	{

		printf("Failed to load script file./n");

		return -1;

	}



	// Give the code to the script engine

	int nRet = pScriptEngine->AddScriptSection(module, filename, code.c_str(), len, 0);

	if( nRet < 0 ) 

	{

		printf("An error occured while adding the script section./n");

	}



	// At this point the engine has copied the code to an 

	// internal buffer so we are free to release the memory we 

	// allocated. 



	// We can also add other script sections if we would like.

	// All script sections will be compiled together as if they

	// where one large script. 



	return nRet;

}
导入脚本的C++类:
 class c_scard

 {

 public:

	 void AddRef() {refCount++;}

	 void Release() {refCount--; if( refCount == 0 ) delete this;}

	 int refCount;



 	void reconnect(){AfxMessageBox(_T("reconnect invoked by script!"));};

 protected:

 private:

 };
scriptstring是他的字符串扩展库,还有一些,用法差不多,我也没用所以就不知道了。
至于怎么让vc找到lib库,还有一些比较浅显的我就不说了,自己多看看应该能明白,如果有问题可以留言。
相关资源:
这里有两篇关于angelscript的文章,我借鉴了很多,在此表示感谢。
http://huanzizone.blog.sohu.com/81849208.html
下面是外国人写的指南,用来入门很不错。
http://www.gameengineer.net/tutorials-angelscript.html 


### 回答1: 'b'wx.invoke不是一个函数'的意思是当前代码中使用了wx.invoke这个函数,但是实际上该函数并不存在。可能是因为代码中未引用该函数所在的库或文件,或者该函数已被移除或更改了名称。需要检查代码中是否正确引用了相关库或文件,并进一步排查问题的原因。 ### 回答2: ### 回答3: wx.invoke is not a function 是常见的JavaScript错误。它通常出现在使用微信 JavaScript SDK API(如 wx.config,wx.ready等)时。 出现这个错误的原因有很多,其中最常见的是因为微信 API 没有正确加载导致的。这可能是因为微信 SDK API文件没有正确引用或者 JS文件没有被正确加载,或者是因为微信API库还没有加载完成就被调用了相应的函数。 解决这个错误的方法非常简单,一般有以下几种: 1.检查微信 API 文件是否正确引用,确保你的项目中已经正确加载了微信JavaScript API文件。如果需要,可以从微信公众平台重新获取较新的API文件。 2.确保微信API库已经成功加载。在微信SDK调用任何API之前,需要添加wx.ready API的回调函数来确保微信API库加载完成。 3.检查你的代码中是否存在语法错误,例如拼写错误、大小写错误等。这些小错误可能会使JavaScript无法识别wx.invoke函数。 总之,如果你看到wx.invoke is not a function错误,最好首先确保微信API已经正确引用并成功加载。如果这些步骤都是正确的,那么很可能是微信API文件已经过期或SDK API更新导致,在这种情况下,重新获取API文件或更新SDK API即可解决问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值