BsManagedSerializableArray.cpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "Serialization/BsManagedSerializableArray.h"
  4. #include "RTTI/BsManagedSerializableArrayRTTI.h"
  5. #include "BsMonoManager.h"
  6. #include "Serialization/BsScriptAssemblyManager.h"
  7. #include "Serialization/BsManagedSerializableField.h"
  8. #include "BsMonoClass.h"
  9. #include "BsMonoMethod.h"
  10. #include "BsMonoArray.h"
  11. namespace bs
  12. {
  13. ManagedSerializableArray::ManagedSerializableArray(const ConstructPrivately& dummy)
  14. {
  15. }
  16. ManagedSerializableArray::ManagedSerializableArray(const ConstructPrivately& dummy,
  17. const SPtr<ManagedSerializableTypeInfoArray>& typeInfo, MonoObject* managedInstance)
  18. : mArrayTypeInfo(typeInfo)
  19. {
  20. mGCHandle = MonoUtil::newGCHandle(managedInstance, false);
  21. ScriptArray scriptArray((MonoArray*)managedInstance);
  22. mElemSize = scriptArray.elementSize();
  23. initMonoObjects();
  24. mNumElements.resize(typeInfo->mRank);
  25. for(UINT32 i = 0; i < typeInfo->mRank; i++)
  26. mNumElements[i] = getLengthInternal(i);
  27. }
  28. ManagedSerializableArray::~ManagedSerializableArray()
  29. {
  30. if(mGCHandle != 0)
  31. {
  32. MonoUtil::freeGCHandle(mGCHandle);
  33. mGCHandle = 0;
  34. }
  35. }
  36. SPtr<ManagedSerializableArray> ManagedSerializableArray::createFromExisting(MonoObject* managedInstance,
  37. const SPtr<ManagedSerializableTypeInfoArray>& typeInfo)
  38. {
  39. if(managedInstance == nullptr)
  40. return nullptr;
  41. if(!ScriptAssemblyManager::instance().getBuiltinClasses().systemArrayClass->isInstanceOfType(managedInstance))
  42. return nullptr;
  43. return bs_shared_ptr_new<ManagedSerializableArray>(ConstructPrivately(), typeInfo, managedInstance);
  44. }
  45. SPtr<ManagedSerializableArray> ManagedSerializableArray::createNew(const SPtr<ManagedSerializableTypeInfoArray>& typeInfo, const Vector<UINT32>& sizes)
  46. {
  47. return bs_shared_ptr_new<ManagedSerializableArray>(ConstructPrivately(), typeInfo, createManagedInstance(typeInfo, sizes));
  48. }
  49. SPtr<ManagedSerializableArray> ManagedSerializableArray::createNew()
  50. {
  51. return bs_shared_ptr_new<ManagedSerializableArray>(ConstructPrivately());
  52. }
  53. MonoObject* ManagedSerializableArray::createManagedInstance(const SPtr<ManagedSerializableTypeInfoArray>& typeInfo, const Vector<UINT32>& sizes)
  54. {
  55. if (!typeInfo->isTypeLoaded())
  56. return nullptr;
  57. MonoClass* arrayClass = ScriptAssemblyManager::instance().getBuiltinClasses().systemArrayClass;
  58. MonoMethod* createInstance = arrayClass->getMethodExact("CreateInstance", "Type,int[]");
  59. ScriptArray lengthArray(MonoUtil::getINT32Class(), (UINT32)sizes.size());
  60. for (UINT32 i = 0; i < (UINT32)sizes.size(); i++)
  61. lengthArray.set(i, sizes[i]);
  62. void* params[2] = { MonoUtil::getType(typeInfo->mElementType->getMonoClass()), lengthArray.getInternal() };
  63. return createInstance->invoke(nullptr, params);
  64. }
  65. MonoObject* ManagedSerializableArray::getManagedInstance() const
  66. {
  67. if(mGCHandle != 0)
  68. return MonoUtil::getObjectFromGCHandle(mGCHandle);
  69. return nullptr;
  70. }
  71. void ManagedSerializableArray::setFieldData(UINT32 arrayIdx, const SPtr<ManagedSerializableFieldData>& val)
  72. {
  73. if (mGCHandle != 0)
  74. {
  75. MonoArray* array = (MonoArray*)MonoUtil::getObjectFromGCHandle(mGCHandle);
  76. setFieldData(array, arrayIdx, val);
  77. }
  78. else
  79. {
  80. mCachedEntries[arrayIdx] = val;
  81. }
  82. }
  83. void ManagedSerializableArray::setFieldData(MonoArray* obj, UINT32 arrayIdx, const SPtr<ManagedSerializableFieldData>& val)
  84. {
  85. if (MonoUtil::isValueType(mElementMonoClass))
  86. setValueInternal(obj, arrayIdx, val->getValue(mArrayTypeInfo->mElementType));
  87. else
  88. {
  89. MonoObject* ptrToObj = (MonoObject*)val->getValue(mArrayTypeInfo->mElementType);
  90. setValueInternal(obj, arrayIdx, &ptrToObj);
  91. }
  92. }
  93. SPtr<ManagedSerializableFieldData> ManagedSerializableArray::getFieldData(UINT32 arrayIdx)
  94. {
  95. if (mGCHandle != 0)
  96. {
  97. MonoArray* array = (MonoArray*)MonoUtil::getObjectFromGCHandle(mGCHandle);
  98. ScriptArray scriptArray(array);
  99. UINT32 numElems = scriptArray.size();
  100. assert(arrayIdx < numElems);
  101. void* arrayValue = scriptArray.getRaw(arrayIdx, mElemSize);
  102. if (MonoUtil::isValueType(mElementMonoClass))
  103. {
  104. MonoObject* boxedObj = nullptr;
  105. if (arrayValue != nullptr)
  106. boxedObj = MonoUtil::box(mElementMonoClass, arrayValue);
  107. return ManagedSerializableFieldData::create(mArrayTypeInfo->mElementType, boxedObj);
  108. }
  109. else
  110. return ManagedSerializableFieldData::create(mArrayTypeInfo->mElementType, *(MonoObject**)arrayValue);
  111. }
  112. else
  113. return mCachedEntries[arrayIdx];
  114. }
  115. void ManagedSerializableArray::serialize()
  116. {
  117. if(mGCHandle == 0)
  118. return;
  119. mNumElements.resize(mArrayTypeInfo->mRank);
  120. for (UINT32 i = 0; i < mArrayTypeInfo->mRank; i++)
  121. mNumElements[i] = getLengthInternal(i);
  122. UINT32 numElements = getTotalLength();
  123. mCachedEntries = Vector<SPtr<ManagedSerializableFieldData>>(numElements);
  124. for (UINT32 i = 0; i < numElements; i++)
  125. mCachedEntries[i] = getFieldData(i);
  126. // Serialize children
  127. for (auto& fieldEntry : mCachedEntries)
  128. fieldEntry->serialize();
  129. MonoUtil::freeGCHandle(mGCHandle);
  130. mGCHandle = 0;
  131. }
  132. MonoObject* ManagedSerializableArray::deserialize()
  133. {
  134. MonoObject* managedInstance = createManagedInstance(mArrayTypeInfo, mNumElements);
  135. if (managedInstance == nullptr)
  136. return nullptr;
  137. ScriptArray scriptArray((MonoArray*)managedInstance);
  138. mElemSize = scriptArray.elementSize();
  139. initMonoObjects();
  140. // Deserialize children
  141. for (auto& fieldEntry : mCachedEntries)
  142. fieldEntry->deserialize();
  143. UINT32 idx = 0;
  144. for (auto& arrayEntry : mCachedEntries)
  145. {
  146. setFieldData((MonoArray*)managedInstance, idx, arrayEntry);
  147. idx++;
  148. }
  149. return managedInstance;
  150. }
  151. void ManagedSerializableArray::setValueInternal(MonoArray* obj, UINT32 arrayIdx, void* val)
  152. {
  153. ScriptArray scriptArray(obj);
  154. UINT32 numElems = (UINT32)scriptArray.size();
  155. assert(arrayIdx < numElems);
  156. scriptArray.setRaw(arrayIdx, (UINT8*)val, mElemSize);
  157. }
  158. void ManagedSerializableArray::initMonoObjects()
  159. {
  160. mElementMonoClass = mArrayTypeInfo->mElementType->getMonoClass();
  161. MonoClass* arrayClass = ScriptAssemblyManager::instance().getBuiltinClasses().systemArrayClass;
  162. mCopyMethod = arrayClass->getMethodExact("Copy", "Array,Array,int");
  163. }
  164. UINT32 ManagedSerializableArray::toSequentialIdx(const Vector<UINT32>& idx) const
  165. {
  166. UINT32 mNumDims = (UINT32)mNumElements.size();
  167. if(idx.size() != mNumDims)
  168. BS_EXCEPT(InvalidParametersException, "Provided index doesn't have the correct number of dimensions");
  169. if(mNumElements.size() == 0)
  170. return 0;
  171. UINT32 curIdx = 0;
  172. UINT32 prevDimensionSize = 1;
  173. for(INT32 i = mNumDims - 1; i >= 0; i--)
  174. {
  175. curIdx += idx[i] * prevDimensionSize;
  176. prevDimensionSize *= mNumElements[i];
  177. }
  178. return curIdx;
  179. }
  180. void ManagedSerializableArray::resize(const Vector<UINT32>& newSizes)
  181. {
  182. if (mGCHandle != 0)
  183. {
  184. assert(mArrayTypeInfo->mRank == (UINT32)newSizes.size());
  185. UINT32 srcCount = 1;
  186. for (auto& numElems : mNumElements)
  187. srcCount *= numElems;
  188. UINT32 dstCount = 1;
  189. for (auto& numElems : newSizes)
  190. dstCount *= numElems;
  191. UINT32 copyCount = std::min(srcCount, dstCount);
  192. MonoObject* newArray = createManagedInstance(mArrayTypeInfo, newSizes);
  193. void* params[3];
  194. params[0] = getManagedInstance();
  195. params[1] = newArray;
  196. params[2] = &copyCount;
  197. mCopyMethod->invoke(nullptr, params);
  198. MonoUtil::freeGCHandle(mGCHandle);
  199. mGCHandle = MonoUtil::newGCHandle(newArray, false);
  200. mNumElements = newSizes;
  201. }
  202. else
  203. {
  204. mNumElements = newSizes;
  205. mCachedEntries.resize(getTotalLength());
  206. }
  207. }
  208. UINT32 ManagedSerializableArray::getLengthInternal(UINT32 dimension) const
  209. {
  210. MonoObject* managedInstace = MonoUtil::getObjectFromGCHandle(mGCHandle);
  211. MonoClass* systemArray = ScriptAssemblyManager::instance().getBuiltinClasses().systemArrayClass;
  212. MonoMethod* getLength = systemArray->getMethod("GetLength", 1);
  213. void* params[1] = { &dimension };
  214. MonoObject* returnObj = getLength->invoke(managedInstace, params);
  215. return *(UINT32*)MonoUtil::unbox(returnObj);
  216. }
  217. UINT32 ManagedSerializableArray::getTotalLength() const
  218. {
  219. UINT32 totalNumElements = 1;
  220. for (auto& numElems : mNumElements)
  221. totalNumElements *= numElems;
  222. return totalNumElements;
  223. }
  224. RTTITypeBase* ManagedSerializableArray::getRTTIStatic()
  225. {
  226. return ManagedSerializableArrayRTTI::instance();
  227. }
  228. RTTITypeBase* ManagedSerializableArray::getRTTI() const
  229. {
  230. return ManagedSerializableArray::getRTTIStatic();
  231. }
  232. }