libcm is a C development framework with an emphasis on audio signal processing applications.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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, &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. }