Firstly thanks to both of you for useful replies. Here is the new info I got from your replies: 1. sqlite_load_extension is per-db-connection - Oddly I did not see any explicit reference to this in either of the two places I looked for it: i) http://www.sqlite.org/cvstrac/wiki?p=LoadableExtensions or ii) http://www.sqlite.org/c3ref/load_extension.html
2. Following up on windows dllmain info - which was very useful in itself - but since we use both windows and linux, I checked the equivalent for linux as well and yes, luckily, gcc allows you to define a 'function attribute' called 'constructor' and 'destructor' which can be used to export the functions in your shared lib to invoke at dlopen and dlclose. So, I should be able to use this 'destructor'-attributed function for library stuff cleanup on linux - haven't gotten to testing it yet though. 3. Libs loaded but no more useful will be swapped out and will not consume memory - interesting point. As for what I have tried from your suggestions so far: 1. Tried the collating sequence xDestroy trick but that did not work for my case - this because my lib prepares some statements internally and seems like close() checks for unfinalised prepared statements and fails even before control ever reaches xDestroy for collations: Now, if only, it reached the xDestroy - I do finalize those prepared statements there! === sqlite> .load ./libMylib.so sqlite> .q error closing database: Unable to close due to unfinalised statements === 2. I would prefer having an 'unload lib' command because libs will be given to users (other than me) on both embedded and desktop-type envs and how their code uses it is beyond my control. But still, yes, I already have a function in my lib which can be called to do cleanup and I have registered it with sqlite so that it can be invoked using "SELECT mylib_cleanup();" - though not a real unload, I can set a flag within mylib_cleanup() to indicate the lib 'closed' (and check this flag in beginning of all functions exported from lib so that user code cannot access it) and then let this 'closed' lib remain dead in the memory or let it be swapped out as you mentioned. While this works and I will use it just because my libs must work on older and current sqlite versions, for future sqlite versions, I would suggest having an 'unload lib' command to simplify coding this unload behavior. Thanks, SK On Mon, Aug 31, 2009 at 10:51 AM, Jean-Christophe Deschamps <j...@q-e-d.org>wrote: > > At 18:25 30/08/2009, you wrote: > 疮 > > When we load an extension it invokes sqlite3_extension_init(). Lets say, >> in >> addition to creating functions, the loaded extension library also does >> some >> internal data structure allocations, initializations etc here. >> >> Now, when the database is closed the loaded extension needs to do >> cleanup. >> To do that: >> 1. Is it possible to register a callback which is invoked on database >> close? >> 2. or is there a plan to add something like: sqlite3_extension_end() which >> can be used for this? >> 3. and if answer to 2 is yes, how about add an 'unload' command for >> extensions as well so that we can unload extensions when they are no more >> needed? >> >> 4. If none of the above functionality exists yet, is there a workaround >> available today to achieve this? >> > `--- > > As a sidenote to what Roger just disclosed (umm, what a strange "hack"!), > it is possible that a more conventional way exist. From what I can tell, it > all depends on the environment. At least there is one clean way in the case > of a .dll extension under Windows. It's quite possible that a similar way > could work for other systems as well. > > What is your environment? > > > In the Windows .dll case, you can have the extension registered in several > ways: > > 1a) your app calls sqlite3_load_extension() > or > 1b) your app issues a "SELECT load_extension('yourext.dll'[, > 'entry_point']);" > > and your .dll has code like this: > > DLL_EXPORT int sqlite3_extension_init( // std name of entry point > sqlite3 *db, > char **pzErrMsg, > const sqlite3_api_routines *pApi > ){ > SQLITE_EXTENSION_INIT2(pApi) > // calls to sqlite3_create_function(db, ...) > // and/or calls to sqlite3_create_collation(db, ...) > return SQLITE_OK; // or SQLITE_ERROR > } > > The drawback is that the extension is registered for the calling > connection > only. Besides what Roger suggested there's no official callback for > cleanup > (again on a connection-basis). > > 2) your app issues a call to sqlite_auto_extension(entry_point). Then the > extension > will be available for any _new_ DB connection. > You can invoke sqlite3_reset_auto_extension() to free memory allocated > to > manage the extension, but I believe you don't have an official hook to > clean > anything else of your own. > > 3) your app loads the extension as 1a) or 1b) and your load entry point > looks like > > DLL_EXPORT int sqlite3_extension_init( > sqlite3 *db, > char **pzErrMsg, > const sqlite3_api_routines *pApi > ){ > return SQLITE_OK; > } > > Yes, it's a noop, BUT wait a minute, your .dll also contains this: > > // the DllMain will be called by Windows upon first .dll invokation, i.e. > when you call the noop function above > // it will be called again when closing the .dll, which gives you the > opportunity to clean up things > > #if ((defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || > defined(__MINGW32__) || defined(__BORLANDC__)) && (!defined(SQLITE_CORE))) > int __stdcall DllMain(void *hinstDLL, unsigned long fdwReason, void > *lpReserved) > { > if (fdwReason == 1) { // DLL_PROCESS_ATTACH > // > // <=== insert here code to set up your own mess > // > sqlite3_auto_extension((void*)sqlite3_extension_load); > } else if (fdwReason == 0) { // DLL_PROCESS_DETACH > // > // <=== insert here code to clean up your own mess > // > sqlite3_reset_auto_extension(); > }; > return 1; > } > #endif > > > // SQLite core will call this on every new DB connection > DLL_EXPORT int sqlite3_extension_load( > sqlite3 *db, > char **pzErrMsg, > const sqlite3_api_routines *pApi > ){ > SQLITE_EXTENSION_INIT2(pApi) > return sqlite3_auto_extension((void*)your_ext_register); > } > > > DLL_EXPORT int your_ext_register( > sqlite3 *db, > char **pzErrMsg, > const sqlite3_api_routines *pApi > ){ > SQLITE_EXTENSION_INIT2(pApi) > // > // more mess setup > // > // calls to sqlite3_create_function(db, ...) > // and/or calls to sqlite3_create_collation(db, ...) > return SQLITE_OK; // or SQLITE_ERROR > } > > I hope I didn't make mistakes in the excerpt. Anyway this gets you two > birds with one stone. You can also use this trick if you're using a > third-party SQLite manager, provided it allows you to load extensions. If > you're lucky enough your non-Windows OS will have a similar hook which you > can use. > > > > > _______________________________________________ sqlite-users mailing list sqlite-users@sqlite.org http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users