code: def lyr_proj(lyr, t_srs, preserve_fields=True):
      
      #Need to check t_srs
      s_srs = lyr.GetSpatialRef()
      cT = osr.CoordinateTransformation(s_srs, t_srs)
  
      #Do everything in memory
      drv = ogr.GetDriverByName('Memory')
  
      #Might want to save clipped, warped shp to disk?
      # create the output layer
      #drv = ogr.GetDriverByName('ESRI Shapefile')
      #out_fn = '/tmp/temp.shp'
      #if os.path.exists(out_fn):
      #    driver.DeleteDataSource(out_fn)
      #out_ds = driver.CreateDataSource(out_fn)
      
      out_ds = drv.CreateDataSource('out')
      outlyr = out_ds.CreateLayer('out', srs=t_srs, geom_type=lyr.GetGeomType())
  
      if preserve_fields:
          # add fields
          inLayerDefn = lyr.GetLayerDefn()
          for i in range(0, inLayerDefn.GetFieldCount()):
              fieldDefn = inLayerDefn.GetFieldDefn(i)
              outlyr.CreateField(fieldDefn)
          # get the output layer's feature definition
      outLayerDefn = outlyr.GetLayerDefn()
  
      # loop through the input features
      inFeature = lyr.GetNextFeature()
      while inFeature:
          # get the input geometry
          geom = inFeature.GetGeometryRef()
          # reproject the geometry
          geom.Transform(cT)
          # create a new feature
          outFeature = ogr.Feature(outLayerDefn)
          # set the geometry and attribute
          outFeature.SetGeometry(geom)
          if preserve_fields:
              for i in range(0, outLayerDefn.GetFieldCount()):
                  outFeature.SetField(outLayerDefn.GetFieldDefn(i).GetNameRef(), inFeature.GetField(i))
          # add the feature to the shapefile
          outlyr.CreateFeature(outFeature)
          # destroy the features and get the next input feature
          inFeature = lyr.GetNextFeature()
      #NOTE: have to operate on ds here rather than lyr, otherwise segfault
      return out_ds
docs: Reproject an OGR layer