Skip to content

Commit 66d0a66

Browse files
committed
Fix -Wincompatible-function-pointer-types warning on Clang
See: libvips/libvips#3901 (comment)
1 parent 911f922 commit 66d0a66

File tree

3 files changed

+39
-32
lines changed

3 files changed

+39
-32
lines changed

pyvips/gvalue.py

Lines changed: 8 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -220,36 +220,17 @@ def set(self, value):
220220
memory = glib_lib.g_malloc(len(value))
221221
ffi.memmove(memory, value, len(value))
222222

223-
# this is horrible!
224-
#
225-
# * in API mode, we must have 8.6+ and use set_blob_free to
226-
# attach the metadata to avoid leaks
227-
# * pre-8.6, we just pass a NULL free pointer and live with the
228-
# leak
229-
#
230-
# this is because in API mode you can't pass a builtin (what
231-
# vips_lib.g_free() becomes) as a parameter to ffi.callback(), and
232-
# vips_value_set_blob() needs a callback for arg 2
233-
#
234-
# additionally, you can't make a py def which calls g_free() and
235-
# then use the py def in the callback, since libvips will trigger
236-
# these functions during cleanup, and py will have shut down by
237-
# then and you'll get a segv
238-
239-
if at_least_libvips(8, 6):
223+
# In API mode, we use set_blob_free in a backwards compatible way.
224+
# For pre-8.6 libvipses, in ABI mode, we declare the type of the
225+
# free func in set_blob incorrectly so that we can pass g_free
226+
# at runtime without triggering an exception.
227+
if pyvips.API_mode or at_least_libvips(8, 6):
240228
vips_lib.vips_value_set_blob_free(self.gvalue,
241229
memory, len(value))
242230
else:
243-
# we declare the type of the free func in set_blob incorrectly
244-
# so that we can pass g_free at runtime without triggering an
245-
# exception
246-
if pyvips.API_mode:
247-
vips_lib.vips_value_set_blob(self.gvalue,
248-
ffi.NULL, memory, len(value))
249-
else:
250-
vips_lib.vips_value_set_blob(self.gvalue,
251-
glib_lib.g_free,
252-
memory, len(value))
231+
vips_lib.vips_value_set_blob(self.gvalue,
232+
glib_lib.g_free,
233+
memory, len(value))
253234
else:
254235
raise Error('unsupported gtype for set {0}, fundamental {1}'.
255236
format(type_name(gtype), type_name(fundamental)))

pyvips/pyvips_build.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,35 @@
99
if pkgconfig.installed('vips', '< 8.2'):
1010
raise Exception('pkg-config "vips" is too old -- need libvips 8.2 or later')
1111

12+
major, minor, micro = [int(s) for s in pkgconfig.modversion('vips').split('.')]
13+
1214
ffibuilder = FFI()
1315

16+
# vips_value_set_blob_free and vips_area_free_cb compat for libvips < 8.6
17+
compat = '''
18+
int
19+
vips_area_free_cb(void *mem, VipsArea *area)
20+
{
21+
g_free(mem);
22+
23+
return 0;
24+
}
25+
26+
void
27+
vips_value_set_blob_free(GValue* value, void* data, size_t length)
28+
{
29+
vips_value_set_blob(value, (VipsCallbackFn) vips_area_free_cb,
30+
data, length);
31+
}
32+
''' if major == 8 and minor < 6 else ''
33+
1434
ffibuilder.set_source("_libvips",
15-
r"""
35+
f"""
1636
#include <vips/vips.h>
37+
{compat}
1738
""",
1839
**pkgconfig.parse('vips'))
1940

20-
major, minor, micro = [int(s) for s in pkgconfig.modversion('vips').split('.')]
2141

2242
features = {
2343
'major': major,

pyvips/vdecls.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,6 @@ def cdefs(features):
110110
void vips_value_set_array_int (GValue* value,
111111
const int* array, int n );
112112
void vips_value_set_array_image (GValue *value, int n);
113-
typedef void (*FreeFn)(void* a);
114-
void vips_value_set_blob (GValue* value,
115-
FreeFn free_fn, void* data, size_t length);
116113
117114
int g_value_get_boolean (const GValue* value);
118115
int g_value_get_int (GValue* value);
@@ -405,6 +402,15 @@ def cdefs(features):
405402
int vips_cache_get_max_files();
406403
'''
407404

405+
# we must only define this in ABI mode ... in API mode we use
406+
# vips_value_set_blob_free in a backwards compatible way
407+
if not features['api']:
408+
code += '''
409+
typedef void (*FreeFn)(void* a);
410+
void vips_value_set_blob (GValue* value,
411+
FreeFn free_fn, void* data, size_t length);
412+
'''
413+
408414
if _at_least(features, 8, 5):
409415
code += '''
410416
char** vips_image_get_fields (VipsImage* image);

0 commit comments

Comments
 (0)