Skip to content

Commit 1c05fcd

Browse files
authored
Revise logic for unified (semistatic) libvips binaries (#505)
* Revise logic for unified (semistatic) libvips binaries
1 parent 6ce5540 commit 1c05fcd

File tree

1 file changed

+33
-32
lines changed

1 file changed

+33
-32
lines changed

pyvips/__init__.py

+33-32
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,17 @@
1010
# user code can override this null handler
1111
logger.addHandler(logging.NullHandler())
1212

13+
def library_name(name, abi_number):
14+
is_windows = os.name == 'nt'
15+
is_mac = sys.platform == 'darwin'
16+
17+
if is_windows:
18+
return f'lib{name}-{abi_number}.dll'
19+
elif is_mac:
20+
return f'lib{name}.{abi_number}.dylib'
21+
else:
22+
return f'lib{name}.so.{abi_number}'
23+
1324
# pull in our module version number
1425
from .version import __version__
1526

@@ -48,41 +59,12 @@
4859

4960
ffi = FFI()
5061

51-
_is_windows = os.name == 'nt'
52-
_is_mac = sys.platform == 'darwin'
53-
54-
# yuk
55-
if _is_windows:
56-
vips_lib = ffi.dlopen('libvips-42.dll')
57-
elif _is_mac:
58-
vips_lib = ffi.dlopen('libvips.42.dylib')
59-
else:
60-
vips_lib = ffi.dlopen('libvips.so.42')
62+
vips_lib = ffi.dlopen(library_name('vips', 42))
63+
glib_lib = vips_lib
64+
gobject_lib = vips_lib
6165

6266
logger.debug('Loaded lib %s', vips_lib)
6367

64-
if _is_windows:
65-
# On Windows, `GetProcAddress()` can only search in a specified DLL and
66-
# doesn't look into its dependent libraries for symbols. Therefore, we
67-
# check if the GLib DLLs are available. If these can not be found, we
68-
# assume that GLib is statically linked into libvips.
69-
try:
70-
glib_lib = ffi.dlopen('libglib-2.0-0.dll')
71-
gobject_lib = ffi.dlopen('libgobject-2.0-0.dll')
72-
73-
logger.debug('Loaded lib %s', glib_lib)
74-
logger.debug('Loaded lib %s', gobject_lib)
75-
except Exception:
76-
glib_lib = vips_lib
77-
gobject_lib = vips_lib
78-
else:
79-
# macOS and *nix uses `dlsym()`, which also searches for named symbols
80-
# in the dependencies of the shared library. Therefore, we can support
81-
# a single shared libvips library with all dependencies statically
82-
# linked.
83-
glib_lib = vips_lib
84-
gobject_lib = vips_lib
85-
8668
ffi.cdef('''
8769
int vips_init (const char* argv0);
8870
int vips_version (int flag);
@@ -108,6 +90,25 @@
10890

10991
ffi.cdef(cdefs(features))
11092

93+
# We can sometimes get dependent libraries from libvips -- either the platform
94+
# will open dependencies for us automatically, or the libvips binary has been
95+
# built to includes all main dependencies (common on windows, can happen
96+
# elsewhere).
97+
#
98+
# We must get glib functions from libvips if we can, since it will be the
99+
# one that libvips itself is using, and they will share runtime types.
100+
try:
101+
is_unified = gobject_lib.g_type_from_name(b'VipsImage') != 0
102+
except Exception:
103+
is_unified = False
104+
105+
if not is_unified:
106+
glib_lib = ffi.dlopen(library_name('glib-2.0', 0))
107+
gobject_lib = ffi.dlopen(library_name('gobject-2.0', 0))
108+
109+
logger.debug('Loaded lib %s', glib_lib)
110+
logger.debug('Loaded lib %s', gobject_lib)
111+
111112

112113
from .error import *
113114

0 commit comments

Comments
 (0)