CSFunctionWriter.cpp 29 KB

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