home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 15 / AACD15.ISO / AACD / Programming / Python2 / Python20_source / Python / dynload_beos.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-10-25  |  6.1 KB  |  253 lines

  1.  
  2. /* Support for dynamic loading of extension modules */
  3.  
  4. #include <kernel/image.h>
  5. #include <kernel/OS.h>
  6. #include <stdlib.h>
  7. #include <unistd.h>
  8.  
  9. #include "Python.h"
  10. #include "importdl.h"
  11.  
  12. const struct filedescr _PyImport_DynLoadFiletab[] = {
  13.     {".so", "rb", C_EXTENSION},
  14.     {"module.so", "rb", C_EXTENSION},
  15.     {0, 0}
  16. };
  17.  
  18. #if defined(MAXPATHLEN) && !defined(_SYS_PARAM_H)
  19. #undef MAXPATHLEN
  20. #endif
  21.  
  22. #ifdef WITH_THREAD
  23. #include "pythread.h"
  24. static PyThread_type_lock beos_dyn_lock;
  25. #endif
  26.  
  27. static PyObject *beos_dyn_images = NULL;
  28.  
  29. /* ----------------------------------------------------------------------
  30.  * BeOS dynamic loading support
  31.  *
  32.  * This uses shared libraries, but BeOS has its own way of doing things
  33.  * (much easier than dlfnc.h, from the look of things).  We'll use a
  34.  * Python Dictionary object to store the images_ids so we can be very
  35.  * nice and unload them when we exit.
  36.  *
  37.  * Note that this is thread-safe.  Probably irrelevent, because of losing
  38.  * systems... Python probably disables threads while loading modules.
  39.  * Note the use of "probably"!  Better to be safe than sorry. [chrish]
  40.  *
  41.  * As of 1.5.1 this should also work properly when you've configured
  42.  * Python without thread support; the 1.5 version required it, which wasn't
  43.  * very friendly.  Note that I haven't tested it without threading... why
  44.  * would you want to avoid threads on BeOS? [chrish]
  45.  *
  46.  * As of 1.5.2, the PyImport_BeImageID() function has been removed; Donn
  47.  * tells me it's not necessary anymore because of PyCObject_Import().
  48.  * [chrish]
  49.  */
  50.  
  51. /* Whack an item; the item is an image_id in disguise, so we'll call
  52.  * unload_add_on() for it.
  53.  */
  54. static void beos_nuke_dyn( PyObject *item )
  55. {
  56.     status_t retval;
  57.  
  58.     if( item ) {
  59.         image_id id = (image_id)PyInt_AsLong( item );
  60.         
  61.         retval = unload_add_on( id );
  62.     }
  63. }
  64.  
  65. /* atexit() handler that'll call unload_add_on() for every item in the
  66.  * dictionary.
  67.  */
  68. static void beos_cleanup_dyn( void )
  69. {
  70.     if( beos_dyn_images ) {
  71.         int idx;
  72.         int list_size;
  73.         PyObject *id_list;
  74.  
  75. #ifdef WITH_THREAD
  76.         PyThread_acquire_lock( beos_dyn_lock, 1 );
  77. #endif
  78.  
  79.         id_list = PyDict_Values( beos_dyn_images );
  80.  
  81.         list_size = PyList_Size( id_list );
  82.         for( idx = 0; idx < list_size; idx++ ) {
  83.             PyObject *the_item;
  84.             
  85.             the_item = PyList_GetItem( id_list, idx );
  86.             beos_nuke_dyn( the_item );
  87.         }
  88.  
  89.         PyDict_Clear( beos_dyn_images );
  90.  
  91. #ifdef WITH_THREAD
  92.         PyThread_free_lock( beos_dyn_lock );
  93. #endif
  94.     }
  95. }
  96.  
  97. /*
  98.  * Initialize our dictionary, and the dictionary mutex.
  99.  */
  100. static void beos_init_dyn( void )
  101. {
  102.     /* We're protected from a race condition here by the atomic init_count
  103.      * variable.
  104.      */
  105.     static int32 init_count = 0;
  106.     int32 val;
  107.  
  108.     val = atomic_add( &init_count, 1 );
  109.     if( beos_dyn_images == NULL && val == 0 ) {
  110.         beos_dyn_images = PyDict_New();
  111. #ifdef WITH_THREAD
  112.         beos_dyn_lock = PyThread_allocate_lock();
  113. #endif
  114.         atexit( beos_cleanup_dyn );
  115.     }
  116. }
  117.  
  118. /*
  119.  * Add an image_id to the dictionary; the module name of the loaded image
  120.  * is the key.  Note that if the key is already in the dict, we unload
  121.  * that image; this should allow reload() to work on dynamically loaded
  122.  * modules (super-keen!).
  123.  */
  124. static void beos_add_dyn( char *name, image_id id )
  125. {
  126.     int retval;
  127.     PyObject *py_id;
  128.  
  129.     if( beos_dyn_images == NULL ) {
  130.         beos_init_dyn();
  131.     }
  132.  
  133. #ifdef WITH_THREAD
  134.     retval = PyThread_acquire_lock( beos_dyn_lock, 1 );
  135. #endif
  136.  
  137.     /* If there's already an object with this key in the dictionary,
  138.      * we're doing a reload(), so let's nuke it.
  139.      */
  140.     py_id = PyDict_GetItemString( beos_dyn_images, name );
  141.     if( py_id ) {
  142.         beos_nuke_dyn( py_id );
  143.         retval = PyDict_DelItemString( beos_dyn_images, name );
  144.     }
  145.  
  146.     py_id = PyInt_FromLong( (long)id );
  147.     if( py_id ) {
  148.         retval = PyDict_SetItemString( beos_dyn_images, name, py_id );
  149.     }
  150.  
  151. #ifdef WITH_THREAD
  152.     PyThread_release_lock( beos_dyn_lock );
  153. #endif
  154. }
  155.  
  156.  
  157.  
  158. dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname,
  159.                     const char *pathname, FILE *fp)
  160. {
  161.     dl_funcptr p;
  162.     image_id the_id;
  163.     status_t retval;
  164.     char fullpath[PATH_MAX];
  165.     char funcname[258];
  166.  
  167.     if( Py_VerboseFlag ) {
  168.         printf( "load_add_on( %s )\n", pathname );
  169.     }
  170.  
  171.     /* Hmm, this old bug appears to have regenerated itself; if the
  172.      * path isn't absolute, load_add_on() will fail.  Reported to Be
  173.      * April 21, 1998.
  174.      */
  175.     if( pathname[0] != '/' ) {
  176.         (void)getcwd( fullpath, PATH_MAX );
  177.         (void)strncat( fullpath, "/", PATH_MAX );
  178.         (void)strncat( fullpath, pathname, PATH_MAX );
  179.             
  180.         if( Py_VerboseFlag ) {
  181.             printf( "load_add_on( %s )\n", fullpath );
  182.         }
  183.     } else {
  184.         (void)strcpy( fullpath, pathname );
  185.     }
  186.  
  187.     the_id = load_add_on( fullpath );
  188.     if( the_id < B_NO_ERROR ) {
  189.         /* It's too bad load_add_on() doesn't set errno or something...
  190.          */
  191.         char buff[256];  /* hate hard-coded string sizes... */
  192.  
  193.         if( Py_VerboseFlag ) {
  194.             printf( "load_add_on( %s ) failed", fullpath );
  195.         }
  196.  
  197.         switch( the_id ) {
  198.         case B_ERROR:
  199.             sprintf( buff, "BeOS: Failed to load %.200s", fullpath );
  200.             break;
  201.         default:
  202.             sprintf( buff, "Unknown error loading %.200s", fullpath );
  203.             break;
  204.         }
  205.  
  206.         PyErr_SetString( PyExc_ImportError, buff );
  207.         return NULL;
  208.     }
  209.  
  210.     sprintf(funcname, "init%.200s", shortname);
  211.     if( Py_VerboseFlag ) {
  212.         printf( "get_image_symbol( %s )\n", funcname );
  213.     }
  214.  
  215.     retval = get_image_symbol( the_id, funcname, B_SYMBOL_TYPE_TEXT, &p );
  216.     if( retval != B_NO_ERROR || p == NULL ) {
  217.         /* That's bad, we can't find that symbol in the module...
  218.          */
  219.         char buff[256];  /* hate hard-coded string sizes... */
  220.  
  221.         if( Py_VerboseFlag ) {
  222.             printf( "get_image_symbol( %s ) failed", funcname );
  223.         }
  224.  
  225.         switch( retval ) {
  226.         case B_BAD_IMAGE_ID:
  227.             sprintf( buff, "can't load init function for dynamic module: "
  228.                            "Invalid image ID for %.180s", fullpath );
  229.             break;
  230.         case B_BAD_INDEX:
  231.             sprintf( buff, "can't load init function for dynamic module: "
  232.                            "Bad index for %.180s", funcname );
  233.             break;
  234.         default:
  235.             sprintf( buff, "can't load init function for dynamic module: "
  236.                            "Unknown error looking up %.180s", funcname );
  237.             break;
  238.         }
  239.  
  240.         retval = unload_add_on( the_id );
  241.  
  242.         PyErr_SetString( PyExc_ImportError, buff );
  243.         return NULL;
  244.     }
  245.  
  246.     /* Save the module name and image ID for later so we can clean up
  247.      * gracefully.
  248.      */
  249.     beos_add_dyn( fqname, the_id );
  250.  
  251.     return p;
  252. }
  253.