Jump to content

  • Log In with Google      Sign In   
  • Create Account

Interested in a FREE copy of HTML5 game maker Construct 2?

We'll be giving away three Personal Edition licences in next Tuesday's GDNet Direct email newsletter!

Sign up from the right-hand sidebar on our homepage and read Tuesday's newsletter for details!


We're also offering banner ads on our site from just $5! 1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


FDsagizi

Member Since 03 Apr 2009
Offline Last Active Apr 27 2014 09:09 PM

#5024223 AngelScript SDK 2.25.2 - Bytecode load example

Posted by FDsagizi on 22 January 2013 - 02:23 AM

I use this:

 

http://www.everfall.com/paste/id.php?iore8puh6ktv




#4983923 CScriptBuilder bug

Posted by FDsagizi on 26 September 2012 - 02:43 AM

Hi Posted Image

if defined AS_PROCESS_METADATA - CScriptBuilder crash on this script code:

std::string script = "class ";


#4983515 Pod type and Null pointer exception - bug with call destructor

Posted by FDsagizi on 25 September 2012 - 04:08 AM

Hello!

I find bug Posted Image

if comment this code

// null_object.Do();

destructor call 2 times - it is ok!

but, if we have null pointer exception

destructor call 3 times and c++ crash

http://www.everfall....hp?nt1d6pbl1rkg


#4830053 Dynamic reloading script

Posted by FDsagizi on 01 July 2011 - 09:58 AM

WitchLord
Thank you very much for your help and tips!!!

I got everything done and everything works!


the same way I did it as a module (as well as all the standard examples) and would like to give you a code that you added it to AngelScript - think to many people it will be useful!



Here is the code

ScriptReloader.h
http://www.everfall....hp?55dmnkzvxuzc
ScriptReloader.cpp
http://www.everfall....hp?3m8vcr75t0ty



ScriptReloader.h



//
// CScriptReloader
//

#ifndef SCRIPTRELOADER_H
#define SCRIPTRELOADER_H

#include <angelscript.h>
#include <vector>
#include <string>

BEGIN_AS_NAMESPACE

class CScriptReloader;

struct CScriptReloaderVariable
{
	CScriptReloaderVariable(){
		init();
	}
	CScriptReloaderVariable( CScriptReloaderVariable *_parent, std::string _name,  void *_ref, int _typeId ) 
	{
		init();

		name = _name;
		reloader = _parent->reloader;
		Store( _ref, _typeId );
	}

	void init(){
		handle_ptr = restore_ptr = NULL;
		type_id = 0;
		is_init = false;
		reloader = NULL;
	}

	// need to get engine, and module
	CScriptReloader *reloader;

	//  if standard type ( int, float )...
	int type_id;

	// if its class, need save type str type - "string" "myClass" then next find by decl
	std::string type_id_str;
	
	// name variable
	std::string name;

	// is initialize
	bool is_init;

	// 'this' pointer to variable
	void *ptr;

	// where handle references
	void *handle_ptr;

	// new address object, ie address the restoration
	void *restore_ptr;

	// serialize data
	std::vector<char> mem;

	// if type == string
	std::string txt_val;

	// Child's, or if type == array, or handle data( if handle not found in global space )
	std::vector<CScriptReloaderVariable> childs;

	// save the object and its children
	void Store(void *ref, int refTypeId );

	//restore the object and its children
	void Restore(void *ref);

	// you first need to save all the objects before you can save references to objects
	void StoreHandle();

	// first restore the objects, then we have their new address, and we can restore the handle.
	void RestoreHandle(); 

	// set type to this var
	void setType(int typeId );

	// if it class, return obj type
	asIObjectType *getType();

	// Get child by name variable
	CScriptReloaderVariable *child( std::string _name )
	{
		for( size_t i =0; i < childs.size(); i++ )
			if( childs[i].name == _name )
				return &childs[i];

		return nullptr;
	}

	// get all ptrs of the child
	void  childsPtr( std::vector<void*> *_ptrs )
	{
		_ptrs->push_back( ptr );

		for( size_t i=0; i < childs.size(); ++i )
			childs[i].childsPtr( _ptrs );
	}

	// find variable by ptr
	CScriptReloaderVariable *findByPtr( void *_ptr )
	{
		if( ptr == _ptr )
			return this;

		for( size_t i =0; i < childs.size(); i++ )
		{
			CScriptReloaderVariable *find = childs[i].findByPtr(_ptr );
			if( find )
				return find;
		}

		return nullptr;
	}

	// find variable by ptr but looking only at those in the references, which will create a new object
	CScriptReloaderVariable *findByPtrInCreated( void *_ptr )
	{
		// if this handle created object
		if( type_id & asTYPEID_OBJHANDLE && childs.size() == 1 )
		{
			if( childs[0].ptr == _ptr )
				return this;
		}

		if(  !(type_id & asTYPEID_OBJHANDLE ) )
		{
			for( size_t i =0; i < childs.size(); i++ )
			{
				CScriptReloaderVariable *find = childs[i].findByPtrInCreated(_ptr );
				if( find )
					return find;
			}
		}

		return nullptr;
	}

	// may be that the two references refer to the same variable. 
	// But this variable is not available in the global list. 
	// According to this reference will be restores it. 
	// And so two links are not created 2 variables, 
	// it is necessary to cancel the creation of one of them.
	void canselDublicate( CScriptReloaderVariable *_from );
};


// This class keeps a list of variables, then restores them after the reboot script.
// But you have to be careful with the change of signature classes, or 
// changing the types of objects. You can remove or add variables, functions, 
// methods. But you can not (yet) to change the variable type. 
//
//You also need to understand that after a reboot you should get a new id 
// FUNCTIONS, or class to call them from C + + code.
class CScriptReloader
{

public:
	
	// then store all the variables
	CScriptReloaderVariable root;

	asIScriptEngine *engine;

	asIScriptModule *mod;

	// Store all global variables, and handles
	void Store()
	{
		root.reloader = this;

		// first store global variables
		for( int i =0; i < mod->GetGlobalVarCount(); i++ )
		{
			const char *name;
			int type_id;
			mod->GetGlobalVar( i, &name, &type_id );
			root.childs.push_back( CScriptReloaderVariable( &root, name,  mod->GetAddressOfGlobalVar( i ), type_id ) );
		}

		// second store handles
		root.StoreHandle();
	}

	// Retrieve all global variables after reload script.
	void Restore()
	{
		// first restore global variables
		int var_count = mod->GetGlobalVarCount();
		for( int i =0; i < var_count; i++ )
		{
			const char *name;
			mod->GetGlobalVar(i, &name );

			CScriptReloaderVariable *v = root.child( name );
			v->Restore( mod->GetAddressOfGlobalVar( i ) );
		}

		// up all handles to new ptr
		root.RestoreHandle();
	}

};


END_AS_NAMESPACE

#endif


ScriptReloader.cpp



#include "stdafx.h"
#include <assert.h>
#include <string.h> // strstr
#include <stdio.h>  // sprintf
#include "scriptreloader.h"
#include "scriptstring.h"
#include "scriptarray.h"

using namespace std;

BEGIN_AS_NAMESPACE


void CScriptReloaderVariable::Store(void *ref, int _typeId)
{
	is_init = true;
	setType( _typeId );
	ptr = ref;

	if( type_id & asTYPEID_OBJHANDLE )
	{
		handle_ptr = *(void**)ref;
	}
	else if( type_id & asTYPEID_SCRIPTOBJECT )
	{
		asIScriptObject *obj = (asIScriptObject *)ref;
		asIObjectType *type = obj->GetObjectType();
		setType(  type->GetTypeId() );

		// Store childs 
		for(int i =0; i < type->GetPropertyCount(); i++ )
		{	
			int child_id;
			const char *child_name;
			type->GetProperty( i, &child_name, &child_id );

			childs.push_back( CScriptReloaderVariable( this, child_name, obj->GetAddressOfProperty( i ), child_id ) );
		}	
	}
	else
	{
		int size = reloader->engine->GetSizeOfPrimitiveType( type_id );
		
		if( size == 0 )
		{			
			if( type_id_str== "string" )
			{
				CScriptString *txt_ref = ((CScriptString*)ref); 
				txt_val = txt_ref->buffer;
			}
			else if( type_id_str == "array" )
			{
				CScriptArray *array = (CScriptArray*)ref;

				for( int i =0; i < array->GetSize(); i++ )
					childs.push_back( CScriptReloaderVariable( this, "", array->At( i ), array->GetElementTypeId() ) );
			}
			else if( getType() )
			{
				size = getType()->GetSize();	
			}
		}

		if( size )
		{
			mem.resize( size );
			memcpy(&mem[0], ref, size);
		}
	}
}

void CScriptReloaderVariable::Restore(void *ref)
{
	if( !this || !is_init || !ref )
		return;

	restore_ptr = ref;

	if( type_id  & asTYPEID_OBJHANDLE )
	{
		// if need create objects
		if( childs.size() == 1 )
		{
			asIObjectType *type = childs[0].getType();

			void *new_obejct = reloader->engine->CreateScriptObject( type->GetTypeId() );

			childs[0].Restore( new_obejct );	
		}
	}
	else if( type_id & asTYPEID_SCRIPTOBJECT )
	{
		asIScriptObject *obj = (asIScriptObject *)ref;
		asIObjectType *type = getType();

		// Retrieve children s
		for( int i =0; i < type->GetPropertyCount() ; i++ )
		{	
			const char *name_property;
			type->GetProperty(i, &name_property );
			
			child( name_property )->Restore( obj->GetAddressOfProperty( i ) );		
		}
	}
	else
	{
		if( mem.size() )
			memcpy( ref, &mem[0], mem.size());
		else
		{
			if( type_id_str == "string" )
			{
				CScriptString *ref_txt = ((CScriptString*)ref);			
				ref_txt->buffer = txt_val;
			}
			else if( type_id_str == "array" )
			{
				CScriptArray *array = (CScriptArray*)ref;
				array->Resize( childs.size() );

				for( size_t i =0; i < childs.size(); ++i )	
					childs[i].Restore( array->At(i) );
			}
		}
	}
}

void CScriptReloaderVariable::canselDublicate( CScriptReloaderVariable *from )
{
	std::vector<void*> ptrs;
	from->childsPtr( &ptrs );

	for( size_t i=0; i < ptrs.size(); ++i )
	{
		CScriptReloaderVariable *find = reloader->root.findByPtrInCreated( ptrs[i] );

		while( find )
		{
			// cancel create object
			find->childs.clear();

			// Find next link to this ptr
			find = reloader->root.findByPtrInCreated( ptrs[i] );
		}
	}
}

void CScriptReloaderVariable::StoreHandle()
{
	// Find to 
	if( handle_ptr )
	{
		CScriptReloaderVariable *handle_to = reloader->root.findByPtr( handle_ptr );
		
		// if handle is not found in global space...
		if( handle_to == nullptr )
		{
			asIObjectType *type = getType();

			CScriptReloaderVariable need_create = CScriptReloaderVariable( this, name, handle_ptr, type->GetTypeId() ); 

			canselDublicate( &need_create );

			childs.push_back( need_create );
		}
	}
	// Childs...
	for( size_t i=0; i < childs.size(); ++i )
		childs[i].StoreHandle();
}

void CScriptReloaderVariable::RestoreHandle()
{
	CScriptReloaderVariable *handle_to = reloader->root.findByPtr( handle_ptr );

	// Restore handle!
	if( restore_ptr && handle_to && handle_to->restore_ptr )
		*(void**)restore_ptr = handle_to->restore_ptr;
	
	// Childs...
	for( size_t i=0; i < childs.size(); ++i )
		childs[i].RestoreHandle();
}


void CScriptReloaderVariable::setType(  int _typeId )
{
	type_id = _typeId;

	asIObjectType *type = reloader->engine->GetObjectTypeById( type_id  );

	if( type )
		type_id_str = type->GetName();
}

asIObjectType *CScriptReloaderVariable::getType()
{
	if( !type_id_str.empty() )
	{
		int new_type_id = reloader->mod->GetTypeIdByDecl( type_id_str.c_str() );
		return reloader->engine->GetObjectTypeById( new_type_id );
	}	

	return nullptr;
}

END_AS_NAMESPACE





If necessary, I can make an example of how to use it!
Although it's easy!

	CScriptReloader reloader;
	
	reloader.engine = engine;
	reloader.mod = mod;

	reloader.Store ();

		// Reload scripts...

	reloader.Restore ();



PARTNERS