Accessing sqlite3Apis pointer when loading sqlite3 dll/so.
I have a shared library that internally uses a statically linked sqlite for a few different internal tasks. Amongst these there is some code that provides a few virtual tables. I would like to extend the interface of the library so that as well as it’s normal interface, it can be accessed as an sqlite extension through some of these virtual tables. This will allow my library to be used in two ways:
a) Through its normal C interface.
b) From an sqlite3 extension loadable from the sqlite3 client app, or the R or python interfaces to sqlite3.
The problem is how to build the internal code that accesses sqlite3, including the virtual table code that I also want to make available through the extension. For the virtual table code I think I would need to build two copies, one with SQLITE_CORE defined (to be used internally), and the other without (to be used in case b). Doing this, in case b, I would suffer the problems I have read about where there would be two copies of the static global that implements the posix locking workaround. Although in my use case it is almost certain this would not cause a problem (I can’t envisage a use case where both my statically linked sqlite3 and the one being used at the interface layer would open the same db). It still feels like an ugly solution.
My thought instead is to build all of sqlite code using sqlite3ext.h and without SQLITE_CORE defined, and in case a, dynamically load an sqlite3 library. However i need to get access to the sqlite3_api_routines pointer within whichever sqlite3 library is being used. My question is how to do this?
In case b, the pointer is passed when the extension is first loaded, and I can pass it through to the rest of my library. For case a I’m struggling a bit. The best I can figure is:
(Assume I have called dlopen/LoadLibrary and can access symbols with dlsym/GetProcAddress)
1. Set up a fake extension function whose purpose is to capture the sqlite3Apis pointer passed to xInit within sqlite3AutoLoadExtensions.
2. Use dlsym/GetProcAddress to find sqlite3_auto_extension, sqlite3_cancel_auto_extension, sqlite3_open_v2, sqlite3_close.
3. Register my extension with sqlite3_auto extension.
4. Open an in memory database to load the extension and capture the sqlite3_api_routines pointer.
5. Close the database.
6. Cancel the auto extension.
My questions are:
1) Am I missing anything, i.e. does this work.
2) Will it be guaranteed in the future that the sqlite3_api_routines pointer will be passed to the extensions loaded by sqlite3_auto_extension.
3) Is there a better way to do this as it feels a little hacky.