CSFunctionWriter.cpp 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101
  1. //
  2. // Copyright (c) 2014-2016 THUNDERBEAST GAMES LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. #include <Atomic/IO/FileSystem.h>
  23. #include "../JSBind.h"
  24. #include "../JSBModule.h"
  25. #include "../JSBPackage.h"
  26. #include "../JSBEnum.h"
  27. #include "../JSBClass.h"
  28. #include "../JSBFunction.h"
  29. #include "CSTypeHelper.h"
  30. #include "CSFunctionWriter.h"
  31. namespace ToolCore
  32. {
  33. bool CSFunctionWriter::wroteConstructor_ = false;
  34. CSFunctionWriter::CSFunctionWriter(JSBFunction *function) : JSBFunctionWriter(function)
  35. {
  36. }
  37. void CSFunctionWriter::WriteNativeParameterMarshal(String& source)
  38. {
  39. }
  40. void CSFunctionWriter::WriteNativeConstructor(String& source)
  41. {
  42. }
  43. void CSFunctionWriter::GenNativeCallParameters(String& sig)
  44. {
  45. JSBClass* klass = function_->GetClass();
  46. const Vector<JSBFunctionType*>& parameters = function_->GetParameters();
  47. Vector<String> args;
  48. unsigned numParams = parameters.Size();
  49. if (function_->HasMutatedReturn())
  50. numParams--;
  51. if (numParams)
  52. {
  53. for (unsigned int i = 0; i < numParams; i++)
  54. {
  55. JSBFunctionType* ptype = parameters.At(i);
  56. // ignore "Context" parameters
  57. if (ptype->type_->asClassType())
  58. {
  59. JSBClassType* classType = ptype->type_->asClassType();
  60. JSBClass* klass = classType->class_;
  61. if (klass->GetName() == "Context")
  62. {
  63. continue;
  64. }
  65. if (klass->IsNumberArray() || ptype->isReference_)
  66. args.Push(ToString("*%s", ptype->name_.CString()));
  67. else
  68. args.Push(ToString("%s", ptype->name_.CString()));
  69. }
  70. else if (ptype->type_->asVectorType())
  71. {
  72. args.Push(ToString("%s__vector", ptype->name_.CString()));
  73. }
  74. else
  75. {
  76. if (ptype->type_->asStringType())
  77. {
  78. args.Push(ToString("%s ? String(%s) : String::EMPTY", ptype->name_.CString(), ptype->name_.CString()));
  79. }
  80. else if (ptype->type_->asStringHashType())
  81. {
  82. args.Push(ToString("StringHash(%s)", ptype->name_.CString()));
  83. }
  84. else
  85. {
  86. args.Push(ToString("%s", ptype->name_.CString()));
  87. }
  88. }
  89. }
  90. }
  91. sig.Join(args, ", ");
  92. }
  93. void CSFunctionWriter::WriteNativeFunction(String& source)
  94. {
  95. JSBClass* klass = function_->GetClass();
  96. JSBPackage* package = klass->GetPackage();
  97. String fname = function_->IsConstructor() ? "Constructor" : function_->GetName();
  98. String returnType;
  99. String functionSig = CSTypeHelper::GetNativeFunctionSignature(function_, returnType);
  100. String line;
  101. line = ToString("ATOMIC_EXPORT_API %s %s\n",
  102. returnType.CString(), functionSig.CString());
  103. source += IndentLine(line);
  104. source += IndentLine("{\n");
  105. Indent();
  106. source += "\n";
  107. if (function_->HasMutatedReturn())
  108. {
  109. line = ToString("if (!__retValue) return;\n");
  110. source += IndentLine(line);
  111. line = ToString("VariantVector __retValueVector;\n");
  112. source += IndentLine(line);
  113. }
  114. // vector marshal
  115. bool hasVectorMarshal = false;
  116. const Vector<JSBFunctionType*>& fparams = function_->GetParameters();
  117. for (unsigned i = 0; i < fparams.Size(); i++)
  118. {
  119. JSBFunctionType* ftype = fparams[i];
  120. // skip mutated input param
  121. if (function_->HasMutatedReturn() && i == fparams.Size() - 1)
  122. break;
  123. // Interface
  124. JSBClass* interface = 0;
  125. if (ftype->type_->asClassType() && ftype->type_->asClassType()->class_->IsInterface())
  126. {
  127. // We need to downcast to the interface
  128. // TODO: this assumes Object* is in hierarchy, how do we validate this?
  129. interface = ftype->type_->asClassType()->class_;
  130. line = ToString("%s = dynamic_cast<%s*>((Object*)%s);\n", ftype->name_.CString(), interface->GetNativeName().CString(), ftype->name_.CString());
  131. source += IndentLine(line);
  132. }
  133. // Vector
  134. JSBVectorType* vtype = ftype->type_->asVectorType();
  135. if (!vtype)
  136. continue;
  137. JSBClassType* classType = vtype->vectorType_->asClassType();
  138. if (!classType)
  139. continue;
  140. String className = classType->class_->GetName();
  141. String vectorMarshal;
  142. hasVectorMarshal = true;
  143. if (vtype->isVariantVector_)
  144. {
  145. const String& pname = ftype->name_;
  146. // TODO: handle early out with return value
  147. if (!function_->returnType_)
  148. source += IndentLine(ToString("if (!%s) return;\n", pname.CString()));
  149. source += IndentLine(ToString("VariantVector %s__vector;\n", pname.CString()));
  150. source += IndentLine(ToString("%s->AdaptToVector(%s__vector);\n", pname.CString(), pname.CString()));
  151. }
  152. else if (vtype->isPODVector_)
  153. {
  154. const String& pname = ftype->name_;
  155. source += IndentLine(ToString("PODVector<%s*> %s__vector;\n", className.CString(), pname.CString()));
  156. source += IndentLine(ToString("if (%s) %s->AdaptToVector<%s*>(%s__vector);\n", pname.CString(), pname.CString(), className.CString(), pname.CString()));
  157. }
  158. else
  159. {
  160. // vectorMarshal = ToString("PODVector<%s*> %s__vector", className.CString(), ftype->name_.CString());
  161. }
  162. if (vectorMarshal.Length())
  163. {
  164. source += IndentLine(vectorMarshal);
  165. vectorMarshal = String::EMPTY;
  166. }
  167. }
  168. bool returnValue = false;
  169. bool sharedPtrReturn = false;
  170. String returnStatement;
  171. if (returnType == "const char*")
  172. {
  173. returnValue = true;
  174. source += IndentLine("static String returnValue;\n");
  175. returnStatement = "returnValue = ";
  176. }
  177. else if (function_->GetReturnClass() && function_->GetReturnClass()->IsNumberArray())
  178. {
  179. returnStatement = "*returnValue = ";
  180. }
  181. else if (function_->GetReturnClass() && function_->GetReturnType()->isSharedPtr_)
  182. {
  183. returnStatement = ToString("SharedPtr<%s> returnValuePtr = ", function_->GetReturnClass()->GetNativeName().CString());
  184. sharedPtrReturn = true;
  185. }
  186. else if (function_->GetReturnType() && function_->GetReturnType()->type_->asVectorType())
  187. {
  188. // we have an out parameter
  189. JSBVectorType* vtype = function_->GetReturnType()->type_->asVectorType();
  190. if (!vtype->vectorTypeIsSharedPtr_ && !vtype->vectorTypeIsWeakPtr_)
  191. {
  192. returnStatement = ToString("%sVector<%s*> returnValue__vector = ", vtype->isPODVector_ ? "POD" : "", vtype->vectorType_->asClassType()->class_->GetName().CString());
  193. }
  194. else
  195. {
  196. returnStatement = ToString("%sVector<%s<%s>> returnValue__vector = ", vtype->isPODVector_ ? "POD" : "", vtype->vectorTypeIsSharedPtr_ ? "SharedPtr" : "WeakPtr", vtype->vectorType_->asClassType()->class_->GetName().CString());
  197. }
  198. }
  199. else
  200. {
  201. if (returnType != "void" && !hasVectorMarshal)
  202. {
  203. returnStatement = "return ";
  204. }
  205. else if (returnType != "void")
  206. {
  207. returnStatement = ToString("%s returnValue = ", returnType.CString());
  208. }
  209. }
  210. String callSig;
  211. GenNativeCallParameters(callSig);
  212. if (!function_->isConstructor_)
  213. {
  214. if (function_->IsStatic())
  215. {
  216. line = ToString("%s%s::%s(%s);\n", returnStatement.CString(), klass->GetNativeName().CString(), function_->GetName().CString(), callSig.CString());
  217. }
  218. else
  219. {
  220. if (function_->hasMutatedReturn_)
  221. {
  222. // this handles VariantVector case now, can be expanded
  223. line = ToString("__retValueVector = self->%s(%s);\n", function_->GetName().CString(), callSig.CString());
  224. }
  225. else
  226. {
  227. line = ToString("%sself->%s(%s);\n", returnStatement.CString(), function_->GetName().CString(), callSig.CString());
  228. }
  229. }
  230. }
  231. else
  232. {
  233. if (klass->IsAbstract())
  234. {
  235. line = "return 0; // Abstract Class\n";
  236. }
  237. else if (klass->IsObject())
  238. {
  239. if (callSig.Length())
  240. line = ToString("return new %s(NETCore::GetContext(), %s);\n", klass->GetNativeName().CString(), callSig.CString());
  241. else
  242. line = ToString("return new %s(NETCore::GetContext());\n", klass->GetNativeName().CString());
  243. }
  244. else
  245. {
  246. line = ToString("return new %s(%s);\n", klass->GetNativeName().CString(), callSig.CString());
  247. }
  248. }
  249. source += IndentLine(line);
  250. // Vector marshaling
  251. for (unsigned i = 0; i < fparams.Size(); i++)
  252. {
  253. JSBFunctionType* ftype = fparams[i];
  254. JSBVectorType* vtype = ftype->type_->asVectorType();
  255. if (!vtype)
  256. continue;
  257. if (function_->HasMutatedReturn() && i == fparams.Size() - 1)
  258. {
  259. source += IndentLine("__retValue->AdaptFromVector(__retValueVector);\n");
  260. break;
  261. }
  262. JSBClassType* classType = vtype->vectorType_->asClassType();
  263. if (!classType)
  264. continue;
  265. String className = classType->class_->GetName();
  266. String vectorMarshal;
  267. if (vtype->isPODVector_)
  268. {
  269. const String& pname = ftype->name_;
  270. source += IndentLine(ToString("if (%s) %s->AdaptFromVector<%s*>(%s__vector);\n", pname.CString(), pname.CString(), className.CString(), pname.CString()));
  271. }
  272. else
  273. {
  274. // vectorMarshal = ToString("PODVector<%s*> %s__vector", className.CString(), ftype->name_.CString());
  275. }
  276. if (vectorMarshal.Length())
  277. {
  278. source += IndentLine(vectorMarshal);
  279. vectorMarshal = String::EMPTY;
  280. }
  281. }
  282. if (sharedPtrReturn)
  283. {
  284. // We need to keep the shared ptr return value alive through the call, without adding an unwanted reference
  285. source += IndentLine(ToString("%s* returnValue = returnValuePtr;\n", function_->GetReturnClass()->GetNativeName().CString()));
  286. source += IndentLine("if (returnValue)\n");
  287. source += IndentLine("{\n");
  288. Indent();
  289. source += IndentLine("returnValue->AddRefSilent();\n");
  290. source += IndentLine("returnValuePtr = 0;\n");
  291. source += IndentLine("returnValue->ReleaseRefSilent();\n");
  292. Dedent();
  293. source += IndentLine("}\n");
  294. source += IndentLine("return returnValue;\n");
  295. }
  296. else if (returnType == "const char*")
  297. {
  298. source += IndentLine("return returnValue.CString();\n");
  299. }
  300. else if (function_->GetReturnType() && function_->GetReturnType()->type_->asVectorType())
  301. {
  302. // we have an out parameter
  303. JSBVectorType* vtype = function_->GetReturnType()->type_->asVectorType();
  304. source += IndentLine("if (returnValue) returnValue->AdaptFromVector(returnValue__vector);\n");
  305. }
  306. else if (returnType != "void" && hasVectorMarshal)
  307. {
  308. source += IndentLine("return returnValue;\n");
  309. }
  310. Dedent();
  311. source += IndentLine("}\n");
  312. source += "\n";
  313. }
  314. void CSFunctionWriter::GenerateNativeSource(String& sourceOut)
  315. {
  316. String source = "";
  317. WriteNativeFunction(source);
  318. sourceOut += source;
  319. }
  320. // MANAGED----------------------------------------------------------------------------------------
  321. void CSFunctionWriter::WriteDefaultStructParameters(String& source)
  322. {
  323. for (unsigned i = 0; i < defaultStructParameters_.Size(); i++)
  324. {
  325. const DefaultStructParameter& dparm = defaultStructParameters_[i];
  326. String line = ToString("if (default(%s).Equals(%s)) %s = %s;\n",
  327. dparm.type.CString(), dparm.parameterName.CString(), dparm.parameterName.CString(),
  328. dparm.assignment.CString());
  329. source += IndentLine(line);
  330. }
  331. }
  332. void CSFunctionWriter::WriteManagedPInvokeFunctionSignature(String& source)
  333. {
  334. JSBClass* klass = function_->GetClass();
  335. JSBPackage* package = klass->GetPackage();
  336. if (klass->IsInterface())
  337. return;
  338. source += "\n";
  339. // CoreCLR has pinvoke security demand code commented out, so we do not (currently) need this optimization:
  340. // https://github.com/dotnet/coreclr/issues/1605
  341. // line = "[SuppressUnmanagedCodeSecurity]\n";
  342. // source += IndentLine(line);
  343. String line = "[DllImport (Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]\n";
  344. source += IndentLine(line);
  345. String returnType = CSTypeHelper::GetPInvokeTypeString(function_->GetReturnType());
  346. // handled by out parameter
  347. if (function_->GetReturnType() && function_->GetReturnType()->type_->asVectorType())
  348. returnType = "void";
  349. if (returnType == "bool")
  350. {
  351. // default boolean marshal is 4 byte windows type BOOL and not 1 byte bool
  352. // https://blogs.msdn.microsoft.com/jaredpar/2008/10/14/pinvoke-and-bool-or-should-i-say-bool/
  353. source += IndentLine("[return: MarshalAs(UnmanagedType.I1)]\n");
  354. }
  355. if (returnType == "string")
  356. returnType = "IntPtr";
  357. if (function_->IsConstructor())
  358. returnType = "IntPtr";
  359. const Vector<JSBFunctionType*>& parameters = function_->GetParameters();
  360. Vector<String> args;
  361. if (!function_->IsConstructor() && !function_->IsStatic())
  362. {
  363. args.Push("IntPtr self");
  364. }
  365. if (parameters.Size())
  366. {
  367. for (unsigned int i = 0; i < parameters.Size(); i++)
  368. {
  369. JSBFunctionType* ptype = parameters.At(i);
  370. String name = ptype->name_;
  371. if (name == "object")
  372. name = "_object";
  373. else if (name == "readonly")
  374. name = "readOnly";
  375. else if (name == "params")
  376. name = "parameters";
  377. // ignore "Context" parameters
  378. if (ptype->type_->asClassType())
  379. {
  380. JSBClassType* classType = ptype->type_->asClassType();
  381. JSBClass* klass = classType->class_;
  382. if (klass->GetName() == "Context")
  383. {
  384. continue;
  385. }
  386. if (klass->IsNumberArray())
  387. {
  388. args.Push("ref " + klass->GetName() + " " + name);
  389. }
  390. else
  391. {
  392. args.Push("IntPtr " + name);
  393. }
  394. }
  395. else
  396. {
  397. args.Push(CSTypeHelper::GetPInvokeTypeString(ptype) + " " + name);
  398. }
  399. }
  400. }
  401. if (function_->GetReturnClass())
  402. {
  403. JSBClass* retClass = function_->GetReturnClass();
  404. if (retClass->IsNumberArray())
  405. {
  406. args.Push("ref " + retClass->GetName() + " retValue");
  407. }
  408. }
  409. else if (function_->GetReturnType() && function_->GetReturnType()->type_->asVectorType())
  410. {
  411. args.Push("IntPtr returnValue");
  412. }
  413. String pstring;
  414. pstring.Join(args, ", ");
  415. String fname = function_->IsConstructor() ? "Constructor" : function_->GetName();
  416. line = ToString("private static extern %s csb_%s_%s_%s_%u(%s);\n",
  417. returnType.CString(), package->GetName().CString(), klass->GetName().CString(),
  418. fname.CString(), function_->GetID(), pstring.CString());
  419. source += IndentLine(line);
  420. source += "\n";
  421. }
  422. void CSFunctionWriter::GenManagedFunctionParameters(String& sig)
  423. {
  424. // generate args
  425. const Vector<JSBFunctionType*>& parameters = function_->GetParameters();
  426. if (parameters.Size())
  427. {
  428. for (unsigned int i = 0; i < parameters.Size(); i++)
  429. {
  430. bool isStruct = false;
  431. JSBFunctionType* ptype = parameters.At(i);
  432. // ignore "Context" parameters
  433. if (ptype->type_->asClassType())
  434. {
  435. JSBClassType* classType = ptype->type_->asClassType();
  436. JSBClass* klass = classType->class_;
  437. if (klass->GetName() == "Context")
  438. {
  439. continue;
  440. }
  441. // TODO: we should have a better system for struct type in general
  442. // This number array is really for JS
  443. if (klass->IsNumberArray())
  444. {
  445. isStruct = true;
  446. }
  447. }
  448. String managedTypeString = CSTypeHelper::GetManagedTypeString(ptype);
  449. if (!ptype->isConst_ && (ptype->isReference_ && isStruct))
  450. {
  451. // pass by reference
  452. managedTypeString = "ref " + managedTypeString;
  453. }
  454. sig += managedTypeString;
  455. String init = ptype->initializer_;
  456. if (init.Length())
  457. {
  458. init = MapDefaultParameter(ptype);
  459. if (init.Length())
  460. sig += " = " + init;
  461. }
  462. if (i + 1 != parameters.Size())
  463. sig += ", ";
  464. }
  465. }
  466. }
  467. void CSFunctionWriter::WriteManagedConstructor(String& source)
  468. {
  469. JSBClass* klass = function_->GetClass();
  470. JSBPackage* package = klass->GetPackage();
  471. if (klass->GetName() == "RefCounted")
  472. return;
  473. // wrapping constructor
  474. String line;
  475. if (!wroteConstructor_)
  476. {
  477. line = ToString("public %s (IntPtr native) : base (native)\n", klass->GetName().CString());
  478. source += IndentLine(line);
  479. source += IndentLine("{\n");
  480. source += IndentLine("}\n\n");
  481. }
  482. // don't add wrapping constructor for overloads
  483. wroteConstructor_ = true;
  484. String sig;
  485. GenManagedFunctionParameters(sig);
  486. line = ToString("public %s (%s)\n", klass->GetName().CString(), sig.CString());
  487. source += IndentLine(line);
  488. source += IndentLine("{\n");
  489. Indent();
  490. WriteDefaultStructParameters(source);
  491. source += IndentLine("if (nativeInstance == IntPtr.Zero)\n");
  492. source += IndentLine("{\n");
  493. Indent();
  494. source += IndentLine(ToString("var classType = typeof(%s);\n", klass->GetName().CString()));
  495. source += IndentLine("var thisType = this.GetType();\n");
  496. source += IndentLine("var thisTypeIsNative = NativeCore.IsNativeType(thisType);\n");
  497. source += IndentLine("var nativeAncsestorType = NativeCore.GetNativeAncestorType(thisType);\n");
  498. source += IndentLine("if ( (thisTypeIsNative && (thisType == classType)) || (!thisTypeIsNative && (nativeAncsestorType == classType)))\n");
  499. source += IndentLine("{\n");
  500. Indent();
  501. String callSig;
  502. GenPInvokeCallParameters(callSig);
  503. line = ToString("nativeInstance = NativeCore.RegisterNative (csb_%s_%s_Constructor_%u(%s), this);\n",
  504. package->GetName().CString(), klass->GetName().CString(), function_->GetID(), callSig.CString());
  505. source += IndentLine(line);
  506. Dedent();
  507. source += IndentLine("}\n");
  508. Dedent();
  509. source += IndentLine("}\n");
  510. Dedent();
  511. source += IndentLine("}\n");
  512. }
  513. void CSFunctionWriter::GenPInvokeCallParameters(String& sig)
  514. {
  515. // generate args
  516. const Vector<JSBFunctionType*>& parameters = function_->GetParameters();
  517. if (parameters.Size())
  518. {
  519. for (unsigned int i = 0; i < parameters.Size(); i++)
  520. {
  521. JSBFunctionType* ptype = parameters.At(i);
  522. // ignore "Context" parameters
  523. if (ptype->type_->asClassType())
  524. {
  525. JSBClassType* classType = ptype->type_->asClassType();
  526. JSBClass* klass = classType->class_;
  527. if (klass->GetName() == "Context")
  528. {
  529. continue;
  530. }
  531. }
  532. String name = ptype->name_;
  533. if (name == "object")
  534. name = "_object";
  535. else if (name == "readonly")
  536. name = "readOnly";
  537. else if (name == "params")
  538. name = "parameters";
  539. if (ptype->type_->asClassType())
  540. {
  541. JSBClass* pclass = ptype->type_->asClassType()->class_;
  542. if (pclass->IsNumberArray())
  543. {
  544. sig += "ref " + name;
  545. }
  546. else
  547. {
  548. sig += name + " == null ? IntPtr.Zero : " + name + ".NativeInstance";
  549. }
  550. }
  551. else
  552. {
  553. sig += name;
  554. }
  555. if (i + 1 != parameters.Size())
  556. sig += ", ";
  557. }
  558. }
  559. // data marshaller
  560. if (function_->GetReturnType() && !CSTypeHelper::IsSimpleReturn(function_->GetReturnType()))
  561. {
  562. if (function_->GetReturnClass()->IsNumberArray())
  563. {
  564. if (sig.Length())
  565. sig += ", ";
  566. JSBClass* klass = function_->GetClass();
  567. sig += ToString("ref %s%s%uReturnValue", klass->GetName().CString(), function_->GetName().CString(), function_->GetID());
  568. }
  569. }
  570. else if (!function_->IsStatic() && function_->GetReturnType() && function_->GetReturnType()->type_->asVectorType())
  571. {
  572. if (sig.Length())
  573. sig += ", ";
  574. JSBClass* klass = function_->GetClass();
  575. sig += "returnScriptVector";
  576. }
  577. }
  578. void CSFunctionWriter::WriteManagedFunction(String& source)
  579. {
  580. JSBClass* klass = function_->GetClass();
  581. JSBPackage* package = klass->GetPackage();
  582. String sig;
  583. String returnType = CSTypeHelper::GetManagedTypeString(function_->GetReturnType());
  584. GenManagedFunctionParameters(sig);
  585. String line = klass->IsInterface() ? "" : "public ";
  586. if (function_->IsStatic())
  587. {
  588. line += "static ";
  589. }
  590. bool marked = false;
  591. JSBClass* baseClass = klass->GetBaseClass();
  592. if (baseClass)
  593. {
  594. JSBFunction* override = baseClass->MatchFunction(function_, true);
  595. if (override)
  596. {
  597. marked = true;
  598. if (override->IsVirtual())
  599. line += "override ";
  600. else
  601. line += "new ";
  602. }
  603. }
  604. if (!marked && function_->IsVirtual() && !klass->IsInterface())
  605. line += "virtual ";
  606. line += ToString("%s %s (%s)", returnType.CString(), function_->GetName().CString(), sig.CString());
  607. if (klass->IsInterface())
  608. {
  609. // If we're an interface we have no implementation
  610. line += ";\n\n";
  611. source += IndentLine(line);
  612. return;
  613. }
  614. else
  615. line += "\n";
  616. source += IndentLine(line);
  617. source += IndentLine("{\n");
  618. Indent();
  619. WriteDefaultStructParameters(source);
  620. line.Clear();
  621. if (function_->GetReturnType())
  622. {
  623. if (function_->GetReturnType()->type_->asStringType())
  624. {
  625. line += "return System.Runtime.InteropServices.Marshal.PtrToStringAnsi(";
  626. }
  627. else if (function_->GetReturnType()->type_->asStringHashType())
  628. {
  629. line += "return ";
  630. }
  631. else if (function_->GetReturnType()->type_->asVectorType())
  632. {
  633. source += IndentLine(ToString("var returnScriptVector = %s%s%uReturnValue.GetScriptVector();\n", klass->GetName().CString(), function_->GetName().CString(), function_->GetID()));
  634. }
  635. else if (CSTypeHelper::IsSimpleReturn(function_->GetReturnType()))
  636. line += "return ";
  637. else
  638. {
  639. if (function_->GetReturnClass())
  640. {
  641. if (!function_->GetReturnClass()->IsNumberArray())
  642. line += "IntPtr retNativeInstance = ";
  643. }
  644. }
  645. }
  646. String callSig;
  647. GenPInvokeCallParameters(callSig);
  648. String nativeInstance;
  649. if (!function_->IsStatic())
  650. nativeInstance = "nativeInstance";
  651. line += ToString("csb_%s_%s_%s_%u(%s",
  652. package->GetName().CString(), klass->GetName().CString(), function_->GetName().CString(), function_->GetID(), nativeInstance.CString());
  653. if (callSig.Length())
  654. {
  655. if (nativeInstance.Length())
  656. line += ", " + callSig;
  657. else
  658. line += callSig;
  659. }
  660. if (function_->GetReturnType())
  661. {
  662. if (function_->GetReturnType()->type_->asStringType())
  663. line += ")";
  664. }
  665. line += ");\n";
  666. source += IndentLine(line);
  667. if (function_->GetReturnType() && !CSTypeHelper::IsSimpleReturn(function_->GetReturnType()))
  668. {
  669. if (function_->GetReturnType()->type_->asClassType())
  670. {
  671. JSBClass* retClass = function_->GetReturnClass();
  672. JSBClass* klass = function_->GetClass();
  673. if (retClass->IsNumberArray())
  674. {
  675. line = ToString("return %s%s%uReturnValue;", klass->GetName().CString(), function_->GetName().CString(), function_->GetID());
  676. }
  677. else
  678. {
  679. line = ToString("return retNativeInstance == IntPtr.Zero ? null : NativeCore.WrapNative<%s> (retNativeInstance);", retClass->GetName().CString());
  680. }
  681. source += IndentLine(line);
  682. source+= "\n";
  683. }
  684. }
  685. else if (function_->GetReturnType() && function_->GetReturnType()->type_->asVectorType())
  686. {
  687. if (!function_->IsStatic())
  688. {
  689. source += IndentLine(ToString("return %s%s%uReturnValue;", klass->GetName().CString(), function_->GetName().CString(), function_->GetID()));
  690. source+= "\n";
  691. }
  692. }
  693. Dedent();
  694. source += IndentLine("}\n");
  695. }
  696. void CSFunctionWriter::GenerateManagedSource(String& sourceOut)
  697. {
  698. JSBClass* klass = function_->GetClass();
  699. String source = "";
  700. Indent();
  701. Indent();
  702. if (function_->GetDocString().Length())
  703. {
  704. // monodocer -assembly:NETCore.dll -path:en -pretty
  705. // mdoc export-html -o htmldocs en
  706. source += IndentLine("/// <summary>\n");
  707. if (function_->GetDocString().Contains('\n'))
  708. source += IndentLine("/* " + function_->GetDocString() + "*/\n");
  709. else
  710. source += IndentLine("/// " + function_->GetDocString() + "\n");
  711. source += IndentLine("/// </summary>\n");
  712. }
  713. if (function_->IsConstructor())
  714. WriteManagedConstructor(source);
  715. else
  716. WriteManagedFunction(source);
  717. WriteManagedPInvokeFunctionSignature(source);
  718. if (!klass->IsInterface())
  719. {
  720. // data marshaller
  721. if (function_->GetReturnType() && !CSTypeHelper::IsSimpleReturn(function_->GetReturnType()))
  722. {
  723. if (function_->GetReturnClass())
  724. {
  725. JSBClass* retClass = function_->GetReturnClass();
  726. if (retClass->IsNumberArray())
  727. {
  728. String managedType = CSTypeHelper::GetManagedTypeString(function_->GetReturnType());
  729. String marshal = "private ";
  730. if (function_->IsStatic())
  731. marshal += "static ";
  732. marshal += managedType + " ";
  733. marshal += ToString("%s%s%uReturnValue = new %s();\n", klass->GetName().CString(), function_->GetName().CString(), function_->GetID(), managedType.CString());
  734. sourceOut += IndentLine(marshal);
  735. }
  736. }
  737. }
  738. else if (!function_->IsStatic() && function_->GetReturnType() && function_->GetReturnType()->type_->asVectorType())
  739. {
  740. JSBVectorType* vtype = function_->GetReturnType()->type_->asVectorType();
  741. if (vtype->vectorType_->asClassType())
  742. {
  743. String classname = vtype->vectorType_->asClassType()->class_->GetName();
  744. String typestring = "Vector<" + classname + ">";
  745. String marshal = "private " + typestring + " ";
  746. marshal += ToString("%s%s%uReturnValue = new %s();\n", function_->GetClass()->GetName().CString(), function_->GetName().CString(), function_->GetID(), typestring.CString());
  747. sourceOut += IndentLine(marshal);
  748. }
  749. }
  750. }
  751. Dedent();
  752. Dedent();
  753. sourceOut += source;
  754. }
  755. void CSFunctionWriter::GenerateSource(String& sourceOut)
  756. {
  757. }
  758. String CSFunctionWriter::MapDefaultParameter(JSBFunctionType* parameter)
  759. {
  760. String init = parameter->initializer_;
  761. if (!init.Length())
  762. return init;
  763. if (parameter->type_->asClassType())
  764. {
  765. if (init == "0")
  766. return "null";
  767. }
  768. if (parameter->type_->asEnumType())
  769. {
  770. return parameter->type_->asEnumType()->enum_->GetName() + "." + init;
  771. }
  772. if (function_->class_->GetPackage()->ContainsConstant(init))
  773. return "Constants." + init;
  774. if (init == "true" || init == "false")
  775. return init;
  776. if (init == "0.0f")
  777. return init;
  778. if (init == "1.0f")
  779. return init;
  780. if (init == "0.1f")
  781. return init;
  782. if (init == "0")
  783. return init;
  784. if (init == "3")
  785. return init;
  786. if (init == "-1")
  787. return init;
  788. if (init == "\"\\t\"")
  789. return init;
  790. if (init == "NULL")
  791. return "null";
  792. if (init == "M_MAX_UNSIGNED")
  793. return "0xffffffff";
  794. if (init == "String::EMPTY")
  795. return "\"\"";
  796. // this kind of sucks, can't define const structs
  797. // and default parameters need to be const :/
  798. DefaultStructParameter dparm;
  799. dparm.parameterName = parameter->name_;
  800. if (init == "Vector3::ZERO")
  801. {
  802. dparm.type = "Vector3";
  803. dparm.assignment = "Vector3.Zero";
  804. defaultStructParameters_.Push(dparm);
  805. return "default(Vector3)";
  806. }
  807. if (init == "Vector3::ONE")
  808. {
  809. dparm.type = "Vector3";
  810. dparm.assignment = "Vector3.One";
  811. defaultStructParameters_.Push(dparm);
  812. return "default(Vector3)";
  813. }
  814. if (init == "Vector3::UP")
  815. {
  816. dparm.type = "Vector3";
  817. dparm.assignment = "Vector3.Up";
  818. defaultStructParameters_.Push(dparm);
  819. return "default(Vector3)";
  820. }
  821. if (init == "IntVector2::ZERO")
  822. {
  823. dparm.type = "IntVector2";
  824. dparm.assignment = "IntVector2.Zero";
  825. defaultStructParameters_.Push(dparm);
  826. return "default(IntVector2)";
  827. }
  828. if (init == "Quaternion::IDENTITY")
  829. {
  830. dparm.type = "Quaternion";
  831. dparm.assignment = "Quaternion.Identity";
  832. defaultStructParameters_.Push(dparm);
  833. return "default(Quaternion)";
  834. }
  835. if (init == "StringHash::ZERO")
  836. {
  837. dparm.type = "StringHash";
  838. dparm.assignment = "StringHash.Zero";
  839. defaultStructParameters_.Push(dparm);
  840. return "default(StringHash)";
  841. }
  842. return String::EMPTY;
  843. }
  844. }