Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

I'm having a bit of a nightmare getting to the bottom of this DLL loading problem. The stand alone script works absolutely fine but the exact same code does not work within QGIS.

import sys   
from pysqlite2 import dbapi2 as sqlite

sys.path.append(os.path.dirname(__file__)
conn = sqlite.connect(db_name)
conn.enable_load_extension(True)
spatial_dll = os.path.join(os.path.dirname(__file__), "libspatialite-1.dll")
conn.execure('SELECT load_extension("%s")' % spatial_dll)

In the same directory as this script are the dependant DLL needed. It works like a charm stand alone, but not when put inside of QGIS. I am guessing I either have some kind of path issue or a compatibility issue with another version of the DLL somewhere else in QGIS.

Can anyone point me in the right direction? I don't have enough hair left as it is and I am losing more and more each hour...

Dan

share|improve this question
1  
I don't know why you decided to load the dll manually, but it might not be necessary because it's possible to use spatialite by default: qgis.org/pyqgis-cookbook/loadlayer.html?highlight=spatialite –  underdark May 13 '13 at 19:12
    
Thanks for your input. Unfortunately this is not a solution I can use. The body of code is part of a much larger project that cannot be customized specifically for QGIS - its used by other applications as well. So I need to use pure Python methods with databases and shapefiles/wkt over built in QGIS functions. Also, I want to distribute the DLLs with my plugin that hopefully mean users don't have to download/configure/install anything. –  Dan May 14 '13 at 9:15
3  
It seems like there could be some worth in asking our friends over at Stack Overflow if they have any insight into the problem. This seems to be strictly programming related. Even though it concerns GIS software, it is not related to GIS concepts. You may get more response and help over there. –  Get Spatial May 14 '13 at 21:15
1  
your standalone environment is broken - execure shouldn't work there either ;) Do you get any error messages? are all dependant DLLs in the directory of the script or do you rely on any entries in PATH that might different from within QGIS. Does your standalone use the python from OSGeo4W/QGIS or a different one? If it doesn't, does it work when using the OSGeo4W/QGIS python outside of QGIS? –  jef May 18 '13 at 18:23

1 Answer 1

up vote 1 down vote accepted

So the answer to this took some time to find but ended up trivial but not straightforward to spot (to me at least). Damn you PATH...

When my plugin was running, I noted that if I ran os.getcwd() within my plugin, it did not actually output the plugin directory, but instead "C:\Program Files (x86)\QGIS" - the install directory of QGIS for my current machine. So any relative paths (e.g. a DLL looking for a dependent DLL in the current working directory) wouldn't work because I wasn't starting off where I thought I was.

So I made sure that my plugin and DLL directories were included in PATH:

plugin_dir = os.path.dirname(os.path.abspath(__file__))
dll_dir = os.path.join(plugin_dir + 'dlls')
sys.path.append(plugin_dir)
sys.path.append(dll_dir)

But yet I still found a similar problem. The libspatialite.dll path was correct and all the right directories showed up if I ran:

import sys
for i in sys.path:
    print i

Also, my code continued to work as a standalone application. But they would not work within QGIS, outputting the same "the specified module could not be found" error.

The answer finally came when I stumbled across (this post). Fundamentally, it seems that sys.path.append doesn't seem to do quite enough if the DLL being loaded has linked DLLS itself - which the version of libspatialite.dll I am using does.

Now, I am not entirely sure why a DLL with linked DLLs would work when run from a script when the Python current working directory is the same directory as the DLLs, and would not work when loaded from within QGIS, but this seems to be the case. I'm lead to believe this could be something to do with "runtime dynamic linking" but I don't know enough about it to be sure.

So, final solution was to permanently modify PATH

if spatialite_dll_dir not in os.environ['PATH']:
    os.environ['PATH'] = spatialite_dll_dir + ';' + os.environ['PATH']

And everything is now working! For now at least...and thank you all very much for your help and suggestions.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.