In general, assuming that static library uses ABI compatible with shared libraries (which is not the case on all platforms), then symbol resolution is delegated to dynamic linker.
If your DSO has been linked with libc statically, it may include its own copy of required code from libc and other libraries. That may potentially create issues if DSO is loaded from another executable that uses libc.
If your DSO was linked with libc dynamically, then the DSO would add required shared library on its dynamic dependency list and would leave the symbols unresolved until it's loaded.
Let's assume, that we're dealing with the latter case as it's what typically happens.
When you load DSO, runtime linker recursively loads required shared libraries and for each unresolved symbol tries to figure out its location. If your executable, for instance, has statically linked printf and your DSO wants to us it, dynamic linker would resolve references from DSO to point to printf's location in the executable. If the executable is dynamically linked with libc, printf references would point to the code in libc.so.
You can get a peek at what's going on if you set LD_DEBUG=all in the environment and run the app that loads your DSO (or any dynamically linked executable). You will see what dynamic linker is doing as it happens. The output is verbose, but should give you general idea of what happens under the hood.