sqratimport.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. //
  2. // SqratImport: Supports importing of squirrel modules
  3. //
  4. //
  5. // Copyright (c) 2009 Brandon Jones
  6. //
  7. // This software is provided 'as-is', without any express or implied
  8. // warranty. In no event will the authors be held liable for any damages
  9. // arising from the use of this software.
  10. //
  11. // Permission is granted to anyone to use this software for any purpose,
  12. // including commercial applications, and to alter it and redistribute it
  13. // freely, subject to the following restrictions:
  14. //
  15. // 1. The origin of this software must not be misrepresented; you must not
  16. // claim that you wrote the original software. If you use this software
  17. // in a product, an acknowledgment in the product documentation would be
  18. // appreciated but is not required.
  19. //
  20. // 2. Altered source versions must be plainly marked as such, and must not be
  21. // misrepresented as being the original software.
  22. //
  23. // 3. This notice may not be removed or altered from any source
  24. // distribution.
  25. //
  26. #include "sqratimport.h"
  27. #include "sqmodule.h"
  28. //#include "sqratlib/sqratBase.h"
  29. #include <stdio.h>
  30. #include <sqstdio.h>
  31. #if defined(_WIN32)
  32. #include <windows.h>
  33. #elif defined(__unix)
  34. #include <dlfcn.h>
  35. #endif
  36. typedef SQRESULT (*SQMODULELOAD)(HSQUIRRELVM v, HSQAPI sq);
  37. static HSQAPI sqapi = NULL;
  38. // Create and populate the HSQAPI structure with function pointers
  39. // If new functions are added to the Squirrel API, they should be added here too
  40. static HSQAPI sqrat_newapi() {
  41. HSQAPI sq = (HSQAPI)sq_malloc(sizeof(sq_api));
  42. #define SQUIRREL_API_FUNC(fret, fname, fargs) sq->sq_##fname = sq_##fname;
  43. #include "sqapi.h"
  44. #undef SQUIRREL_API_FUNC
  45. return sq;
  46. }
  47. static void sqrat_deleteapi(HSQAPI sq) {
  48. sq_free(sq, sizeof(sq_api));
  49. }
  50. static SQRESULT sqrat_importscript(HSQUIRRELVM v, const SQChar* moduleName) {
  51. if(SQ_FAILED(sqstd_loadfile(v, moduleName, true, true))) {
  52. char filename[1024];
  53. scsprintf(filename, sizeof(filename), "%s.nut", moduleName);
  54. if(SQ_FAILED(sqstd_loadfile(v, filename, true, true))) {
  55. return SQ_ERROR;
  56. }
  57. }
  58. sq_push(v, -2);
  59. sq_call(v, 1, false, true);
  60. return SQ_OK;
  61. }
  62. static SQRESULT sqrat_importbin(HSQUIRRELVM v, const SQChar* moduleName) {
  63. SQMODULELOAD modLoad = 0;
  64. #if defined(_WIN32)
  65. HMODULE mod;
  66. mod = GetModuleHandleA(moduleName);
  67. if(mod == NULL) {
  68. mod = LoadLibraryA(moduleName);
  69. if(mod == NULL) {
  70. return SQ_ERROR;
  71. }
  72. }
  73. modLoad = (SQMODULELOAD)GetProcAddress(mod, "sqmodule_load");
  74. if(modLoad == NULL) {
  75. FreeLibrary(mod);
  76. return SQ_ERROR;
  77. }
  78. #elif defined(__unix)
  79. /* adding .so to moduleName? */
  80. void *mod = dlopen(moduleName, RTLD_NOW | RTLD_LOCAL
  81. #ifndef ANDROID_BUILD
  82. | RTLD_NOLOAD //RTLD_NOLOAD flag is not specified in POSIX.1-2001..so not the best solution :(
  83. #endif
  84. );
  85. if (mod == NULL) {
  86. mod = dlopen(moduleName, RTLD_NOW | RTLD_LOCAL);
  87. if (mod == NULL)
  88. return SQ_ERROR;
  89. }
  90. modLoad = (SQMODULELOAD) dlsym(mod, "sqmodule_load");
  91. if (modLoad == NULL) {
  92. dlclose(mod);
  93. return SQ_ERROR;
  94. }
  95. #endif
  96. if(sqapi == NULL) {
  97. sqapi = sqrat_newapi(); // Caching this for multiple imports is probably a very good idea
  98. }
  99. SQRESULT res = modLoad(v, sqapi);
  100. return res;
  101. }
  102. SQRESULT sqrat_import(HSQUIRRELVM v) {
  103. const SQChar* moduleName;
  104. HSQOBJECT table;
  105. SQRESULT res = SQ_OK;
  106. //SQInteger top = sq_gettop(v);
  107. sq_getstring(v, -2, &moduleName);
  108. sq_getstackobj(v, -1, &table);
  109. sq_addref(v, &table);
  110. sq_settop(v, 0); // Clear Stack
  111. sq_pushobject(v, table); // Push the target table onto the stack
  112. if(SQ_FAILED(sqrat_importscript(v, moduleName))) {
  113. res = sqrat_importbin(v, moduleName);
  114. }
  115. sq_settop(v, 0); // Clean up the stack (just in case the module load leaves it messy)
  116. sq_pushobject(v, table); // return the target table
  117. sq_release(v, &table);
  118. return res;
  119. }
  120. static SQRESULT sqratbase_import(HSQUIRRELVM v) {
  121. SQInteger args = sq_gettop(v);
  122. switch(args) {
  123. case 2:
  124. sq_pushroottable(v);
  125. break;
  126. case 3:
  127. // should already have the desired table pushed onto the stack
  128. if(sq_gettype(v, 3) != OT_TABLE) return sq_throwerror(v, _SC("table expected as second parameter"));
  129. break;
  130. default:
  131. // Error, unexpected number of arguments
  132. return sq_throwerror(v, _SC("unexpected number of arguments"));
  133. break;
  134. }
  135. sqrat_import(v);
  136. return 1;
  137. }
  138. SQRESULT sqrat_register_importlib(HSQUIRRELVM v) {
  139. sq_pushroottable(v);
  140. sq_pushstring(v, _SC("import"), -1);
  141. sq_newclosure(v, &sqratbase_import, 0);
  142. sq_newslot(v, -3, 0);
  143. sq_pop(v, 1); // pop root table
  144. return SQ_OK;
  145. }