CSFunctionWriter.cpp 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000
  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. Vector<JSBFunctionType*>& parameters = function_->GetParameters();
  47. Vector<String> args;
  48. if (parameters.Size())
  49. {
  50. for (unsigned int i = 0; i < parameters.Size(); i++)
  51. {
  52. JSBFunctionType* ptype = parameters.At(i);
  53. // ignore "Context" parameters
  54. if (ptype->type_->asClassType())
  55. {
  56. JSBClassType* classType = ptype->type_->asClassType();
  57. JSBClass* klass = classType->class_;
  58. if (klass->GetName() == "Context")
  59. {
  60. continue;
  61. }
  62. if (klass->IsNumberArray() || ptype->isReference_)
  63. args.Push(ToString("*%s", ptype->name_.CString()));
  64. else
  65. args.Push(ToString("%s", ptype->name_.CString()));
  66. }
  67. else if (ptype->type_->asVectorType())
  68. {
  69. args.Push(ToString("%s__vector", ptype->name_.CString()));
  70. }
  71. else
  72. {
  73. if (ptype->type_->asStringType() || ptype->type_->asStringHashType())
  74. {
  75. args.Push(ToString("%s ? String(%s) : String::EMPTY", ptype->name_.CString(), ptype->name_.CString()));
  76. }
  77. else
  78. {
  79. args.Push(ToString("%s", ptype->name_.CString()));
  80. }
  81. }
  82. }
  83. }
  84. sig.Join(args, ", ");
  85. }
  86. void CSFunctionWriter::WriteNativeFunction(String& source)
  87. {
  88. JSBClass* klass = function_->GetClass();
  89. JSBPackage* package = klass->GetPackage();
  90. String fname = function_->IsConstructor() ? "Constructor" : function_->GetName();
  91. String returnType;
  92. String functionSig = CSTypeHelper::GetNativeFunctionSignature(function_, returnType);
  93. String line;
  94. line = ToString("ATOMIC_EXPORT_API %s %s\n",
  95. returnType.CString(), functionSig.CString());
  96. source += IndentLine(line);
  97. source += IndentLine("{\n");
  98. Indent();
  99. source += "\n";
  100. // vector marshal
  101. bool hasVectorMarshal = false;
  102. Vector<JSBFunctionType*>& fparams = function_->GetParameters();
  103. for (unsigned i = 0; i < fparams.Size(); i++)
  104. {
  105. JSBFunctionType* ftype = fparams[i];
  106. JSBVectorType* vtype = ftype->type_->asVectorType();
  107. if (!vtype)
  108. continue;
  109. JSBClassType* classType = vtype->vectorType_->asClassType();
  110. if (!classType)
  111. continue;
  112. String className = classType->class_->GetName();
  113. String vectorMarshal;
  114. hasVectorMarshal = true;
  115. if (vtype->isPODVector_)
  116. {
  117. const String& pname = ftype->name_;
  118. source += IndentLine(ToString("PODVector<%s*> %s__vector;\n", className.CString(), pname.CString()));
  119. source += IndentLine(ToString("if (%s) %s->AdaptToVector<%s*>(%s__vector);\n", pname.CString(), pname.CString(), className.CString(), pname.CString()));
  120. }
  121. else
  122. {
  123. // vectorMarshal = ToString("PODVector<%s*> %s__vector", className.CString(), ftype->name_.CString());
  124. }
  125. if (vectorMarshal.Length())
  126. {
  127. source += IndentLine(vectorMarshal);
  128. vectorMarshal = String::EMPTY;
  129. }
  130. }
  131. bool returnValue = false;
  132. bool sharedPtrReturn = false;
  133. String returnStatement;
  134. if (returnType == "const char*")
  135. {
  136. returnValue = true;
  137. source += IndentLine("static String returnValue;\n");
  138. returnStatement = "returnValue = ";
  139. }
  140. else if (function_->GetReturnClass() && function_->GetReturnClass()->IsNumberArray())
  141. {
  142. returnStatement = "*returnValue = ";
  143. }
  144. else if (function_->GetReturnClass() && function_->GetReturnType()->isSharedPtr_)
  145. {
  146. returnStatement = ToString("SharedPtr<%s> returnValue = ", function_->GetReturnClass()->GetNativeName().CString());
  147. sharedPtrReturn = true;
  148. }
  149. else if (function_->GetReturnType() && function_->GetReturnType()->type_->asVectorType())
  150. {
  151. // we have an out parameter
  152. JSBVectorType* vtype = function_->GetReturnType()->type_->asVectorType();
  153. if (!vtype->vectorTypeIsSharedPtr_ && !vtype->vectorTypeIsWeakPtr_)
  154. {
  155. returnStatement = ToString("%sVector<%s*> returnValue__vector = ", vtype->isPODVector_ ? "POD" : "", vtype->vectorType_->asClassType()->class_->GetName().CString());
  156. }
  157. else
  158. {
  159. returnStatement = ToString("%sVector<%s<%s>> returnValue__vector = ", vtype->isPODVector_ ? "POD" : "", vtype->vectorTypeIsSharedPtr_ ? "SharedPtr" : "WeakPtr", vtype->vectorType_->asClassType()->class_->GetName().CString());
  160. }
  161. }
  162. else
  163. {
  164. if (returnType != "void" && !hasVectorMarshal)
  165. {
  166. returnStatement = "return ";
  167. }
  168. else if (returnType != "void")
  169. {
  170. returnStatement = ToString("%s returnValue = ", returnType.CString());
  171. }
  172. }
  173. String callSig;
  174. GenNativeCallParameters(callSig);
  175. if (!function_->isConstructor_)
  176. {
  177. if (function_->IsStatic())
  178. {
  179. line = ToString("%s%s::%s(%s);\n", returnStatement.CString(), klass->GetNativeName().CString(), function_->GetName().CString(), callSig.CString());
  180. }
  181. else
  182. {
  183. line = ToString("%sself->%s(%s);\n", returnStatement.CString(), function_->GetName().CString(), callSig.CString());
  184. }
  185. }
  186. else
  187. {
  188. if (klass->IsAbstract())
  189. {
  190. line = "return 0; // Abstract Class\n";
  191. }
  192. else if (klass->IsObject())
  193. {
  194. if (callSig.Length())
  195. line = ToString("return new %s(NETCore::GetContext(), %s);\n", klass->GetNativeName().CString(), callSig.CString());
  196. else
  197. line = ToString("return new %s(NETCore::GetContext());\n", klass->GetNativeName().CString());
  198. }
  199. else
  200. {
  201. line = ToString("return new %s(%s);\n", klass->GetNativeName().CString(), callSig.CString());
  202. }
  203. }
  204. source += IndentLine(line);
  205. // Vector marshaling
  206. for (unsigned i = 0; i < fparams.Size(); i++)
  207. {
  208. JSBFunctionType* ftype = fparams[i];
  209. JSBVectorType* vtype = ftype->type_->asVectorType();
  210. if (!vtype)
  211. continue;
  212. JSBClassType* classType = vtype->vectorType_->asClassType();
  213. if (!classType)
  214. continue;
  215. String className = classType->class_->GetName();
  216. String vectorMarshal;
  217. if (vtype->isPODVector_)
  218. {
  219. const String& pname = ftype->name_;
  220. source += IndentLine(ToString("if (%s) %s->AdaptFromVector<%s*>(%s__vector);\n", pname.CString(), pname.CString(), className.CString(), pname.CString()));
  221. }
  222. else
  223. {
  224. // vectorMarshal = ToString("PODVector<%s*> %s__vector", className.CString(), ftype->name_.CString());
  225. }
  226. if (vectorMarshal.Length())
  227. {
  228. source += IndentLine(vectorMarshal);
  229. vectorMarshal = String::EMPTY;
  230. }
  231. }
  232. if (sharedPtrReturn)
  233. {
  234. source += IndentLine("if (returnValue.NotNull()) returnValue->AddRef();\n");
  235. source += IndentLine("return returnValue;\n");
  236. }
  237. else if (returnType == "const char*")
  238. {
  239. source += IndentLine("return returnValue.CString();\n");
  240. }
  241. else if (function_->GetReturnType() && function_->GetReturnType()->type_->asVectorType())
  242. {
  243. // we have an out parameter
  244. JSBVectorType* vtype = function_->GetReturnType()->type_->asVectorType();
  245. source += IndentLine("if (returnValue) returnValue->AdaptFromVector(returnValue__vector);\n");
  246. }
  247. else if (returnType != "void" && hasVectorMarshal)
  248. {
  249. source += IndentLine("return returnValue;\n");
  250. }
  251. Dedent();
  252. source += IndentLine("}\n");
  253. source += "\n";
  254. }
  255. void CSFunctionWriter::GenerateNativeSource(String& sourceOut)
  256. {
  257. String source = "";
  258. WriteNativeFunction(source);
  259. sourceOut += source;
  260. }
  261. // MANAGED----------------------------------------------------------------------------------------
  262. void CSFunctionWriter::WriteDefaultStructParameters(String& source)
  263. {
  264. for (unsigned i = 0; i < defaultStructParameters_.Size(); i++)
  265. {
  266. const DefaultStructParameter& dparm = defaultStructParameters_[i];
  267. String line = ToString("if (default(%s).Equals(%s)) %s = %s;\n",
  268. dparm.type.CString(), dparm.parameterName.CString(), dparm.parameterName.CString(),
  269. dparm.assignment.CString());
  270. source += IndentLine(line);
  271. }
  272. }
  273. void CSFunctionWriter::WriteManagedPInvokeFunctionSignature(String& source)
  274. {
  275. source += "\n";
  276. // CoreCLR has pinvoke security demand code commented out, so we do not (currently) need this optimization:
  277. // https://github.com/dotnet/coreclr/issues/1605
  278. // line = "[SuppressUnmanagedCodeSecurity]\n";
  279. // source += IndentLine(line);
  280. String line = "[DllImport (Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]\n";
  281. source += IndentLine(line);
  282. JSBClass* klass = function_->GetClass();
  283. JSBPackage* package = klass->GetPackage();
  284. String returnType = CSTypeHelper::GetPInvokeTypeString(function_->GetReturnType());
  285. // handled by out parameter
  286. if (function_->GetReturnType() && function_->GetReturnType()->type_->asVectorType())
  287. returnType = "void";
  288. if (returnType == "bool")
  289. {
  290. // default boolean marshal is 4 byte windows type BOOL and not 1 byte bool
  291. // https://blogs.msdn.microsoft.com/jaredpar/2008/10/14/pinvoke-and-bool-or-should-i-say-bool/
  292. source += IndentLine("[return: MarshalAs(UnmanagedType.I1)]\n");
  293. }
  294. if (returnType == "string")
  295. returnType = "IntPtr";
  296. if (function_->IsConstructor())
  297. returnType = "IntPtr";
  298. Vector<JSBFunctionType*>& parameters = function_->GetParameters();
  299. Vector<String> args;
  300. if (!function_->IsConstructor() && !function_->IsStatic())
  301. {
  302. args.Push("IntPtr self");
  303. }
  304. if (parameters.Size())
  305. {
  306. for (unsigned int i = 0; i < parameters.Size(); i++)
  307. {
  308. JSBFunctionType* ptype = parameters.At(i);
  309. String name = ptype->name_;
  310. if (name == "object")
  311. name = "_object";
  312. else if (name == "readonly")
  313. name = "readOnly";
  314. else if (name == "params")
  315. name = "parameters";
  316. // ignore "Context" parameters
  317. if (ptype->type_->asClassType())
  318. {
  319. JSBClassType* classType = ptype->type_->asClassType();
  320. JSBClass* klass = classType->class_;
  321. if (klass->GetName() == "Context")
  322. {
  323. continue;
  324. }
  325. if (klass->IsNumberArray())
  326. {
  327. args.Push("ref " + klass->GetName() + " " + name);
  328. }
  329. else
  330. {
  331. args.Push("IntPtr " + name);
  332. }
  333. }
  334. else
  335. {
  336. args.Push(CSTypeHelper::GetPInvokeTypeString(ptype) + " " + name);
  337. }
  338. }
  339. }
  340. if (function_->GetReturnClass())
  341. {
  342. JSBClass* retClass = function_->GetReturnClass();
  343. if (retClass->IsNumberArray())
  344. {
  345. args.Push("ref " + retClass->GetName() + " retValue");
  346. }
  347. }
  348. else if (function_->GetReturnType() && function_->GetReturnType()->type_->asVectorType())
  349. {
  350. args.Push("IntPtr returnValue");
  351. }
  352. String pstring;
  353. pstring.Join(args, ", ");
  354. String fname = function_->IsConstructor() ? "Constructor" : function_->GetName();
  355. line = ToString("private static extern %s csb_%s_%s_%s_%u(%s);\n",
  356. returnType.CString(), package->GetName().CString(), klass->GetName().CString(),
  357. fname.CString(), function_->GetID(), pstring.CString());
  358. source += IndentLine(line);
  359. source += "\n";
  360. }
  361. void CSFunctionWriter::GenManagedFunctionParameters(String& sig)
  362. {
  363. // generate args
  364. Vector<JSBFunctionType*>& parameters = function_->GetParameters();
  365. if (parameters.Size())
  366. {
  367. for (unsigned int i = 0; i < parameters.Size(); i++)
  368. {
  369. bool isStruct = false;
  370. JSBFunctionType* ptype = parameters.At(i);
  371. // ignore "Context" parameters
  372. if (ptype->type_->asClassType())
  373. {
  374. JSBClassType* classType = ptype->type_->asClassType();
  375. JSBClass* klass = classType->class_;
  376. if (klass->GetName() == "Context")
  377. {
  378. continue;
  379. }
  380. // TODO: we should have a better system for struct type in general
  381. // This number array is really for JS
  382. if (klass->IsNumberArray())
  383. {
  384. isStruct = true;
  385. }
  386. }
  387. String managedTypeString = CSTypeHelper::GetManagedTypeString(ptype);
  388. if (!ptype->isConst_ && (ptype->isReference_ && isStruct))
  389. {
  390. // pass by reference
  391. managedTypeString = "ref " + managedTypeString;
  392. }
  393. sig += managedTypeString;
  394. String init = ptype->initializer_;
  395. if (init.Length())
  396. {
  397. init = MapDefaultParameter(ptype);
  398. if (init.Length())
  399. sig += " = " + init;
  400. }
  401. if (i + 1 != parameters.Size())
  402. sig += ", ";
  403. }
  404. }
  405. }
  406. void CSFunctionWriter::WriteManagedConstructor(String& source)
  407. {
  408. JSBClass* klass = function_->GetClass();
  409. JSBPackage* package = klass->GetPackage();
  410. if (klass->GetName() == "RefCounted")
  411. return;
  412. // wrapping constructor
  413. String line;
  414. if (!wroteConstructor_)
  415. {
  416. line = ToString("public %s (IntPtr native) : base (native)\n", klass->GetName().CString());
  417. source += IndentLine(line);
  418. source += IndentLine("{\n");
  419. source += IndentLine("}\n\n");
  420. }
  421. // don't add wrapping constructor for overloads
  422. wroteConstructor_ = true;
  423. String sig;
  424. GenManagedFunctionParameters(sig);
  425. line = ToString("public %s (%s)\n", klass->GetName().CString(), sig.CString());
  426. source += IndentLine(line);
  427. source += IndentLine("{\n");
  428. Indent();
  429. WriteDefaultStructParameters(source);
  430. source += IndentLine("if (nativeInstance == IntPtr.Zero)\n");
  431. source += IndentLine("{\n");
  432. Indent();
  433. source += IndentLine(ToString("var classType = typeof(%s);\n", klass->GetName().CString()));
  434. source += IndentLine("var thisType = this.GetType();\n");
  435. source += IndentLine("var thisTypeIsNative = NativeCore.IsNativeType(thisType);\n");
  436. source += IndentLine("var nativeAncsestorType = NativeCore.GetNativeAncestorType(thisType);\n");
  437. source += IndentLine("if ( (thisTypeIsNative && (thisType == classType)) || (!thisTypeIsNative && (nativeAncsestorType == classType)))\n");
  438. source += IndentLine("{\n");
  439. Indent();
  440. String callSig;
  441. GenPInvokeCallParameters(callSig);
  442. source += IndentLine("IntPtr nativeInstanceOverride = NativeCore.NativeContructorOverride;\n");
  443. line = ToString("nativeInstance = NativeCore.RegisterNative (nativeInstanceOverride != IntPtr.Zero ? nativeInstanceOverride : csb_%s_%s_Constructor_%u(%s), this);\n",
  444. package->GetName().CString(), klass->GetName().CString(), function_->GetID(), callSig.CString());
  445. source += IndentLine(line);
  446. Dedent();
  447. source += IndentLine("}\n");
  448. Dedent();
  449. source += IndentLine("}\n");
  450. Dedent();
  451. source += IndentLine("}\n");
  452. }
  453. void CSFunctionWriter::GenPInvokeCallParameters(String& sig)
  454. {
  455. // generate args
  456. Vector<JSBFunctionType*>& parameters = function_->GetParameters();
  457. if (parameters.Size())
  458. {
  459. for (unsigned int i = 0; i < parameters.Size(); i++)
  460. {
  461. JSBFunctionType* ptype = parameters.At(i);
  462. // ignore "Context" parameters
  463. if (ptype->type_->asClassType())
  464. {
  465. JSBClassType* classType = ptype->type_->asClassType();
  466. JSBClass* klass = classType->class_;
  467. if (klass->GetName() == "Context")
  468. {
  469. continue;
  470. }
  471. }
  472. String name = ptype->name_;
  473. if (name == "object")
  474. name = "_object";
  475. else if (name == "readonly")
  476. name = "readOnly";
  477. else if (name == "params")
  478. name = "parameters";
  479. if (ptype->type_->asClassType())
  480. {
  481. JSBClass* pclass = ptype->type_->asClassType()->class_;
  482. if (pclass->IsNumberArray())
  483. {
  484. sig += "ref " + name;
  485. }
  486. else
  487. {
  488. sig += name + " == null ? IntPtr.Zero : " + name + ".nativeInstance";
  489. }
  490. }
  491. else
  492. {
  493. sig += name;
  494. }
  495. if (i + 1 != parameters.Size())
  496. sig += ", ";
  497. }
  498. }
  499. // data marshaller
  500. if (function_->GetReturnType() && !CSTypeHelper::IsSimpleReturn(function_->GetReturnType()))
  501. {
  502. if (function_->GetReturnClass()->IsNumberArray())
  503. {
  504. if (sig.Length())
  505. sig += ", ";
  506. JSBClass* klass = function_->GetClass();
  507. sig += ToString("ref %s%s%uReturnValue", klass->GetName().CString(), function_->GetName().CString(), function_->GetID());
  508. }
  509. }
  510. else if (!function_->IsStatic() && function_->GetReturnType() && function_->GetReturnType()->type_->asVectorType())
  511. {
  512. if (sig.Length())
  513. sig += ", ";
  514. JSBClass* klass = function_->GetClass();
  515. sig += "returnScriptVector";
  516. }
  517. }
  518. void CSFunctionWriter::WriteManagedFunction(String& source)
  519. {
  520. JSBClass* klass = function_->GetClass();
  521. JSBPackage* package = klass->GetPackage();
  522. String sig;
  523. String returnType = CSTypeHelper::GetManagedTypeString(function_->GetReturnType());
  524. GenManagedFunctionParameters(sig);
  525. String line = "public ";
  526. if (function_->IsStatic())
  527. {
  528. line += "static ";
  529. }
  530. bool marked = false;
  531. JSBClass* baseClass = klass->GetBaseClass();
  532. if (baseClass)
  533. {
  534. JSBFunction* override = baseClass->MatchFunction(function_, true);
  535. if (override)
  536. {
  537. marked = true;
  538. if (override->IsVirtual())
  539. line += "override ";
  540. else
  541. line += "new ";
  542. }
  543. }
  544. if (!marked && function_->IsVirtual())
  545. line += "virtual ";
  546. line += ToString("%s %s (%s)\n", returnType.CString(), function_->GetName().CString(), sig.CString());
  547. source += IndentLine(line);
  548. source += IndentLine("{\n");
  549. Indent();
  550. WriteDefaultStructParameters(source);
  551. line.Clear();
  552. if (function_->GetReturnType())
  553. {
  554. if (function_->GetReturnType()->type_->asStringType() || function_->GetReturnType()->type_->asStringHashType())
  555. {
  556. line += "return System.Runtime.InteropServices.Marshal.PtrToStringAnsi(";
  557. }
  558. else if (function_->GetReturnType()->type_->asVectorType())
  559. {
  560. source += IndentLine(ToString("var returnScriptVector = %s%s%uReturnValue.GetScriptVector();\n", klass->GetName().CString(), function_->GetName().CString(), function_->GetID()));
  561. }
  562. else if (CSTypeHelper::IsSimpleReturn(function_->GetReturnType()))
  563. line += "return ";
  564. else
  565. {
  566. if (function_->GetReturnClass())
  567. {
  568. if (!function_->GetReturnClass()->IsNumberArray())
  569. line += "IntPtr retNativeInstance = ";
  570. }
  571. }
  572. }
  573. String callSig;
  574. GenPInvokeCallParameters(callSig);
  575. String nativeInstance;
  576. if (!function_->IsStatic())
  577. nativeInstance = "nativeInstance";
  578. line += ToString("csb_%s_%s_%s_%u(%s",
  579. package->GetName().CString(), klass->GetName().CString(), function_->GetName().CString(), function_->GetID(), nativeInstance.CString());
  580. if (callSig.Length())
  581. {
  582. if (nativeInstance.Length())
  583. line += ", " + callSig;
  584. else
  585. line += callSig;
  586. }
  587. if (function_->GetReturnType())
  588. {
  589. if (function_->GetReturnType()->type_->asStringType() || function_->GetReturnType()->type_->asStringHashType())
  590. line += ")";
  591. }
  592. line += ");\n";
  593. source += IndentLine(line);
  594. if (function_->GetReturnType() && !CSTypeHelper::IsSimpleReturn(function_->GetReturnType()))
  595. {
  596. if (function_->GetReturnType()->type_->asClassType())
  597. {
  598. JSBClass* retClass = function_->GetReturnClass();
  599. JSBClass* klass = function_->GetClass();
  600. if (retClass->IsNumberArray())
  601. {
  602. line = ToString("return %s%s%uReturnValue;", klass->GetName().CString(), function_->GetName().CString(), function_->GetID());
  603. }
  604. else
  605. {
  606. line = ToString("return retNativeInstance == IntPtr.Zero ? null : NativeCore.WrapNative<%s> (retNativeInstance);", retClass->GetName().CString());
  607. }
  608. source += IndentLine(line);
  609. source+= "\n";
  610. }
  611. }
  612. else if (function_->GetReturnType() && function_->GetReturnType()->type_->asVectorType())
  613. {
  614. if (!function_->IsStatic())
  615. {
  616. source += IndentLine(ToString("return %s%s%uReturnValue;", klass->GetName().CString(), function_->GetName().CString(), function_->GetID()));
  617. source+= "\n";
  618. }
  619. }
  620. Dedent();
  621. source += IndentLine("}\n");
  622. }
  623. void CSFunctionWriter::GenerateManagedSource(String& sourceOut)
  624. {
  625. String source = "";
  626. Indent();
  627. Indent();
  628. if (function_->GetDocString().Length())
  629. {
  630. // monodocer -assembly:NETCore.dll -path:en -pretty
  631. // mdoc export-html -o htmldocs en
  632. source += IndentLine("/// <summary>\n");
  633. if (function_->GetDocString().Contains('\n'))
  634. source += IndentLine("/* " + function_->GetDocString() + "*/\n");
  635. else
  636. source += IndentLine("/// " + function_->GetDocString() + "\n");
  637. source += IndentLine("/// </summary>\n");
  638. }
  639. if (function_->IsConstructor())
  640. WriteManagedConstructor(source);
  641. else
  642. WriteManagedFunction(source);
  643. WriteManagedPInvokeFunctionSignature(source);
  644. // data marshaller
  645. if (function_->GetReturnType() && !CSTypeHelper::IsSimpleReturn(function_->GetReturnType()))
  646. {
  647. if (function_->GetReturnClass())
  648. {
  649. JSBClass* retClass = function_->GetReturnClass();
  650. if (retClass->IsNumberArray())
  651. {
  652. JSBClass* klass = function_->GetClass();
  653. String managedType = CSTypeHelper::GetManagedTypeString(function_->GetReturnType());
  654. String marshal = "private ";
  655. if (function_->IsStatic())
  656. marshal += "static ";
  657. marshal += managedType + " ";
  658. marshal += ToString("%s%s%uReturnValue = new %s();\n", klass->GetName().CString(), function_->GetName().CString(), function_->GetID(), managedType.CString());
  659. sourceOut += IndentLine(marshal);
  660. }
  661. }
  662. }
  663. else if (!function_->IsStatic() && function_->GetReturnType() && function_->GetReturnType()->type_->asVectorType())
  664. {
  665. JSBVectorType* vtype = function_->GetReturnType()->type_->asVectorType();
  666. if (vtype->vectorType_->asClassType())
  667. {
  668. String classname = vtype->vectorType_->asClassType()->class_->GetName();
  669. String typestring = "Vector<" + classname + ">";
  670. String marshal = "private " + typestring + " ";
  671. marshal += ToString("%s%s%uReturnValue = new %s();\n", function_->GetClass()->GetName().CString(), function_->GetName().CString(), function_->GetID(), typestring.CString());
  672. sourceOut += IndentLine(marshal);
  673. }
  674. }
  675. Dedent();
  676. Dedent();
  677. sourceOut += source;
  678. }
  679. void CSFunctionWriter::GenerateSource(String& sourceOut)
  680. {
  681. }
  682. String CSFunctionWriter::MapDefaultParameter(JSBFunctionType* parameter)
  683. {
  684. String init = parameter->initializer_;
  685. if (!init.Length())
  686. return init;
  687. if (parameter->type_->asClassType())
  688. {
  689. if (init == "0")
  690. return "null";
  691. }
  692. if (parameter->type_->asEnumType())
  693. {
  694. return parameter->type_->asEnumType()->enum_->GetName() + "." + init;
  695. }
  696. if (function_->class_->GetPackage()->ContainsConstant(init))
  697. return "Constants." + init;
  698. if (init == "true" || init == "false")
  699. return init;
  700. if (init == "0.0f")
  701. return init;
  702. if (init == "1.0f")
  703. return init;
  704. if (init == "0.1f")
  705. return init;
  706. if (init == "0")
  707. return init;
  708. if (init == "3")
  709. return init;
  710. if (init == "-1")
  711. return init;
  712. if (init == "\"\\t\"")
  713. return init;
  714. if (init == "NULL")
  715. return "null";
  716. if (init == "M_MAX_UNSIGNED")
  717. return "0xffffffff";
  718. if (init == "String::EMPTY")
  719. return "\"\"";
  720. // this kind of sucks, can't define const structs
  721. // and default parameters need to be const :/
  722. DefaultStructParameter dparm;
  723. dparm.parameterName = parameter->name_;
  724. if (init == "Vector3::ZERO")
  725. {
  726. dparm.type = "Vector3";
  727. dparm.assignment = "Vector3.Zero";
  728. defaultStructParameters_.Push(dparm);
  729. return "default(Vector3)";
  730. }
  731. if (init == "Vector3::ONE")
  732. {
  733. dparm.type = "Vector3";
  734. dparm.assignment = "Vector3.One";
  735. defaultStructParameters_.Push(dparm);
  736. return "default(Vector3)";
  737. }
  738. if (init == "Vector3::UP")
  739. {
  740. dparm.type = "Vector3";
  741. dparm.assignment = "Vector3.Up";
  742. defaultStructParameters_.Push(dparm);
  743. return "default(Vector3)";
  744. }
  745. if (init == "IntVector2::ZERO")
  746. {
  747. dparm.type = "IntVector2";
  748. dparm.assignment = "IntVector2.Zero";
  749. defaultStructParameters_.Push(dparm);
  750. return "default(IntVector2)";
  751. }
  752. if (init == "Quaternion::IDENTITY")
  753. {
  754. dparm.type = "Quaternion";
  755. dparm.assignment = "Quaternion.Identity";
  756. defaultStructParameters_.Push(dparm);
  757. return "default(Quaternion)";
  758. }
  759. return String::EMPTY;
  760. }
  761. }