libvips / php-vips

php binding for libvips
MIT License
604 stars 24 forks source link

php-ffi on windows fails to link to g_malloc and g_free #144

Closed jcupitt closed 2 years ago

jcupitt commented 2 years ago

Config.php tries to link to g_malloc and g_free (glib functions) in the libvips shared library. This works on linux, since it can resolve indirect dependencies, but maybe windows needs the exact shared library that contains the named function.

Experiment with directly linking to glib and gobject. ruby-vips does this and seems to work on windows.

See: https://stackoverflow.com/questions/72330264/libvips-ffi-use-on-windows-php-cannot-find-glib-functions

syslogic commented 2 years ago

This would provide it: https://github.com/GNOME/glib/blob/main/glib/gmem.c ...which reads:

Since GLib 2.46 g_malloc() is hardcoded to always use the system malloc implementation.

Also concerning g_free() ...does one even needs a library for that?

jcupitt commented 2 years ago

It's a historical accident -- glib used (10+ years ago) to have its own malloc implementation, and therefore needed its own free. These days they just use the platform malloc (thank goodness). You still need to use the g_*() versions though.

syslogic commented 2 years ago

I'm not exactly sure if the G stands for GNU or GNOME, ... but the target system might be missing the library: http://www.gnu.org/software/libc/libc.html

codercms commented 2 years ago

Hey guys! Could you give me advice how to statically link libvips with glib? I have the same issue with g_* functions.

kleisauke commented 2 years ago

This commit is also relevant here: https://github.com/kleisauke/net-vips/commit/e04c6b0997130f06a4af2bf66c9055a529024dd1. I think there are at least 3 ways to solve this (ordered from easy to difficult):

  1. Split the GLib and GObject symbols into a separate string and use libglib-2.0-0.dll and libgobject-2.0-0.dll respectively as the name of the shared library on Windows. This is not necessary on Linux and macOS.
  2. Build and distribute libvips on Windows as a single shared library with the GLib and GObject symbols exported. See e.g. the single-shared branch.
  3. Do the same as above, but create a compatibility layer in libvips that wraps all GLib and GObject symbols rather than exporting them (e.g. g_object_unref becomes vips_object_unref, see: https://github.com/libvips/libvips/discussions/2788). This would also require an update to the binding to use this new API.

Note that point 2 would break compatibility with the shared Windows builds, plus all libvips bindings based on FFI needs to be updated to avoid libglib-2.0-0.dll and libgobject-2.0-0.dll. Point 3 has the same disadvantages as point 2, plus would break backwards compatibility with older libvips versions (as it uses those new symbols).

Since this is only a issue on Windows, I think point 1 is the most straightforward. I might look into making a PR somewhere tomorrow.

kleisauke commented 2 years ago

I just opened PR https://github.com/libvips/php-vips/pull/146 for this. Any testing would be welcome (especially on Windows 32-bit).

codercms commented 2 years ago

@kleisauke just tested your PR on x64 Windows (currently I don't have win x86). It works fine!

Code: ```php width}x{$res->height}, {$res->format}, {$res->coding}, {$res->interpretation}, {$res->bands}"); } echo PHP_EOL; echo "Thumbnail write test" . PHP_EOL; foreach ($paths as $path) { var_dump($path); $filename = pathinfo($path, PATHINFO_FILENAME); $res = Vips\Image::thumbnail_buffer(file_get_contents($path), 600, [ 'size' => 'down', 'export_profile' => 'srgb', ]); var_dump("{$res->width}x{$res->height}, {$res->format}, {$res->coding}, {$res->interpretation}, {$res->bands}"); $res->writeToFile("thumb_{$filename}.jpg", [ 'optimize_coding' => true, 'strip' => true, 'interlace' => true, 'background' => 255, 'Q' => 90, ]); $res = Vips\Image::thumbnail($path, 600, [ 'size' => 'down', 'export_profile' => 'srgb', ]); $buf = $res->writeToBuffer(".jpg", [ 'optimize_coding' => true, 'strip' => true, 'interlace' => true, 'background' => 255, 'Q' => 90, ]); file_put_contents("thumb2_{$filename}.jpg", $buf); } ```
Output: ``` PS C:\Users\user\Documents\PhpProjects\php-img\php-vips-fork> php test.php File open test string(53) "C:\Users\user\Pictures\photo_2021-01-15_17-04-50.jpg" string(30) "960x1280, uchar, none, srgb, 3" string(37) "C:\Users\user\Pictures\Untitled2.png" string(31) "1025x1137, uchar, none, srgb, 4" string(53) "C:\Users\user\Pictures\fox.profile0.8bpc.yuv420.avif" string(30) "1204x800, uchar, none, srgb, 3" Thumbnail write test string(53) "C:\Users\user\Pictures\photo_2021-01-15_17-04-50.jpg" string(29) "450x600, uchar, none, srgb, 3" string(37) "C:\Users\user\Pictures\Untitled2.png" string(29) "541x600, uchar, none, srgb, 4" string(53) "C:\Users\user\Pictures\fox.profile0.8bpc.yuv420.avif" string(29) "600x399, uchar, none, srgb, 3" ```