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 5.9KB

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