CSFunctionWriter.cpp 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112
  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. JSBVectorType* vtype = function_->GetReturnType()->type_->asVectorType();
  634. String marshalName = ToString("%s%s%uReturnValue", function_->GetClass()->GetName().CString(), function_->GetName().CString(), function_->GetID());
  635. // Defer creation of ScriptVector return value until method is called
  636. if (vtype->vectorType_->asClassType())
  637. {
  638. String classname = vtype->vectorType_->asClassType()->class_->GetName();
  639. source += IndentLine(ToString("if (%s == null) %s = new Vector<%s>();\n", marshalName.CString(), marshalName.CString(), classname.CString()));
  640. }
  641. source += IndentLine(ToString("var returnScriptVector = %s.GetScriptVector();\n", marshalName.CString()));
  642. }
  643. else if (CSTypeHelper::IsSimpleReturn(function_->GetReturnType()))
  644. line += "return ";
  645. else
  646. {
  647. if (function_->GetReturnClass())
  648. {
  649. if (!function_->GetReturnClass()->IsNumberArray())
  650. line += "IntPtr retNativeInstance = ";
  651. }
  652. }
  653. }
  654. String callSig;
  655. GenPInvokeCallParameters(callSig);
  656. String nativeInstance;
  657. if (!function_->IsStatic())
  658. nativeInstance = "nativeInstance";
  659. line += ToString("csb_%s_%s_%s_%u(%s",
  660. package->GetName().CString(), klass->GetName().CString(), function_->GetName().CString(), function_->GetID(), nativeInstance.CString());
  661. if (callSig.Length())
  662. {
  663. if (nativeInstance.Length())
  664. line += ", " + callSig;
  665. else
  666. line += callSig;
  667. }
  668. if (function_->GetReturnType())
  669. {
  670. if (function_->GetReturnType()->type_->asStringType())
  671. line += ")";
  672. }
  673. line += ");\n";
  674. source += IndentLine(line);
  675. if (function_->GetReturnType() && !CSTypeHelper::IsSimpleReturn(function_->GetReturnType()))
  676. {
  677. if (function_->GetReturnType()->type_->asClassType())
  678. {
  679. JSBClass* retClass = function_->GetReturnClass();
  680. JSBClass* klass = function_->GetClass();
  681. if (retClass->IsNumberArray())
  682. {
  683. line = ToString("return %s%s%uReturnValue;", klass->GetName().CString(), function_->GetName().CString(), function_->GetID());
  684. }
  685. else
  686. {
  687. line = ToString("return retNativeInstance == IntPtr.Zero ? null : NativeCore.WrapNative<%s> (retNativeInstance);", retClass->GetName().CString());
  688. }
  689. source += IndentLine(line);
  690. source+= "\n";
  691. }
  692. }
  693. else if (function_->GetReturnType() && function_->GetReturnType()->type_->asVectorType())
  694. {
  695. if (!function_->IsStatic())
  696. {
  697. source += IndentLine(ToString("return %s%s%uReturnValue;", klass->GetName().CString(), function_->GetName().CString(), function_->GetID()));
  698. source+= "\n";
  699. }
  700. }
  701. Dedent();
  702. source += IndentLine("}\n");
  703. }
  704. void CSFunctionWriter::GenerateManagedSource(String& sourceOut)
  705. {
  706. JSBClass* klass = function_->GetClass();
  707. String source = "";
  708. Indent();
  709. Indent();
  710. if (function_->GetDocString().Length())
  711. {
  712. // monodocer -assembly:NETCore.dll -path:en -pretty
  713. // mdoc export-html -o htmldocs en
  714. source += IndentLine("/// <summary>\n");
  715. if (function_->GetDocString().Contains('\n'))
  716. source += IndentLine("/* " + function_->GetDocString() + "*/\n");
  717. else
  718. source += IndentLine("/// " + function_->GetDocString() + "\n");
  719. source += IndentLine("/// </summary>\n");
  720. }
  721. if (function_->IsConstructor())
  722. WriteManagedConstructor(source);
  723. else
  724. WriteManagedFunction(source);
  725. WriteManagedPInvokeFunctionSignature(source);
  726. if (!klass->IsInterface())
  727. {
  728. // data marshaller
  729. if (function_->GetReturnType() && !CSTypeHelper::IsSimpleReturn(function_->GetReturnType()))
  730. {
  731. if (function_->GetReturnClass())
  732. {
  733. JSBClass* retClass = function_->GetReturnClass();
  734. if (retClass->IsNumberArray())
  735. {
  736. String managedType = CSTypeHelper::GetManagedTypeString(function_->GetReturnType());
  737. String marshal = "private ";
  738. if (function_->IsStatic())
  739. marshal += "static ";
  740. marshal += managedType + " ";
  741. marshal += ToString("%s%s%uReturnValue;\n", klass->GetName().CString(), function_->GetName().CString(), function_->GetID());
  742. sourceOut += IndentLine(marshal);
  743. }
  744. }
  745. }
  746. else if (!function_->IsStatic() && function_->GetReturnType() && function_->GetReturnType()->type_->asVectorType())
  747. {
  748. JSBVectorType* vtype = function_->GetReturnType()->type_->asVectorType();
  749. if (vtype->vectorType_->asClassType())
  750. {
  751. String classname = vtype->vectorType_->asClassType()->class_->GetName();
  752. String typestring = "Vector<" + classname + ">";
  753. String marshal = "private " + typestring + " ";
  754. marshal += ToString("%s%s%uReturnValue = null;\n", function_->GetClass()->GetName().CString(), function_->GetName().CString(), function_->GetID());
  755. sourceOut += IndentLine(marshal);
  756. }
  757. }
  758. }
  759. Dedent();
  760. Dedent();
  761. sourceOut += source;
  762. }
  763. void CSFunctionWriter::GenerateSource(String& sourceOut)
  764. {
  765. }
  766. String CSFunctionWriter::MapDefaultParameter(JSBFunctionType* parameter)
  767. {
  768. String init = parameter->initializer_;
  769. if (!init.Length())
  770. return init;
  771. if (parameter->type_->asClassType())
  772. {
  773. if (init == "0")
  774. return "null";
  775. }
  776. if (parameter->type_->asEnumType())
  777. {
  778. return parameter->type_->asEnumType()->enum_->GetName() + "." + init;
  779. }
  780. if (function_->class_->GetPackage()->ContainsConstant(init))
  781. return "Constants." + init;
  782. if (init == "true" || init == "false")
  783. return init;
  784. if (init == "0.0f")
  785. return init;
  786. if (init == "1.0f")
  787. return init;
  788. if (init == "0.1f")
  789. return init;
  790. if (init == "0")
  791. return init;
  792. if (init == "3")
  793. return init;
  794. if (init == "-1")
  795. return init;
  796. if (init == "\"\\t\"")
  797. return init;
  798. if (init == "NULL")
  799. return "null";
  800. if (init == "M_MAX_UNSIGNED")
  801. return "0xffffffff";
  802. if (init == "String::EMPTY")
  803. return "\"\"";
  804. // this kind of sucks, can't define const structs
  805. // and default parameters need to be const :/
  806. DefaultStructParameter dparm;
  807. dparm.parameterName = parameter->name_;
  808. if (init == "Vector3::ZERO")
  809. {
  810. dparm.type = "Vector3";
  811. dparm.assignment = "Vector3.Zero";
  812. defaultStructParameters_.Push(dparm);
  813. return "default(Vector3)";
  814. }
  815. if (init == "Vector3::ONE")
  816. {
  817. dparm.type = "Vector3";
  818. dparm.assignment = "Vector3.One";
  819. defaultStructParameters_.Push(dparm);
  820. return "default(Vector3)";
  821. }
  822. if (init == "Vector3::UP")
  823. {
  824. dparm.type = "Vector3";
  825. dparm.assignment = "Vector3.Up";
  826. defaultStructParameters_.Push(dparm);
  827. return "default(Vector3)";
  828. }
  829. if (init == "IntVector2::ZERO")
  830. {
  831. dparm.type = "IntVector2";
  832. dparm.assignment = "IntVector2.Zero";
  833. defaultStructParameters_.Push(dparm);
  834. return "default(IntVector2)";
  835. }
  836. if (init == "Quaternion::IDENTITY")
  837. {
  838. dparm.type = "Quaternion";
  839. dparm.assignment = "Quaternion.Identity";
  840. defaultStructParameters_.Push(dparm);
  841. return "default(Quaternion)";
  842. }
  843. if (init == "StringHash::ZERO")
  844. {
  845. dparm.type = "StringHash";
  846. dparm.assignment = "StringHash.Zero";
  847. defaultStructParameters_.Push(dparm);
  848. return "default(StringHash)";
  849. }
  850. return String::EMPTY;
  851. }
  852. }