0

In one of my Django models, I defined a function that loads an external *.dll library by changing into the directory and then importing the library via ctypes.CDLL... so in principle this is what I do in the function of the model:

basepath = os.getcwd()
_DIRNAME = os.path.dirname(__file__)
dllspath = os.path.join(_DIRNAME, "dlls_x64")
os.chdir(dllspath)
__libx64 = ctypes.CDLL("libx64")
...
os.chdir(basepath)

I am sure changing the directories is not recommended during a function call and that this is bad design, but at this point I just want to understand what ctypes.CDLL is exactly doing.

Because when I test this function in a unit test, the library can be found and no error is raised. But when I test the code interactively in a python console, the module cannot be found:

OSError: [WinError 126] The specified module could not be found

I run my unit tests with the module django-test-without-migrations and a sqlite backend because I can't create a unit test database for my production oracle backend. So for unit tests, I do:

python manage.py test --nomigrations --settings=settings.unittests

and settings.unittests.py contains:

from settings.defaults import *
DATABASES['default'] = {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db_unittests.sqlite3')
    }

while for interactive python console, I go:

python manage.py shell_plus

So I do not understand why the *.dll import works in the unit test for the function, but not when I call the function in a console.

Sebastian
  • 15
  • 6
  • In Windows, `ctypes.CDLL` calls WINAPI `LoadLibraryW`, which searches for dependent DLLs using the current DLL search path. By default, that's the application directory (i.e. location of python.exe), system directories, current directory, and the directories in `PATH`. But it can be quite different depending on whether `SetDefaultDllDirectories`, `AddDllDirectory`, or `SetDllDirectoryW` have been called. In particular, the current directory may not be in the search path. Also, the loader will use an already loaded DLL instead of searching for it, so the result can depend on previous calls. – Eryk Sun Mar 25 '19 at 14:21
  • If there are dependent DLLs in the same directory as libx64.dll, try using the `CDLLEx` class from my [previous answer](https://stackoverflow.com/a/7586821), with the flag `LOAD_WITH_ALTERED_SEARCH_PATH`. – Eryk Sun Mar 25 '19 at 14:29
  • Yes, there are dependent DLLs in the same directory as libx64.dll. I will try your `CDLLEx` class. Thanks! – Sebastian Mar 25 '19 at 14:37
  • @eryksun. The module can now be loaded from console. So it seems to work now. Thank you! – Sebastian Mar 25 '19 at 14:55

0 Answers0