as_scriptobject.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632
  1. /*
  2. AngelCode Scripting Library
  3. Copyright (c) 2003-2012 Andreas Jonsson
  4. This software is provided 'as-is', without any express or implied
  5. warranty. In no event will the authors be held liable for any
  6. damages arising from the use of this software.
  7. Permission is granted to anyone to use this software for any
  8. purpose, including commercial applications, and to alter it and
  9. redistribute it freely, subject to the following restrictions:
  10. 1. The origin of this software must not be misrepresented; you
  11. must not claim that you wrote the original software. If you use
  12. this software in a product, an acknowledgment in the product
  13. documentation would be appreciated but is not required.
  14. 2. Altered source versions must be plainly marked as such, and
  15. must not be misrepresented as being the original software.
  16. 3. This notice may not be removed or altered from any source
  17. distribution.
  18. The original version of this library can be located at:
  19. http://www.angelcode.com/angelscript/
  20. Andreas Jonsson
  21. [email protected]
  22. */
  23. // Modified by Lasse Öörni for Urho3D
  24. #include <new>
  25. #include "as_config.h"
  26. #include "as_scriptengine.h"
  27. #include "as_scriptobject.h"
  28. BEGIN_AS_NAMESPACE
  29. // This helper function will call the default factory, that is a script function
  30. asIScriptObject *ScriptObjectFactory(const asCObjectType *objType, asCScriptEngine *engine)
  31. {
  32. asIScriptContext *ctx = 0;
  33. int r = 0;
  34. bool isNested = false;
  35. // TODO: optimize: There should be a pool for the context so it doesn't
  36. // have to be allocated just for creating the script object
  37. // TODO: It must be possible for the application to debug the creation of the object too
  38. // Use nested call in the context if there is an active context
  39. ctx = asGetActiveContext();
  40. if( ctx )
  41. {
  42. r = ctx->PushState();
  43. // It may not always be possible to reuse the current context,
  44. // in which case we'll have to create a new one any way.
  45. if( r == asSUCCESS )
  46. isNested = true;
  47. else
  48. ctx = 0;
  49. }
  50. if( ctx == 0 )
  51. {
  52. r = engine->CreateContext(&ctx, true);
  53. if( r < 0 )
  54. return 0;
  55. }
  56. r = ctx->Prepare(engine->scriptFunctions[objType->beh.factory]);
  57. if( r < 0 )
  58. {
  59. if( isNested )
  60. ctx->PopState();
  61. else
  62. ctx->Release();
  63. return 0;
  64. }
  65. for(;;)
  66. {
  67. r = ctx->Execute();
  68. // We can't allow this execution to be suspended
  69. // so resume the execution immediately
  70. if( r != asEXECUTION_SUSPENDED )
  71. break;
  72. }
  73. if( r != asEXECUTION_FINISHED )
  74. {
  75. if( isNested )
  76. ctx->PopState();
  77. else
  78. ctx->Release();
  79. return 0;
  80. }
  81. asIScriptObject *ptr = (asIScriptObject*)ctx->GetReturnAddress();
  82. // Increase the reference, because the context will release its pointer
  83. ptr->AddRef();
  84. if( isNested )
  85. ctx->PopState();
  86. else
  87. ctx->Release();
  88. return ptr;
  89. }
  90. #ifdef AS_MAX_PORTABILITY
  91. static void ScriptObject_AddRef_Generic(asIScriptGeneric *gen)
  92. {
  93. asCScriptObject *self = (asCScriptObject*)gen->GetObject();
  94. self->AddRef();
  95. }
  96. static void ScriptObject_Release_Generic(asIScriptGeneric *gen)
  97. {
  98. asCScriptObject *self = (asCScriptObject*)gen->GetObject();
  99. self->Release();
  100. }
  101. static void ScriptObject_GetRefCount_Generic(asIScriptGeneric *gen)
  102. {
  103. asCScriptObject *self = (asCScriptObject*)gen->GetObject();
  104. *(int*)gen->GetAddressOfReturnLocation() = self->GetRefCount();
  105. }
  106. static void ScriptObject_SetFlag_Generic(asIScriptGeneric *gen)
  107. {
  108. asCScriptObject *self = (asCScriptObject*)gen->GetObject();
  109. self->SetFlag();
  110. }
  111. static void ScriptObject_GetFlag_Generic(asIScriptGeneric *gen)
  112. {
  113. asCScriptObject *self = (asCScriptObject*)gen->GetObject();
  114. *(bool*)gen->GetAddressOfReturnLocation() = self->GetFlag();
  115. }
  116. static void ScriptObject_EnumReferences_Generic(asIScriptGeneric *gen)
  117. {
  118. asCScriptObject *self = (asCScriptObject*)gen->GetObject();
  119. asIScriptEngine *engine = *(asIScriptEngine**)gen->GetAddressOfArg(0);
  120. self->EnumReferences(engine);
  121. }
  122. static void ScriptObject_ReleaseAllHandles_Generic(asIScriptGeneric *gen)
  123. {
  124. asCScriptObject *self = (asCScriptObject*)gen->GetObject();
  125. asIScriptEngine *engine = *(asIScriptEngine**)gen->GetAddressOfArg(0);
  126. self->ReleaseAllHandles(engine);
  127. }
  128. #endif
  129. void RegisterScriptObject(asCScriptEngine *engine)
  130. {
  131. // Register the default script class behaviours
  132. int r = 0;
  133. UNUSED_VAR(r); // It is only used in debug mode
  134. engine->scriptTypeBehaviours.engine = engine;
  135. engine->scriptTypeBehaviours.flags = asOBJ_SCRIPT_OBJECT | asOBJ_REF | asOBJ_GC;
  136. engine->scriptTypeBehaviours.name = "_builtin_object_";
  137. #ifndef AS_MAX_PORTABILITY
  138. r = engine->RegisterBehaviourToObjectType(&engine->scriptTypeBehaviours, asBEHAVE_CONSTRUCT, "void f(int&in)", asFUNCTION(ScriptObject_Construct), asCALL_CDECL_OBJLAST); asASSERT( r >= 0 );
  139. r = engine->RegisterBehaviourToObjectType(&engine->scriptTypeBehaviours, asBEHAVE_ADDREF, "void f()", asMETHOD(asCScriptObject,AddRef), asCALL_THISCALL); asASSERT( r >= 0 );
  140. r = engine->RegisterBehaviourToObjectType(&engine->scriptTypeBehaviours, asBEHAVE_RELEASE, "void f()", asMETHOD(asCScriptObject,Release), asCALL_THISCALL); asASSERT( r >= 0 );
  141. r = engine->RegisterMethodToObjectType(&engine->scriptTypeBehaviours, "int &opAssign(int &in)", asFUNCTION(ScriptObject_Assignment), asCALL_CDECL_OBJLAST); asASSERT( r >= 0 );
  142. // Register GC behaviours
  143. r = engine->RegisterBehaviourToObjectType(&engine->scriptTypeBehaviours, asBEHAVE_GETREFCOUNT, "int f()", asMETHOD(asCScriptObject,GetRefCount), asCALL_THISCALL); asASSERT( r >= 0 );
  144. r = engine->RegisterBehaviourToObjectType(&engine->scriptTypeBehaviours, asBEHAVE_SETGCFLAG, "void f()", asMETHOD(asCScriptObject,SetFlag), asCALL_THISCALL); asASSERT( r >= 0 );
  145. r = engine->RegisterBehaviourToObjectType(&engine->scriptTypeBehaviours, asBEHAVE_GETGCFLAG, "bool f()", asMETHOD(asCScriptObject,GetFlag), asCALL_THISCALL); asASSERT( r >= 0 );
  146. r = engine->RegisterBehaviourToObjectType(&engine->scriptTypeBehaviours, asBEHAVE_ENUMREFS, "void f(int&in)", asMETHOD(asCScriptObject,EnumReferences), asCALL_THISCALL); asASSERT( r >= 0 );
  147. r = engine->RegisterBehaviourToObjectType(&engine->scriptTypeBehaviours, asBEHAVE_RELEASEREFS, "void f(int&in)", asMETHOD(asCScriptObject,ReleaseAllHandles), asCALL_THISCALL); asASSERT( r >= 0 );
  148. #else
  149. r = engine->RegisterBehaviourToObjectType(&engine->scriptTypeBehaviours, asBEHAVE_CONSTRUCT, "void f(int&in)", asFUNCTION(ScriptObject_Construct_Generic), asCALL_GENERIC); asASSERT( r >= 0 );
  150. r = engine->RegisterBehaviourToObjectType(&engine->scriptTypeBehaviours, asBEHAVE_ADDREF, "void f()", asFUNCTION(ScriptObject_AddRef_Generic), asCALL_GENERIC); asASSERT( r >= 0 );
  151. r = engine->RegisterBehaviourToObjectType(&engine->scriptTypeBehaviours, asBEHAVE_RELEASE, "void f()", asFUNCTION(ScriptObject_Release_Generic), asCALL_GENERIC); asASSERT( r >= 0 );
  152. r = engine->RegisterMethodToObjectType(&engine->scriptTypeBehaviours, "int &opAssign(int &in)", asFUNCTION(ScriptObject_Assignment_Generic), asCALL_GENERIC); asASSERT( r >= 0 );
  153. // Register GC behaviours
  154. r = engine->RegisterBehaviourToObjectType(&engine->scriptTypeBehaviours, asBEHAVE_GETREFCOUNT, "int f()", asFUNCTION(ScriptObject_GetRefCount_Generic), asCALL_GENERIC); asASSERT( r >= 0 );
  155. r = engine->RegisterBehaviourToObjectType(&engine->scriptTypeBehaviours, asBEHAVE_SETGCFLAG, "void f()", asFUNCTION(ScriptObject_SetFlag_Generic), asCALL_GENERIC); asASSERT( r >= 0 );
  156. r = engine->RegisterBehaviourToObjectType(&engine->scriptTypeBehaviours, asBEHAVE_GETGCFLAG, "bool f()", asFUNCTION(ScriptObject_GetFlag_Generic), asCALL_GENERIC); asASSERT( r >= 0 );
  157. r = engine->RegisterBehaviourToObjectType(&engine->scriptTypeBehaviours, asBEHAVE_ENUMREFS, "void f(int&in)", asFUNCTION(ScriptObject_EnumReferences_Generic), asCALL_GENERIC); asASSERT( r >= 0 );
  158. r = engine->RegisterBehaviourToObjectType(&engine->scriptTypeBehaviours, asBEHAVE_RELEASEREFS, "void f(int&in)", asFUNCTION(ScriptObject_ReleaseAllHandles_Generic), asCALL_GENERIC); asASSERT( r >= 0 );
  159. #endif
  160. }
  161. void ScriptObject_Construct_Generic(asIScriptGeneric *gen)
  162. {
  163. asCObjectType *objType = *(asCObjectType**)gen->GetAddressOfArg(0);
  164. asCScriptObject *self = (asCScriptObject*)gen->GetObject();
  165. ScriptObject_Construct(objType, self);
  166. }
  167. void ScriptObject_Construct(asCObjectType *objType, asCScriptObject *self)
  168. {
  169. new(self) asCScriptObject(objType);
  170. }
  171. void ScriptObject_ConstructUnitialized(asCObjectType *objType, asCScriptObject *self)
  172. {
  173. new(self) asCScriptObject(objType, false);
  174. }
  175. asCScriptObject::asCScriptObject(asCObjectType *ot, bool doInitialize)
  176. {
  177. refCount.set(1);
  178. objType = ot;
  179. objType->AddRef();
  180. isDestructCalled = false;
  181. // Notify the garbage collector of this object
  182. if( objType->flags & asOBJ_GC )
  183. objType->engine->gc.AddScriptObjectToGC(this, objType);
  184. // Construct all properties
  185. asCScriptEngine *engine = objType->engine;
  186. for( asUINT n = 0; n < objType->properties.GetLength(); n++ )
  187. {
  188. asCObjectProperty *prop = objType->properties[n];
  189. if( prop->type.IsObject() )
  190. {
  191. asPWORD *ptr = (asPWORD*)(((char*)this) + prop->byteOffset);
  192. if( prop->type.IsObjectHandle() )
  193. *ptr = 0;
  194. else
  195. {
  196. // Allocate the object and call it's constructor
  197. *ptr = (asPWORD)AllocateObject(prop->type.GetObjectType(), engine, doInitialize);
  198. }
  199. }
  200. }
  201. // Urho3D: initialize userdata
  202. userData = 0;
  203. }
  204. void asCScriptObject::Destruct()
  205. {
  206. // Call the destructor, which will also call the GCObject's destructor
  207. this->~asCScriptObject();
  208. // Free the memory
  209. userFree(this);
  210. }
  211. asCScriptObject::~asCScriptObject()
  212. {
  213. objType->Release();
  214. // The engine pointer should be available from the objectType
  215. asCScriptEngine *engine = objType->engine;
  216. // Destroy all properties
  217. for( asUINT n = 0; n < objType->properties.GetLength(); n++ )
  218. {
  219. asCObjectProperty *prop = objType->properties[n];
  220. if( prop->type.IsObject() )
  221. {
  222. // Destroy the object
  223. void **ptr = (void**)(((char*)this) + prop->byteOffset);
  224. if( *ptr )
  225. {
  226. FreeObject(*ptr, prop->type.GetObjectType(), engine);
  227. *(asDWORD*)ptr = 0;
  228. }
  229. }
  230. }
  231. }
  232. asIScriptEngine *asCScriptObject::GetEngine() const
  233. {
  234. return objType->engine;
  235. }
  236. int asCScriptObject::AddRef() const
  237. {
  238. // Increase counter and clear flag set by GC
  239. gcFlag = false;
  240. return refCount.atomicInc();
  241. }
  242. int asCScriptObject::Release() const
  243. {
  244. // Clear the flag set by the GC
  245. gcFlag = false;
  246. // Call the script destructor behaviour if the reference counter is 1.
  247. if( refCount.get() == 1 && !isDestructCalled )
  248. {
  249. // This cast is OK since we are the last reference
  250. const_cast<asCScriptObject*>(this)->CallDestructor();
  251. }
  252. // Now do the actual releasing
  253. int r = refCount.atomicDec();
  254. if( r == 0 )
  255. {
  256. // This cast is OK since we are the last reference
  257. const_cast<asCScriptObject*>(this)->Destruct();
  258. return 0;
  259. }
  260. return r;
  261. }
  262. void asCScriptObject::CallDestructor()
  263. {
  264. asIScriptContext *ctx = 0;
  265. bool isNested = false;
  266. // Make sure the destructor is called once only, even if the
  267. // reference count is increased and then decreased again
  268. isDestructCalled = true;
  269. // Call the destructor for this class and all the super classes
  270. asCObjectType *ot = objType;
  271. while( ot )
  272. {
  273. int funcIndex = ot->beh.destruct;
  274. if( funcIndex )
  275. {
  276. if( ctx == 0 )
  277. {
  278. // Check for active context first as it is quicker
  279. // to reuse than to set up a new one.
  280. ctx = asGetActiveContext();
  281. if( ctx )
  282. {
  283. int r = ctx->PushState();
  284. if( r == asSUCCESS )
  285. isNested = true;
  286. else
  287. ctx = 0;
  288. }
  289. if( ctx == 0 )
  290. {
  291. // Setup a context for calling the default constructor
  292. asCScriptEngine *engine = objType->engine;
  293. int r = engine->CreateContext(&ctx, true);
  294. if( r < 0 ) return;
  295. }
  296. }
  297. int r = ctx->Prepare(objType->engine->scriptFunctions[funcIndex]);
  298. if( r >= 0 )
  299. {
  300. ctx->SetObject(this);
  301. for(;;)
  302. {
  303. r = ctx->Execute();
  304. // If the script tries to suspend itself just restart it
  305. if( r != asEXECUTION_SUSPENDED )
  306. break;
  307. }
  308. // There's not much to do if the execution doesn't
  309. // finish, so we just ignore the result
  310. }
  311. }
  312. ot = ot->derivedFrom;
  313. }
  314. if( ctx )
  315. {
  316. if( isNested )
  317. ctx->PopState();
  318. else
  319. ctx->Release();
  320. }
  321. }
  322. asIObjectType *asCScriptObject::GetObjectType() const
  323. {
  324. return objType;
  325. }
  326. int asCScriptObject::GetRefCount()
  327. {
  328. return refCount.get();
  329. }
  330. void asCScriptObject::SetFlag()
  331. {
  332. gcFlag = true;
  333. }
  334. bool asCScriptObject::GetFlag()
  335. {
  336. return gcFlag;
  337. }
  338. // interface
  339. int asCScriptObject::GetTypeId() const
  340. {
  341. asCDataType dt = asCDataType::CreateObject(objType, false);
  342. return objType->engine->GetTypeIdFromDataType(dt);
  343. }
  344. // interface
  345. void *asCScriptObject::SetUserData(void *data)
  346. {
  347. void *oldData = userData;
  348. userData = data;
  349. return oldData;
  350. }
  351. // interface
  352. void *asCScriptObject::GetUserData() const
  353. {
  354. return userData;
  355. }
  356. asUINT asCScriptObject::GetPropertyCount() const
  357. {
  358. return asUINT(objType->properties.GetLength());
  359. }
  360. int asCScriptObject::GetPropertyTypeId(asUINT prop) const
  361. {
  362. if( prop >= objType->properties.GetLength() )
  363. return asINVALID_ARG;
  364. return objType->engine->GetTypeIdFromDataType(objType->properties[prop]->type);
  365. }
  366. const char *asCScriptObject::GetPropertyName(asUINT prop) const
  367. {
  368. if( prop >= objType->properties.GetLength() )
  369. return 0;
  370. return objType->properties[prop]->name.AddressOf();
  371. }
  372. void *asCScriptObject::GetAddressOfProperty(asUINT prop)
  373. {
  374. if( prop >= objType->properties.GetLength() )
  375. return 0;
  376. // Objects are stored by reference, so this must be dereferenced
  377. asCDataType *dt = &objType->properties[prop]->type;
  378. if( dt->IsObject() && !dt->IsObjectHandle() )
  379. return *(void**)(((char*)this) + objType->properties[prop]->byteOffset);
  380. return (void*)(((char*)this) + objType->properties[prop]->byteOffset);
  381. }
  382. void asCScriptObject::EnumReferences(asIScriptEngine *engine)
  383. {
  384. // We'll notify the GC of all object handles that we're holding
  385. for( asUINT n = 0; n < objType->properties.GetLength(); n++ )
  386. {
  387. asCObjectProperty *prop = objType->properties[n];
  388. if( prop->type.IsObject() )
  389. {
  390. void *ptr = *(void**)(((char*)this) + prop->byteOffset);
  391. if( ptr )
  392. ((asCScriptEngine*)engine)->GCEnumCallback(ptr);
  393. }
  394. }
  395. }
  396. void asCScriptObject::ReleaseAllHandles(asIScriptEngine *engine)
  397. {
  398. for( asUINT n = 0; n < objType->properties.GetLength(); n++ )
  399. {
  400. asCObjectProperty *prop = objType->properties[n];
  401. if( prop->type.IsObject() && prop->type.IsObjectHandle() )
  402. {
  403. void **ptr = (void**)(((char*)this) + prop->byteOffset);
  404. if( *ptr )
  405. {
  406. asASSERT( (prop->type.GetObjectType()->flags & asOBJ_NOCOUNT) || prop->type.GetBehaviour()->release );
  407. if( prop->type.GetBehaviour()->release )
  408. ((asCScriptEngine*)engine)->CallObjectMethod(*ptr, prop->type.GetBehaviour()->release);
  409. *ptr = 0;
  410. }
  411. }
  412. }
  413. }
  414. void ScriptObject_Assignment_Generic(asIScriptGeneric *gen)
  415. {
  416. asCScriptObject *other = *(asCScriptObject**)gen->GetAddressOfArg(0);
  417. asCScriptObject *self = (asCScriptObject*)gen->GetObject();
  418. *self = *other;
  419. *(asCScriptObject**)gen->GetAddressOfReturnLocation() = self;
  420. }
  421. asCScriptObject &ScriptObject_Assignment(asCScriptObject *other, asCScriptObject *self)
  422. {
  423. return (*self = *other);
  424. }
  425. asCScriptObject &asCScriptObject::operator=(const asCScriptObject &other)
  426. {
  427. if( &other != this )
  428. {
  429. asASSERT( other.objType->DerivesFrom(objType) );
  430. asCScriptEngine *engine = objType->engine;
  431. // Copy all properties
  432. for( asUINT n = 0; n < objType->properties.GetLength(); n++ )
  433. {
  434. asCObjectProperty *prop = objType->properties[n];
  435. if( prop->type.IsObject() )
  436. {
  437. void **dst = (void**)(((char*)this) + prop->byteOffset);
  438. void **src = (void**)(((char*)&other) + prop->byteOffset);
  439. if( !prop->type.IsObjectHandle() )
  440. CopyObject(*src, *dst, prop->type.GetObjectType(), engine);
  441. else
  442. CopyHandle((asPWORD*)src, (asPWORD*)dst, prop->type.GetObjectType(), engine);
  443. }
  444. else
  445. {
  446. void *dst = ((char*)this) + prop->byteOffset;
  447. void *src = ((char*)&other) + prop->byteOffset;
  448. memcpy(dst, src, prop->type.GetSizeInMemoryBytes());
  449. }
  450. }
  451. }
  452. return *this;
  453. }
  454. int asCScriptObject::CopyFrom(asIScriptObject *other)
  455. {
  456. if( other == 0 ) return asINVALID_ARG;
  457. if( GetTypeId() != other->GetTypeId() )
  458. return asINVALID_TYPE;
  459. *this = *(asCScriptObject*)other;
  460. return 0;
  461. }
  462. void *asCScriptObject::AllocateObject(asCObjectType *objType, asCScriptEngine *engine, bool doInitialize)
  463. {
  464. void *ptr = 0;
  465. if( objType->flags & asOBJ_SCRIPT_OBJECT )
  466. {
  467. if( doInitialize )
  468. ptr = ScriptObjectFactory(objType, engine);
  469. else
  470. {
  471. ptr = engine->CallAlloc(objType);
  472. ScriptObject_ConstructUnitialized(objType, reinterpret_cast<asCScriptObject*>(ptr));
  473. }
  474. }
  475. else if( objType->flags & asOBJ_TEMPLATE )
  476. {
  477. // Templates store the original factory that takes the object
  478. // type as a hidden parameter in the construct behaviour
  479. ptr = engine->CallGlobalFunctionRetPtr(objType->beh.construct, objType);
  480. }
  481. else if( objType->flags & asOBJ_REF )
  482. {
  483. ptr = engine->CallGlobalFunctionRetPtr(objType->beh.factory);
  484. }
  485. else
  486. {
  487. ptr = engine->CallAlloc(objType);
  488. int funcIndex = objType->beh.construct;
  489. if( funcIndex )
  490. engine->CallObjectMethod(ptr, funcIndex);
  491. }
  492. return ptr;
  493. }
  494. void asCScriptObject::FreeObject(void *ptr, asCObjectType *objType, asCScriptEngine *engine)
  495. {
  496. if( objType->flags & asOBJ_REF )
  497. {
  498. asASSERT( (objType->flags & asOBJ_NOCOUNT) || objType->beh.release );
  499. if( objType->beh.release )
  500. engine->CallObjectMethod(ptr, objType->beh.release);
  501. }
  502. else
  503. {
  504. if( objType->beh.destruct )
  505. engine->CallObjectMethod(ptr, objType->beh.destruct);
  506. engine->CallFree(ptr);
  507. }
  508. }
  509. void asCScriptObject::CopyObject(void *src, void *dst, asCObjectType *objType, asCScriptEngine *engine)
  510. {
  511. // TODO: If the object doesn't have the copy behaviour, and it is not a
  512. // POD object then the copy must not be performed
  513. int funcIndex = objType->beh.copy;
  514. if( funcIndex )
  515. engine->CallObjectMethod(dst, src, funcIndex);
  516. else
  517. memcpy(dst, src, objType->size);
  518. }
  519. void asCScriptObject::CopyHandle(asPWORD *src, asPWORD *dst, asCObjectType *objType, asCScriptEngine *engine)
  520. {
  521. if( *dst )
  522. engine->CallObjectMethod(*(void**)dst, objType->beh.release);
  523. *dst = *src;
  524. if( *dst )
  525. engine->CallObjectMethod(*(void**)dst, objType->beh.addref);
  526. }
  527. END_AS_NAMESPACE