You can use a dynamic pointer cast to reach the base vector/matrix
For example:
std::dynamic_pointer_cast<PETScVector>(x.vector())
I find this useful if I have a Function which has a vector that was created by an internal factory. I can check if PETSc is in use, and then do the dynamic cast to do anything PETSc specific (like apply("")).