Skip to content

Commit

Permalink
Fix -Wincompatible-function-pointer-types warning on Clang (#461)
Browse files Browse the repository at this point in the history
Resolves: #459.
  • Loading branch information
kleisauke authored Apr 18, 2024
1 parent ceb6f53 commit 9c7e151
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 38 deletions.
35 changes: 8 additions & 27 deletions pyvips/gvalue.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,36 +226,17 @@ def set(self, value):
memory = glib_lib.g_malloc(len(value))
ffi.memmove(memory, value, len(value))

# this is horrible!
#
# * in API mode, we must have 8.6+ and use set_blob_free to
# attach the metadata to avoid leaks
# * pre-8.6, we just pass a NULL free pointer and live with the
# leak
#
# this is because in API mode you can't pass a builtin (what
# vips_lib.g_free() becomes) as a parameter to ffi.callback(), and
# vips_value_set_blob() needs a callback for arg 2
#
# additionally, you can't make a py def which calls g_free() and
# then use the py def in the callback, since libvips will trigger
# these functions during cleanup, and py will have shut down by
# then and you'll get a segv

if at_least_libvips(8, 6):
# In API mode, we use set_blob_free in a backwards compatible way.
# For pre-8.6 libvipses, in ABI mode, we declare the type of the
# free func in set_blob incorrectly so that we can pass g_free
# at runtime without triggering an exception.
if pyvips.API_mode or at_least_libvips(8, 6):
vips_lib.vips_value_set_blob_free(self.gvalue,
memory, len(value))
else:
# we declare the type of the free func in set_blob incorrectly
# so that we can pass g_free at runtime without triggering an
# exception
if pyvips.API_mode:
vips_lib.vips_value_set_blob(self.gvalue,
ffi.NULL, memory, len(value))
else:
vips_lib.vips_value_set_blob(self.gvalue,
glib_lib.g_free,
memory, len(value))
vips_lib.vips_value_set_blob(self.gvalue,
glib_lib.g_free,
memory, len(value))
else:
raise Error('unsupported gtype for set {0}, fundamental {1}'.
format(type_name(gtype), type_name(fundamental)))
Expand Down
34 changes: 26 additions & 8 deletions pyvips/pyvips_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,6 @@
if pkgconfig.installed('vips', '< 8.2'):
raise Exception('pkg-config "vips" is too old -- need libvips 8.2 or later')

ffibuilder = FFI()

ffibuilder.set_source("_libvips",
r"""
#include <vips/vips.h>
""",
**pkgconfig.parse('vips'))

# pkgconfig 1.5+ has modversion ... otherwise, use a small shim
try:
from pkgconfig import modversion
Expand All @@ -31,6 +23,32 @@ def modversion(package):

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

ffibuilder = FFI()

# vips_value_set_blob_free and vips_area_free_cb compat for libvips < 8.6
compat = '''
int
vips_area_free_cb(void *mem, VipsArea *area)
{
g_free(mem);
return 0;
}
void
vips_value_set_blob_free(GValue* value, void* data, size_t length)
{
vips_value_set_blob(value, (VipsCallbackFn) vips_area_free_cb,
data, length);
}
''' if major == 8 and minor < 6 else ''

ffibuilder.set_source("_libvips",
r"""
#include <vips/vips.h>
""" + compat,
**pkgconfig.parse('vips'))

features = {
'major': major,
'minor': minor,
Expand Down
12 changes: 9 additions & 3 deletions pyvips/vdecls.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,6 @@ def cdefs(features):
void vips_value_set_array_int (GValue* value,
const int* array, int n );
void vips_value_set_array_image (GValue *value, int n);
typedef void (*FreeFn)(void* a);
void vips_value_set_blob (GValue* value,
FreeFn free_fn, void* data, size_t length);
int g_value_get_boolean (const GValue* value);
int g_value_get_int (GValue* value);
Expand Down Expand Up @@ -405,6 +402,15 @@ def cdefs(features):
int vips_cache_get_max_files();
'''

# we must only define this in ABI mode ... in API mode we use
# vips_value_set_blob_free in a backwards compatible way
if not features['api']:
code += '''
typedef void (*FreeFn)(void* a);
void vips_value_set_blob (GValue* value,
FreeFn free_fn, void* data, size_t length);
'''

if _at_least(features, 8, 5):
code += '''
char** vips_image_get_fields (VipsImage* image);
Expand Down

0 comments on commit 9c7e151

Please sign in to comment.