libcm is a C development framework with an emphasis on audio signal processing applications.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

cmLib.c 6.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. #include "cmPrefix.h"
  2. #include "cmGlobal.h"
  3. #include "cmRpt.h"
  4. #include "cmErr.h"
  5. #include "cmCtx.h"
  6. #include "cmMem.h"
  7. #include "cmMallocDebug.h"
  8. #include "cmLinkedHeap.h"
  9. #include "cmFileSys.h"
  10. #include "cmLib.h"
  11. #include "cmText.h"
  12. #ifndef NDEF
  13. #include <dlfcn.h>
  14. typedef void* _libH_t;
  15. bool _cmLibIsNull( _libH_t lh )
  16. { return lh == NULL; };
  17. const cmChar_t* _cmLibSysError()
  18. {
  19. const char* msg = dlerror();
  20. if( msg == NULL )
  21. msg = "<none>";
  22. return msg;
  23. }
  24. _libH_t _cmLibOpen( const char* libFn )
  25. { return dlopen(libFn,RTLD_LAZY); }
  26. bool _cmLibClose( _libH_t* lH )
  27. {
  28. if( *lH != NULL )
  29. {
  30. if( dlclose(*lH) == 0 )
  31. *lH = NULL;
  32. else
  33. return false;
  34. }
  35. return true;
  36. }
  37. void* _cmLibSym( _libH_t h, const char* symLabel )
  38. { return dlsym(h,symLabel); }
  39. #endif
  40. typedef struct cmLibNode_str
  41. {
  42. cmChar_t* fn;
  43. unsigned id;
  44. _libH_t lH;
  45. struct cmLibNode_str* link;
  46. } cmLibNode_t;
  47. typedef struct
  48. {
  49. cmErr_t err;
  50. cmLibNode_t* nodes;
  51. unsigned id;
  52. cmFileSysH_t fsH;
  53. } cmLib_t;
  54. cmLib_t* _cmLibHandleToPtr( cmLibH_t h )
  55. {
  56. cmLib_t* p = (cmLib_t*)h.h;
  57. return p;
  58. }
  59. cmLibH_t cmLibNullHandle = cmSTATIC_NULL_HANDLE;
  60. cmLibRC_t _cmLibNodeFree( cmLib_t* p, cmLibNode_t* np )
  61. {
  62. if( !_cmLibClose( &np->lH ) )
  63. return cmErrMsg(&p->err,kCloseFailLibRC,"Library close failed. System Message: %s", _cmLibSysError());
  64. // free np->fn and set np->fn to NULL - so the node may be reused.
  65. cmMemPtrFree(&np->fn);
  66. np->id = cmInvalidId;
  67. return kOkLibRC;
  68. }
  69. cmLibRC_t _cmLibFinalize( cmLib_t* p )
  70. {
  71. cmLibNode_t* np = p->nodes;
  72. while( np != NULL )
  73. {
  74. cmLibNode_t* pp = np->link;
  75. _cmLibNodeFree(p,np);
  76. cmMemFree(np);
  77. np = pp;
  78. }
  79. if( cmFileSysIsValid(p->fsH) )
  80. cmFileSysFinalize(&p->fsH);
  81. cmMemFree(p);
  82. return kOkLibRC;
  83. }
  84. cmLibRC_t cmLibInitialize( cmCtx_t* ctx, cmLibH_t* hp, const cmChar_t* dirStr )
  85. {
  86. cmLibRC_t rc = kOkLibRC;
  87. cmLib_t* p = cmMemAllocZ(cmLib_t,1);
  88. cmErrSetup(&p->err,&ctx->rpt,"cmLib");
  89. cmFileSysInitialize(&p->fsH,ctx,"cmLibFs");
  90. hp->h = p;
  91. if( cmTextIsNotEmpty(dirStr) )
  92. if((rc = cmLibScan(*hp,dirStr)) != kOkLibRC )
  93. hp->h = NULL;
  94. if( rc != kOkLibRC )
  95. _cmLibFinalize(p);
  96. return rc;
  97. }
  98. cmLibRC_t cmLibFinalize( cmLibH_t* hp )
  99. {
  100. cmLibRC_t rc;
  101. if( hp == NULL || hp->h == NULL )
  102. return kOkLibRC;
  103. cmLib_t* p = _cmLibHandleToPtr(*hp);
  104. if((rc = _cmLibFinalize(p)) == kOkLibRC )
  105. hp->h = NULL;
  106. return rc;
  107. }
  108. bool cmLibIsValid( cmLibH_t h )
  109. { return h.h != NULL; }
  110. unsigned cmLibOpen( cmLibH_t h, const cmChar_t* libFn )
  111. {
  112. cmLib_t* p = _cmLibHandleToPtr(h);
  113. _libH_t lH = _cmLibOpen(libFn);
  114. cmLibNode_t* np = p->nodes;
  115. unsigned idx = 0;
  116. if( _cmLibIsNull(lH) )
  117. {
  118. // There is apparently no way to get an error code which indicates that the
  119. // file load attempt failed because the file was not a shared library -
  120. // which should not generate an error message - therefore
  121. // we must match the end of the the error string returned by dlerror() with
  122. // 'invalid ELF header'.
  123. const char* errMsg = _cmLibSysError();
  124. const char* s = "invalid ELF header";
  125. unsigned sn = strlen(s);
  126. unsigned mn = strlen(errMsg);
  127. if( errMsg!=NULL && mn>sn && strcmp(errMsg+mn-sn,s)==0 )
  128. cmErrSetRC(&p->err,kOpenFailLibRC ); // signal error but no error message
  129. else
  130. cmErrMsg(&p->err,kOpenFailLibRC,"Library load failed. System Message: %s", errMsg );
  131. return cmInvalidId;
  132. }
  133. while( np != NULL )
  134. {
  135. if( np->fn == NULL )
  136. break;
  137. np = np->link;
  138. ++idx;
  139. }
  140. if( np == NULL )
  141. {
  142. np = cmMemAllocZ(cmLibNode_t,1);
  143. np->link = p->nodes;
  144. p->nodes = np;
  145. }
  146. np->fn = cmMemAllocStr(libFn);
  147. np->lH = lH;
  148. np->id = p->id++;
  149. return idx;
  150. }
  151. cmLibNode_t* _cmLibIdToNode( cmLib_t* p, unsigned libId )
  152. {
  153. cmLibNode_t* np = p->nodes;
  154. while( np != NULL )
  155. {
  156. if( np->id == libId )
  157. return np;
  158. np = np->link;
  159. }
  160. return NULL;
  161. }
  162. cmLibRC_t cmLibClose( cmLibH_t h, unsigned libId )
  163. {
  164. cmLib_t* p = _cmLibHandleToPtr(h);
  165. cmLibNode_t* np = _cmLibIdToNode(p,libId);
  166. if( (np == NULL) || _cmLibIsNull(np->lH) )
  167. return cmErrMsg(&p->err,kInvalidIdLibRC,"The library id %i is not valid or the library is closed.",libId);
  168. return kOkLibRC;
  169. }
  170. void* cmLibSym( cmLibH_t h, unsigned libId, const cmChar_t* funcStr )
  171. {
  172. void* f;
  173. cmLib_t* p = _cmLibHandleToPtr(h);
  174. cmLibNode_t* np = _cmLibIdToNode(p,libId);
  175. if( (np == NULL) || _cmLibIsNull(np->lH) )
  176. {
  177. cmErrMsg(&p->err,kInvalidIdLibRC,"The library id %i is not valid or the library is closed.",libId);
  178. return NULL;
  179. }
  180. if((f = _cmLibSym(np->lH,funcStr)) == NULL)
  181. {
  182. cmErrMsg(&p->err,kSymFailLibRC,"The dynamic symbol '%s' was not found. System Message: %s", cmStringNullGuard(funcStr), _cmLibSysError());
  183. return NULL;
  184. }
  185. return f;
  186. }
  187. cmLibRC_t cmLibScan( cmLibH_t h, const cmChar_t* dirStr )
  188. {
  189. cmLib_t* p = _cmLibHandleToPtr(h);
  190. unsigned dirEntryCnt = 0;
  191. cmFileSysDirEntry_t* d = NULL;
  192. cmLibRC_t rc = kOkLibRC;
  193. unsigned i = 0;
  194. if( cmFileSysIsValid(p->fsH) == false )
  195. return cmErrMsg(&p->err,kFileSysFailLibRC,"The file system object was not successfully initialized.");
  196. if((d = cmFileSysDirEntries(p->fsH, dirStr, kFileFsFl | kFullPathFsFl, &dirEntryCnt )) == NULL )
  197. return cmErrMsg(&p->err,kFileSysFailLibRC,"The scan of directory '%s' failed.",cmStringNullGuard(dirStr));
  198. for(i=0; i<dirEntryCnt; ++i)
  199. cmLibOpen(h,d[i].name);
  200. cmFileSysDirFreeEntries(p->fsH,d);
  201. return rc;
  202. }
  203. unsigned cmLibCount( cmLibH_t h )
  204. {
  205. cmLib_t* p = _cmLibHandleToPtr(h);
  206. cmLibNode_t* np = p->nodes;
  207. unsigned n = 0;
  208. while( np != NULL )
  209. {
  210. np = np->link;
  211. ++n;
  212. }
  213. return n;
  214. }
  215. unsigned cmLibIndexToId( cmLibH_t h, unsigned idx )
  216. {
  217. cmLib_t* p = _cmLibHandleToPtr(h);
  218. cmLibNode_t* np = p->nodes;
  219. unsigned i = 0;
  220. while( np != NULL )
  221. {
  222. if( i == idx )
  223. return np->id;
  224. np = np->link;
  225. ++i;
  226. }
  227. if(np == NULL )
  228. {
  229. cmErrMsg(&p->err,kInvalidIdLibRC,"The library index %i is not valid.",idx);
  230. return cmInvalidId;
  231. }
  232. return np->id;
  233. }
  234. const cmChar_t* cmLibName( cmLibH_t h, unsigned libId )
  235. {
  236. cmLib_t* p = _cmLibHandleToPtr(h);
  237. cmLibNode_t* np = _cmLibIdToNode(p,libId);
  238. if( (np == NULL) || _cmLibIsNull(np->lH) )
  239. {
  240. cmErrMsg(&p->err,kInvalidIdLibRC,"The library id %i is not valid or the library is closed.",libId);
  241. return NULL;
  242. }
  243. return np->fn;
  244. }