ASUtils.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786
  1. //
  2. // Copyright (c) 2008-2020 the Urho3D project.
  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 "ASUtils.h"
  23. #include "Tuning.h"
  24. #include "Utils.h"
  25. #include "XmlAnalyzer.h"
  26. #include "XmlSourceData.h"
  27. #include <cassert>
  28. #include <regex>
  29. namespace ASBindingGenerator
  30. {
  31. // https://www.angelcode.com/angelscript/sdk/docs/manual/doc_datatypes_primitives.html
  32. string CppFundamentalTypeToAS(const string& cppType)
  33. {
  34. if (cppType == "char" || cppType == "signed char")
  35. return "int8";
  36. if (cppType == "unsigned char")
  37. return "uint8";
  38. if (cppType == "short")
  39. return "int16";
  40. if (cppType == "unsigned short")
  41. return "uint16";
  42. if (cppType == "int" || cppType == "long")
  43. return "int";
  44. if (cppType == "unsigned" || cppType == "unsigned int" || cppType == "unsigned long")
  45. return "uint";
  46. if (cppType == "long long")
  47. return "int64";
  48. if (cppType == "unsigned long long")
  49. return "uint64";
  50. return cppType;
  51. }
  52. shared_ptr<EnumAnalyzer> FindEnum(const string& name)
  53. {
  54. NamespaceAnalyzer namespaceAnalyzer(SourceData::namespaceUrho3D_);
  55. vector<EnumAnalyzer> enumAnalyzers = namespaceAnalyzer.GetEnums();
  56. for (EnumAnalyzer enumAnalyzer : enumAnalyzers)
  57. {
  58. if (enumAnalyzer.GetTypeName() == name)
  59. return make_shared<EnumAnalyzer>(enumAnalyzer);
  60. }
  61. return shared_ptr<EnumAnalyzer>();
  62. }
  63. static bool IsUsing(const string& identifier)
  64. {
  65. for (xml_node memberdef : SourceData::usings_)
  66. {
  67. UsingAnalyzer usingAnalyzer(memberdef);
  68. if (usingAnalyzer.GetIdentifier() == identifier)
  69. return true;
  70. }
  71. return false;
  72. }
  73. bool IsKnownType(const string& name)
  74. {
  75. static vector<string> _knownTypes = {
  76. "", // TODO: fix opConv()
  77. "void",
  78. "bool",
  79. "size_t",
  80. "char",
  81. "signed char",
  82. "unsigned char",
  83. "short",
  84. "unsigned short",
  85. "int",
  86. "long",
  87. "unsigned",
  88. "unsigned int",
  89. "unsigned long",
  90. "long long",
  91. "unsigned long long",
  92. "float",
  93. "double",
  94. "SDL_JoystickID",
  95. // TODO: Remove
  96. "VariantMap",
  97. };
  98. if (CONTAINS(_knownTypes, name))
  99. return true;
  100. if (SourceData::classesByName_.find(name) != SourceData::classesByName_.end())
  101. return true;
  102. if (SourceData::enums_.find(name) != SourceData::enums_.end())
  103. return true;
  104. if (EndsWith(name, "Flags"))
  105. return true;
  106. return false;
  107. }
  108. shared_ptr<ClassAnalyzer> FindClassByName(const string& name)
  109. {
  110. auto it = SourceData::classesByName_.find(name);
  111. if (it != SourceData::classesByName_.end())
  112. {
  113. xml_node compounddef = it->second;
  114. return make_shared<ClassAnalyzer>(compounddef);
  115. }
  116. // using VariantVector = Vector<Variant>
  117. return shared_ptr<ClassAnalyzer>();
  118. }
  119. shared_ptr<ClassAnalyzer> FindClassByID(const string& id)
  120. {
  121. auto it = SourceData::classesByID_.find(id);
  122. if (it != SourceData::classesByID_.end())
  123. {
  124. xml_node compounddef = it->second;
  125. return make_shared<ClassAnalyzer>(compounddef);
  126. }
  127. // using VariantVector = Vector<Variant>
  128. return shared_ptr<ClassAnalyzer>();
  129. }
  130. string CppTypeToAS(const TypeAnalyzer& type, bool returnType, bool& outSuccess)
  131. {
  132. if (type.IsRvalueReference() || type.IsDoublePointer() || type.IsRefToPointer())
  133. {
  134. outSuccess = false;
  135. SetLastErrorMessage("Error: type \"" + type.ToString() + "\" can not automatically bind");
  136. return "ERROR";
  137. }
  138. string cppTypeName = type.GetNameWithTemplateParams();
  139. if (cppTypeName == "Context" && returnType)
  140. {
  141. outSuccess = false;
  142. SetLastErrorMessage("Error: type \"" + type.ToString() + "\" can not be returned");
  143. return "ERROR";
  144. }
  145. if (!IsKnownType(type.GetNameWithTemplateParams()))
  146. {
  147. outSuccess = false;
  148. SetLastErrorMessage("Error: type \"" + type.ToString() + "\" can not automatically bind");
  149. return "ERROR";
  150. }
  151. shared_ptr<ClassAnalyzer> analyzer = FindClassByName(type.GetNameWithTemplateParams());
  152. if (analyzer && analyzer->IsInternal())
  153. {
  154. outSuccess = false;
  155. SetLastErrorMessage("Error: type \"" + type.ToString() + "\" can not automatically bind bacause internal");
  156. return "ERROR";
  157. }
  158. if (analyzer && Contains(analyzer->GetComment(), "NO_BIND"))
  159. {
  160. outSuccess = false;
  161. SetLastErrorMessage("Error: type \"" + cppTypeName + "\" can not automatically bind bacause have @nobind mark");
  162. return "ERROR";
  163. }
  164. // analyzer can be null for simple types (int, float) or if type "using VariantVector = Vector<Variant>"
  165. // TODO add to type info "IsUsing"
  166. // TODO add description to TypeAnalyzer::GetClass()
  167. if (IsUsing(cppTypeName) && cppTypeName != "VariantMap")
  168. {
  169. outSuccess = false;
  170. SetLastErrorMessage("Error: using \"" + cppTypeName + "\" can not automatically bind");
  171. return "ERROR";
  172. }
  173. string asTypeName = CppFundamentalTypeToAS(cppTypeName);
  174. if (asTypeName == "void" && type.IsPointer())
  175. {
  176. outSuccess = false;
  177. SetLastErrorMessage("Error: type \"void*\" can not automatically bind");
  178. return "ERROR";
  179. }
  180. if (asTypeName.find('<') != string::npos)
  181. {
  182. outSuccess = false;
  183. SetLastErrorMessage("Error: type \"" + type.ToString() + "\" can not automatically bind");
  184. return "ERROR";
  185. }
  186. if (Contains(type.ToString(), "::"))
  187. {
  188. outSuccess = false;
  189. SetLastErrorMessage("Error: type \"" + type.ToString() + "\" can not automatically bind bacause internal");
  190. return "ERROR";
  191. }
  192. if (type.IsConst() && type.IsReference() && !returnType)
  193. {
  194. outSuccess = true;
  195. return "const " + CppFundamentalTypeToAS(cppTypeName) + "&in";
  196. }
  197. string result = CppFundamentalTypeToAS(cppTypeName);
  198. if (type.IsReference())
  199. {
  200. result += "&";
  201. }
  202. else if (type.IsPointer())
  203. {
  204. shared_ptr<ClassAnalyzer> analyzer = FindClassByName(type.GetNameWithTemplateParams());
  205. if (analyzer && (analyzer->IsRefCounted() || Contains(analyzer->GetComment(), "FAKE_REF")))
  206. {
  207. result += "@+";
  208. }
  209. else
  210. {
  211. outSuccess = false;
  212. SetLastErrorMessage("Error: type \"" + type.ToString() + "\" can not automatically bind");
  213. return "ERROR";
  214. }
  215. }
  216. if (returnType && type.IsConst() && !type.IsPointer())
  217. result = "const " + result;
  218. outSuccess = true;
  219. return result;
  220. }
  221. string CppValueToAS(const string& cppValue)
  222. {
  223. if (cppValue == "nullptr")
  224. return "null";
  225. if (cppValue == "Variant::emptyVariantMap")
  226. return "VariantMap()";
  227. if (cppValue == "NPOS")
  228. return "String::NPOS";
  229. return cppValue;
  230. }
  231. // =================================================================================
  232. shared_ptr<FuncParamConv> CppFunctionParamToAS(int paramIndex, ParamAnalyzer& paramAnalyzer)
  233. {
  234. shared_ptr<FuncParamConv> result = make_shared<FuncParamConv>();
  235. TypeAnalyzer typeAnalyzer = paramAnalyzer.GetType();
  236. string cppTypeName = typeAnalyzer.GetNameWithTemplateParams();
  237. if (cppTypeName == "Context")
  238. {
  239. result->errorMessage_ = "Context can be used as firs parameter of constructors only";
  240. return result;
  241. }
  242. if (cppTypeName == "Vector<String>" && typeAnalyzer.IsConst() && typeAnalyzer.IsReference())
  243. {
  244. result->success_ = true;
  245. result->inputVarName_ = paramAnalyzer.GetDeclname();
  246. result->convertedVarName_ = "param" + to_string(paramIndex);
  247. result->glue_ = " Vector<String> " + result->convertedVarName_ + " = ArrayToVector<String>(" + result->inputVarName_ + ");\n";
  248. result->cppType_ = "CScriptArray*";
  249. //result->asDecl_ = "String[]&";
  250. result->asDecl_ = "Array<String>@+";
  251. string defval = paramAnalyzer.GetDefval();
  252. if (!defval.empty())
  253. {
  254. assert(defval == "Vector< String >()");
  255. //result->asDecl_ += " = Array<String>()";
  256. result->asDecl_ += " = null";
  257. }
  258. return result;
  259. }
  260. smatch match;
  261. regex_match(cppTypeName, match, regex("PODVector<(\\w+)>"));
  262. if (match.size() == 2 && typeAnalyzer.IsConst() && typeAnalyzer.IsReference())
  263. {
  264. string cppTypeName = match[1].str();
  265. string asTypeName = CppFundamentalTypeToAS(cppTypeName);
  266. result->success_ = true;
  267. result->inputVarName_ = paramAnalyzer.GetDeclname();
  268. result->convertedVarName_ = "param" + to_string(paramIndex);
  269. result->glue_ = " PODVector<" + cppTypeName + "> " + result->convertedVarName_ + " = ArrayToPODVector<" + cppTypeName + ">(" + result->inputVarName_ + ");\n";
  270. result->cppType_ = "CScriptArray*";
  271. result->asDecl_ = "Array<" + asTypeName + ">@+";
  272. string defval = paramAnalyzer.GetDefval();
  273. assert(defval.empty()); // TODO: make
  274. return result;
  275. }
  276. regex_match(cppTypeName, match, regex("PODVector<(\\w+)\\*>"));
  277. // TODO check \\w is refcounted
  278. if (match.size() == 2 && typeAnalyzer.IsConst() && typeAnalyzer.IsReference())
  279. {
  280. string cppTypeName = match[1].str();
  281. string asTypeName = CppFundamentalTypeToAS(cppTypeName);
  282. result->success_ = true;
  283. result->inputVarName_ = paramAnalyzer.GetDeclname();
  284. result->convertedVarName_ = "param" + to_string(paramIndex);
  285. result->glue_ = " PODVector<" + cppTypeName + "*> " + result->convertedVarName_ + " = ArrayToPODVector<" + cppTypeName + "*>(" + result->inputVarName_ + ");\n";
  286. result->cppType_ = "CScriptArray*";
  287. result->asDecl_ = "Array<" + asTypeName + "@>@";
  288. string defval = paramAnalyzer.GetDefval();
  289. assert(defval.empty()); // TODO: make
  290. return result;
  291. }
  292. regex_match(cppTypeName, match, regex("Vector<SharedPtr<(\\w+)>>"));
  293. if (match.size() == 2 && typeAnalyzer.IsConst() && typeAnalyzer.IsReference())
  294. {
  295. string cppTypeName = match[1].str();
  296. string asTypeName = CppFundamentalTypeToAS(cppTypeName);
  297. if (cppTypeName == "WorkItem") // TODO autodetect
  298. {
  299. result->errorMessage_ = "TODO";
  300. return result;
  301. }
  302. result->success_ = true;
  303. result->inputVarName_ = paramAnalyzer.GetDeclname();
  304. result->convertedVarName_ = "param" + to_string(paramIndex);
  305. result->glue_ = " Vector<SharedPtr<" + cppTypeName + "> > " + result->convertedVarName_ + " = HandleArrayToVector<" + cppTypeName + ">(" + result->inputVarName_ + ");\n";
  306. result->cppType_ = "CScriptArray*";
  307. result->asDecl_ = "Array<" + asTypeName + "@>@+";
  308. string defval = paramAnalyzer.GetDefval();
  309. assert(defval.empty()); // TODO: make
  310. return result;
  311. }
  312. bool outSuccess;
  313. string asType = CppTypeToAS(typeAnalyzer, false, outSuccess);
  314. if (!outSuccess)
  315. {
  316. result->errorMessage_ = GetLastErrorMessage();
  317. return result;
  318. }
  319. result->asDecl_ = asType;
  320. string defval = paramAnalyzer.GetDefval();
  321. if (!defval.empty())
  322. {
  323. defval = CppValueToAS(defval);
  324. defval = ReplaceAll(defval, "\"", "\\\"");
  325. result->asDecl_ += " = " + defval;
  326. }
  327. result->success_ = true;
  328. result->cppType_ = typeAnalyzer.ToString();
  329. result->inputVarName_ = paramAnalyzer.GetDeclname();
  330. result->convertedVarName_ = result->inputVarName_;
  331. return result;
  332. }
  333. shared_ptr<FuncReturnTypeConv> CppFunctionReturnTypeToAS(const TypeAnalyzer& typeAnalyzer)
  334. {
  335. shared_ptr<FuncReturnTypeConv> result = make_shared<FuncReturnTypeConv>();
  336. string cppTypeName = typeAnalyzer.GetNameWithTemplateParams();
  337. if (cppTypeName == "void" && !typeAnalyzer.IsPointer())
  338. {
  339. result->success_ = true;
  340. result->asReturnType_ = "void";
  341. result->glueReturnType_ = "void";
  342. result->glueReturn_ = "";
  343. return result;
  344. }
  345. if (cppTypeName == "Context")
  346. {
  347. result->errorMessage_ = "Error: type \"" + typeAnalyzer.ToString() + "\" can not be returned";
  348. return result;
  349. }
  350. // Works with both Vector<String> and Vector<String>&
  351. if ((cppTypeName == "Vector<String>" || cppTypeName == "StringVector") && !typeAnalyzer.IsPointer())
  352. {
  353. result->success_ = true;
  354. result->needWrapper_ = true;
  355. result->asReturnType_ = "Array<String>@";
  356. result->glueReturnType_ = "CScriptArray*";
  357. result->glueReturn_ = "return VectorToArray<String>(result, \"Array<String>\");\n";
  358. return result;
  359. }
  360. smatch match;
  361. regex_match(cppTypeName, match, regex("SharedPtr<(\\w+)>"));
  362. if (match.size() == 2)
  363. {
  364. string typeName = match[1].str();
  365. typeName = CppFundamentalTypeToAS(typeName);
  366. if (typeName == "WorkItem") // TODO autodetect
  367. {
  368. result->errorMessage_ = "TODO";
  369. return result;
  370. }
  371. result->success_ = true;
  372. result->needWrapper_ = true;
  373. result->asReturnType_ = typeName + "@+";
  374. result->glueReturnType_ = typeName + "*";
  375. result->glueReturn_ = "return result.Detach();\n";
  376. return result;
  377. }
  378. regex_match(cppTypeName, match, regex("Vector<SharedPtr<(\\w+)>>"));
  379. if (match.size() == 2)
  380. {
  381. string typeName = match[1].str();
  382. typeName = CppFundamentalTypeToAS(typeName);
  383. result->success_ = true;
  384. result->needWrapper_ = true;
  385. result->asReturnType_ = "Array<" + typeName + "@>@";
  386. result->glueReturnType_ = "CScriptArray*";
  387. // Which variant is correct/better?
  388. #if 0
  389. result->glueResult_ = "return VectorToArray<SharedPtr<" + typeName + "> >(result, \"Array<" + typeName + "@>@\");\n";
  390. #else
  391. result->glueReturn_ = "return VectorToHandleArray(result, \"Array<" + typeName + "@>\");\n";
  392. #endif
  393. return result;
  394. }
  395. regex_match(cppTypeName, match, regex("PODVector<(\\w+)\\*>"));
  396. if (match.size() == 2)
  397. {
  398. string typeName = match[1].str();
  399. typeName = CppFundamentalTypeToAS(typeName);
  400. result->success_ = true;
  401. result->needWrapper_ = true;
  402. result->asReturnType_ = "Array<" + typeName + "@>@";
  403. result->glueReturnType_ = "CScriptArray*";
  404. result->glueReturn_ = "return VectorToHandleArray(result, \"Array<" + typeName + "@>\");\n";
  405. return result;
  406. }
  407. regex_match(cppTypeName, match, regex("PODVector<(\\w+)>"));
  408. if (match.size() == 2 && (typeAnalyzer.IsConst() == typeAnalyzer.IsReference()))
  409. {
  410. string typeName = match[1].str();
  411. typeName = CppFundamentalTypeToAS(typeName);
  412. result->success_ = true;
  413. result->needWrapper_ = true;
  414. result->asReturnType_ = "Array<" + typeName + ">@";
  415. result->glueReturnType_ = "CScriptArray*";
  416. result->glueReturn_ = "return VectorToArray(result, \"Array<" + typeName + ">\");\n";
  417. return result;
  418. }
  419. bool outSuccess;
  420. string asType = CppTypeToAS(typeAnalyzer, true, outSuccess);
  421. if (!outSuccess)
  422. {
  423. result->errorMessage_ = GetLastErrorMessage();
  424. return result;
  425. }
  426. result->success_ = true;
  427. result->asReturnType_ = asType;
  428. result->glueReturn_ = "return result;\n";
  429. result->glueReturnType_ = typeAnalyzer.ToString();
  430. return result;
  431. }
  432. // =================================================================================
  433. static string GenerateFunctionWrapperName(xml_node memberdef)
  434. {
  435. string result = ExtractName(memberdef);
  436. result = ReplaceFirst(result, "~", "Destructor_");
  437. vector<ParamAnalyzer> params = ExtractParams(memberdef);
  438. if (params.size() == 0)
  439. {
  440. result += "_void";
  441. }
  442. else
  443. {
  444. for (ParamAnalyzer param : params)
  445. {
  446. string t = param.GetType().GetNameWithTemplateParams();
  447. t = ReplaceAll(t, " ", "");
  448. t = ReplaceAll(t, "::", "");
  449. t = ReplaceAll(t, "<", "");
  450. t = ReplaceAll(t, ">", "");
  451. t = ReplaceAll(t, "*", "");
  452. result += "_" + t;
  453. }
  454. }
  455. return result;
  456. }
  457. string GenerateWrapperName(const GlobalFunctionAnalyzer& functionAnalyzer)
  458. {
  459. return GenerateFunctionWrapperName(functionAnalyzer.GetMemberdef());
  460. }
  461. string GenerateWrapperName(const ClassStaticFunctionAnalyzer& functionAnalyzer)
  462. {
  463. return functionAnalyzer.GetClassName() + "_" + GenerateFunctionWrapperName(functionAnalyzer.GetMemberdef());
  464. }
  465. string GenerateWrapperName(const ClassFunctionAnalyzer& functionAnalyzer, bool templateVersion)
  466. {
  467. if (templateVersion)
  468. return functionAnalyzer.GetClassName() + "_" + GenerateFunctionWrapperName(functionAnalyzer.GetMemberdef()) + "_template";
  469. else
  470. return functionAnalyzer.GetClassName() + "_" + GenerateFunctionWrapperName(functionAnalyzer.GetMemberdef());
  471. }
  472. // =================================================================================
  473. string GenerateWrapper(const GlobalFunctionAnalyzer& functionAnalyzer, vector<shared_ptr<FuncParamConv> >& convertedParams, shared_ptr<FuncReturnTypeConv> convertedReturn)
  474. {
  475. string result;
  476. string insideDefine = InsideDefine(functionAnalyzer.GetHeaderFile());
  477. if (!insideDefine.empty())
  478. result += "#ifdef " + insideDefine + "\n";
  479. result +=
  480. "// " + functionAnalyzer.GetLocation() + "\n"
  481. "static " + convertedReturn->glueReturnType_ + " " + GenerateWrapperName(functionAnalyzer) + "(";
  482. for (size_t i = 0; i < convertedParams.size(); i++)
  483. {
  484. if (i != 0)
  485. result += ", ";
  486. result += convertedParams[i]->cppType_ + " " + convertedParams[i]->inputVarName_;
  487. }
  488. result +=
  489. ")\n"
  490. "{\n";
  491. for (size_t i = 0; i < convertedParams.size(); i++)
  492. result += convertedParams[i]->glue_;
  493. if (convertedReturn->glueReturnType_ != "void")
  494. result += " " + functionAnalyzer.GetReturnType().ToString() + " result = ";
  495. else
  496. result += " ";
  497. result += functionAnalyzer.GetName() + "(";
  498. for (size_t i = 0; i < convertedParams.size(); i++)
  499. {
  500. if (i != 0)
  501. result += ", ";
  502. result += convertedParams[i]->convertedVarName_;
  503. }
  504. result += ");\n";
  505. if (convertedReturn->glueReturnType_ != "void")
  506. result += " " + convertedReturn->glueReturn_;
  507. result += "}\n";
  508. if (!insideDefine.empty())
  509. result += "#endif\n";
  510. result += "\n";
  511. return result;
  512. }
  513. string GenerateWrapper(const ClassStaticFunctionAnalyzer& functionAnalyzer, vector<shared_ptr<FuncParamConv> >& convertedParams, shared_ptr<FuncReturnTypeConv> convertedReturn)
  514. {
  515. string result;
  516. string insideDefine = InsideDefine(functionAnalyzer.GetHeaderFile());
  517. if (!insideDefine.empty())
  518. result += "#ifdef " + insideDefine + "\n";
  519. result +=
  520. "// " + functionAnalyzer.GetLocation() + "\n"
  521. "static " + convertedReturn->glueReturnType_ + " " + GenerateWrapperName(functionAnalyzer) + "(";
  522. for (size_t i = 0; i < convertedParams.size(); i++)
  523. {
  524. if (i != 0)
  525. result += ", ";
  526. result += convertedParams[i]->cppType_ + " " + convertedParams[i]->inputVarName_;
  527. }
  528. result +=
  529. ")\n"
  530. "{\n";
  531. for (size_t i = 0; i < convertedParams.size(); i++)
  532. result += convertedParams[i]->glue_;
  533. if (convertedReturn->glueReturnType_ != "void")
  534. result += " " + functionAnalyzer.GetReturnType().ToString() + " result = ";
  535. else
  536. result += " ";
  537. result += functionAnalyzer.GetClassName() + "::" + functionAnalyzer.GetName() + "(";
  538. for (size_t i = 0; i < convertedParams.size(); i++)
  539. {
  540. if (i != 0)
  541. result += ", ";
  542. result += convertedParams[i]->convertedVarName_;
  543. }
  544. result += ");\n";
  545. if (convertedReturn->glueReturnType_ != "void")
  546. result += " " + convertedReturn->glueReturn_;
  547. result += "}\n";
  548. if (!insideDefine.empty())
  549. result += "#endif\n";
  550. result += "\n";
  551. return result;
  552. }
  553. string GenerateWrapper(const ClassFunctionAnalyzer& functionAnalyzer, bool templateVersion, vector<shared_ptr<FuncParamConv> >& convertedParams, shared_ptr<FuncReturnTypeConv> convertedReturn)
  554. {
  555. string result;
  556. string insideDefine = InsideDefine(functionAnalyzer.GetClass().GetHeaderFile());
  557. if (!insideDefine.empty())
  558. result += "#ifdef " + insideDefine + "\n";
  559. result +=
  560. "// " + functionAnalyzer.GetLocation() + "\n"
  561. "static " + convertedReturn->glueReturnType_ + " " + GenerateWrapperName(functionAnalyzer, templateVersion) + "(" + functionAnalyzer.GetClassName() + "* ptr";
  562. for (size_t i = 0; i < convertedParams.size(); i++)
  563. result += ", " + convertedParams[i]->cppType_ + " " + convertedParams[i]->inputVarName_;
  564. result +=
  565. ")\n"
  566. "{\n";
  567. for (size_t i = 0; i < convertedParams.size(); i++)
  568. result += convertedParams[i]->glue_;
  569. if (convertedReturn->glueReturnType_ != "void")
  570. result += " " + functionAnalyzer.GetReturnType().ToString() + " result = ";
  571. else
  572. result += " ";
  573. result += "ptr->" + functionAnalyzer.GetName() + "(";
  574. for (size_t i = 0; i < convertedParams.size(); i++)
  575. {
  576. if (i != 0)
  577. result += ", ";
  578. result += convertedParams[i]->convertedVarName_;
  579. }
  580. result += ");\n";
  581. if (convertedReturn->glueReturnType_ != "void")
  582. result += " " + convertedReturn->glueReturn_;
  583. result += "}\n";
  584. if (!insideDefine.empty())
  585. result += "#endif\n";
  586. result += "\n";
  587. return result;
  588. }
  589. // =================================================================================
  590. string Generate_asFUNCTIONPR(const GlobalFunctionAnalyzer& functionAnalyzer, const map<string, string>& templateSpecialization)
  591. {
  592. string functionName = functionAnalyzer.GetName();
  593. string cppParams = "(" + JoinParamsTypes(functionAnalyzer.GetMemberdef(), templateSpecialization) + ")";
  594. string returnType = functionAnalyzer.GetReturnType(templateSpecialization).ToString();
  595. return "asFUNCTIONPR(" + functionName + ", " + cppParams + ", " + returnType + ")";
  596. }
  597. string Generate_asFUNCTIONPR(const ClassStaticFunctionAnalyzer& functionAnalyzer, const map<string, string>& templateSpecialization)
  598. {
  599. string className = functionAnalyzer.GetClassName();
  600. string functionName = functionAnalyzer.GetName();
  601. string cppParams = "(" + JoinParamsTypes(functionAnalyzer.GetMemberdef(), templateSpecialization) + ")";
  602. string returnType = functionAnalyzer.GetReturnType(templateSpecialization).ToString();
  603. return "asFUNCTIONPR(" + className + "::" + functionName + ", " + cppParams + ", " + returnType + ")";
  604. }
  605. string Generate_asMETHODPR(const ClassFunctionAnalyzer& functionAnalyzer, bool templateVersion, const map<string, string>& templateSpecialization)
  606. {
  607. string className = functionAnalyzer.GetClassName();
  608. string functionName = functionAnalyzer.GetName();
  609. string cppParams = "(" + JoinParamsTypes(functionAnalyzer.GetMemberdef(), templateSpecialization) + ")";
  610. if (functionAnalyzer.IsConst())
  611. cppParams += " const";
  612. string returnType = functionAnalyzer.GetReturnType(templateSpecialization).ToString();
  613. // Extracting type from function name (workaround for https://github.com/doxygen/doxygen/issues/7732)
  614. if (functionAnalyzer.IsConsversionOperator())
  615. returnType = CutStart(functionName, "operator ");
  616. if (templateVersion)
  617. return "asMETHODPR(T, " + functionName + ", " + cppParams + ", " + returnType + ")";
  618. else
  619. return "asMETHODPR(" + className + ", " + functionName + ", " + cppParams + ", " + returnType + ")";
  620. }
  621. } // namespace ASBindingGenerator