Hi Clément,
I would say first and foremost *never* make a split package. All bundles that contain a package must contain the *whole* package, and there will definitely be a problem if your library if it tries to add types to the API package. Note that it is *not* a split package if two bundles both contain the whole package, and this situation is perfectly fine.
In this scenario the Library bundle must export the package(s) for what it provides (either the package for the factory class, or the package for the type that gets newed up). The important thing is that as far as the library is concerned, the “implementation” class is API. If the library API is coupled to the service API (i.e. receives or returns types from the API package) then it must also express a uses constraint on the service API package when it is exported. Bnd will correctly generate this constraint for you unless you deliberately override it (please don’t ever override it!).
The result should be that Bundle D imports the API package and the library implementation package. Ideally the library and the API bundle will substitutably export the API package (i.e. both export and import it). Substitutable exports are the default behaviour in bnd.
In a system with substitutable imports the wiring will work, with uses constraints ensuring that the API is shared in a valid way.
I hope this helps.
Regards,
Tim