Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Usage troubles under Windows #183

Closed
West14 opened this issue Jan 23, 2023 · 27 comments
Closed

Usage troubles under Windows #183

West14 opened this issue Jan 23, 2023 · 27 comments

Comments

@West14
Copy link

West14 commented Jan 23, 2023

Hello!

I'm trying to use your library under Windows 10, but there are few problems that I can't figure out how to solve.

  1. "The printf check" fails. It can't find printf function.
An exception occurred: [FFI\Exception] Failed resolving C function 'printf' in src\addons\Bubuni\LibVips\vendor\jcupitt\vips\src\FFI.php on line 208
#0 src\addons\Bubuni\LibVips\vendor\jcupitt\vips\src\FFI.php(208): FFI::cdef('    int printf(...')
#1 src\addons\Bubuni\LibVips\vendor\jcupitt\vips\src\FFI.php(116): Jcupitt\Vips\FFI::init()
#2 src\addons\Bubuni\LibVips\vendor\jcupitt\vips\src\VipsOperation.php(80): Jcupitt\Vips\FFI::vips()
#3 src\addons\Bubuni\LibVips\vendor\jcupitt\vips\src\VipsOperation.php(225): Jcupitt\Vips\VipsOperation::newFromName('black')
#4 src\addons\Bubuni\LibVips\vendor\jcupitt\vips\src\Image.php(1290): Jcupitt\Vips\VipsOperation::callBase('black', NULL, Array)
#5 test.php(28): Jcupitt\Vips\Image::__callStatic('black', Array)
#6 {main}

When I comment it, things start to work.

I also want to ask: what is the latest supported libvips version? When i try 8.14. I get errors like this.
image
image

I tried 8.13, but it does not give the expected result (I'll attach reproduce example if needed).
libvips 8.9 seems to be fine.

PHP version:

PHP 7.4.27 (cli) (built: Dec 14 2021 19:52:13) ( ZTS Visual C++ 2017 x64 )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Xdebug v3.1.6, Copyright (c) 2002-2022, by Derick Rethans
@jcupitt
Copy link
Member

jcupitt commented Jan 24, 2023

Hi @West14,

Thanks for reporting this. That's odd, I'd expect ffi to find printf in your C runtime. I have a win10 VM here, I'll fire it up and try it.

@jcupitt
Copy link
Member

jcupitt commented Jan 24, 2023

When i try 8.14. I get errors like this.

I tried here and it seems to work. I downloaded:

https://github.com/libvips/build-win64-mxe/releases/download/v8.14.1/vips-dev-w64-web-8.14.1.zip

Then:

jcupi@DESKTOP-HGI6HBR MINGW64 /f/Downloads
$ unzip -qq vips-dev-w64-web-8.14.1.zip

jcupi@DESKTOP-HGI6HBR MINGW64 /f/Downloads
$ cd vips-dev-8.14/bin/

jcupi@DESKTOP-HGI6HBR MINGW64 /f/Downloads/vips-dev-8.14/bin
$ ./vips.exe black x.png 10 10

jcupi@DESKTOP-HGI6HBR MINGW64 /f/Downloads/vips-dev-8.14/bin
$

What did you download and how did you install it?

@West14
Copy link
Author

West14 commented Jan 24, 2023

./vips.exe black x.png 10 10

Problems occur when using PHP bindings. The CLI utility works fine and I have no issues with it.

@jcupitt
Copy link
Member

jcupitt commented Jan 24, 2023

So therefore I think it must be problem with the way you've installed libvips under php. You must have several different versions of eg. libglib-2.0.dll on your PATH, with an older one overriding the more recent version that libvips needs. It's quite a common library, so I expect you have installed some other package that also bundles it.

@jcupitt
Copy link
Member

jcupitt commented Jan 24, 2023

I had a read around and I agree, I think the printf test won't work on Windows. I thought with no lib it'd search the C runtime (most ffis work like this), but it seems on php it'll search the running php executable itself, but only if the platform supports backlinking (which win does not, since it's missing a run-time linker).

I'll put an if(PHP_OS_FAMILY !== "Windows"){} around that.

I removed that test and it then worked for me. Here's what I did:

Install php

I installed this php:

https://windows.php.net/downloads/releases/php-8.2.1-Win32-vs16-x64.zip

I put it in /c/php to make config simple.

I made a copy of php.ini-development with these changes:

diff --git a/php.ini-development b/php.ini
index 70c6b00..8c29d74 100644
--- a/php.ini-development
+++ b/php.ini
@@ -920,7 +920,7 @@ default_socket_timeout = 60
 ;extension=ldap

 ;extension=curl
-;extension=ffi
+extension=ffi
 ;extension=ftp
 ;extension=fileinfo
 ;extension=gd
@@ -1955,7 +1955,7 @@ ldap.max_links = -1
 ; "preload" - enabled in CLI scripts and preloaded files (default)
 ; "false"   - always disabled
 ; "true"    - always enabled
-;ffi.enable=preload
+ffi.enable=true

 ; List of headers files to preload, wildcard patterns allowed.
 ;ffi.preload=

Install libvips

I installed this libvips:

https://github.com/libvips/build-win64-mxe/releases/download/v8.14.1/vips-dev-w64-web-8.14.1.zip

Then copied the contents of the bin/ directory to bin in my windows home directory. I chose this location because it was on my PATH, though I don't know how it got there heh.


jcupi@DESKTOP-HGI6HBR MINGW64 /c/php
$ ls ~/bin
libaom.dll*               libgobject-2.0-0.dll*     libspng-0.dll*
libc++.dll*               libgsf-1-114.dll*         libtiff-6.dll*
libcairo-2.dll*           libharfbuzz-0.dll*        libunwind.dll*
libcgif-0.dll*            libheif.dll*              libvips-42.dll*
libexif-12.dll*           libimagequant.dll*        libvips-cpp-42.dll*
libexpat-1.dll*           libjpeg-62.dll*           libwebp-7.dll*
libffi-8.dll*             liblcms2-2.dll*           libwebpdemux-2.dll*
libfontconfig-1.dll*      liborc-0.4-0.dll*         libwebpmux-3.dll*
libfreetype-6.dll*        libpango-1.0-0.dll*       libxml2-2.dll*
libfribidi-0.dll*         libpangocairo-1.0-0.dll*  libz1.dll*
libgdk_pixbuf-2.0-0.dll*  libpangoft2-1.0-0.dll*    vips.exe*
libgio-2.0-0.dll*         libpixman-1-0.dll*        vipsedit.exe*
libglib-2.0-0.dll*        libpng16-16.dll*          vipsheader.exe*
libgmodule-2.0-0.dll*     librsvg-2-2.dll*          vipsthumbnail.exe*

This is a dangerous thing to do -- adding dlls to your main PATH is asking for trouble. I'd find a better way to handle this if I was trying to do this properly. I'll remove these dlls again ASAP.

Install php-vips

I downloaded a copy of php-vips-master, then went to the examples/ directory. I took a copy of the vendor/ directory from a working php-vips install I had under linux (simpler than getting composer running under win).

Then tried php-vips like this:

jcupi@DESKTOP-HGI6HBR MINGW64 /f/GIT/php-vips-master/examples
$ /c/php/php.exe watermark-text.php /f/Downloads/download.jpg x.png hello

jcupi@DESKTOP-HGI6HBR MINGW64 /f/GIT/php-vips-master/examples
$

And it made this:

x

So all working, I think.

@jcupitt
Copy link
Member

jcupitt commented Jan 24, 2023

Ah it looks like php-vips 2.1.0 is missing the printf() test, you could try that.

jcupitt added a commit that referenced this issue Jan 24, 2023
Binding printf() won't work on windows. We should find a better way to
test if ffi is enabled.

Thanks West14.

See #183
@jcupitt
Copy link
Member

jcupitt commented Jan 24, 2023

I added the platform check to php-vips master.

I tried 8.13, but it does not give the expected result (I'll attach reproduce example if needed).

Yes please, it'd be interesting to see what failed.

@West14
Copy link
Author

West14 commented Jan 24, 2023

So therefore I think it must be problem with the way you've installed libvips under php. You must have several different versions of eg. libglib-2.0.dll on your PATH, with an older one overriding the more recent version that libvips needs. It's quite a common library, so I expect you have installed some other package that also bundles it.

Thanks for the hint. Thats it!
My web-server software uses separate PATH and there was one libglib-2.0-0.dll in the nginx package.
image

Thank you very much!

Yes please, it'd be interesting to see what failed.

I will check it again and post here. Now I'm not sure I did the test right.

@West14
Copy link
Author

West14 commented Jan 24, 2023

I'll put an if(PHP_OS_FAMILY !== "Windows"){} around that.

Maybe ini_get and extension_loaded can be used?
It seems OK.
image

So we can just do the check like this:

extension_loaded('ffi') && strtolower(ini_get('ffi.enable')) == 'true'

jcupitt added a commit that referenced this issue Jan 24, 2023
thanks West14

see #183
@jcupitt
Copy link
Member

jcupitt commented Jan 24, 2023

Oh nice! I've added that and credited you.

@jcupitt
Copy link
Member

jcupitt commented Jan 24, 2023

Though I see:

$ php -r "var_dump(ini_get('ffi.enable'));"
string(1) "1"
$ php --version
PHP 8.1.7-1ubuntu3.1 (cli) (built: Nov  2 2022 13:39:03) (NTS)

Which is curious.

@West14
Copy link
Author

West14 commented Jan 24, 2023

I'm trying to find out a way how to check it easily.

This is how PHP determines if INI value is true, so perhaps a similar check could be implemented in the library?
https://github.com/php/php-src/blob/ec23f28ea8549f5c4ddbcb9c48728e82d5219ba8/Zend/zend_ini.c#L573-L583

And, of course, we must not forget about the "preload" option, which is currently not supported as far as I know.

@West14
Copy link
Author

West14 commented Jan 24, 2023

Also, we can simply check for the existence of the FFI class.
i.e.

class_exists('FFI')

This can only be used to check if an extension is loaded. The ffi.enable value has no effect on the existence of the class.

@jcupitt
Copy link
Member

jcupitt commented Jan 25, 2023

I tried the various values with php 8.1. I see:

# ffi.enable=true
$ php -r "var_dump(ini_get('ffi.enable'));"
string(1) "1"
# ffi.enable=false
$ php -r "var_dump(ini_get('ffi.enable'));"
string(0) ""
# ffi.enable=preload
$ php -r "var_dump(ini_get('ffi.enable'));"
string(7) "preload"

Sadly it seems the way ini variable values are represented changes quite a bit with the php version :(

And, of course, we must not forget about the "preload" option, which is currently not supported as far as I know.

Yes, it'd be good to support preload, but no one's done the work yet.

@SerafimArts
Copy link

You can use a simple library to check the availability of FFI: https://github.com/php-ffi/env Or just take the FFI check source code from there.

Sorry for the ad =)))

@jcupitt
Copy link
Member

jcupitt commented Feb 7, 2023

Oh nice! Thanks for the link @SerafimArts.

I don't suppose you know how to detect FFI set to preload?

@SerafimArts
Copy link

SerafimArts commented Feb 7, 2023

I don't suppose you know how to detect FFI set to preload?

$isPreload = ini_get('ffi.enable') === 'preload';

In addition, note that preload is completely equivalent to true (enabled) in CLI mode.

@jcupitt
Copy link
Member

jcupitt commented Feb 7, 2023

I noticed you have:

        // - Returns "1" in case of 'ffi.enable=true' or 'ffi.enable=1' in php.ini
        // - Returns "" (empty string) in case of 'ffi.enable=false' or 'ffi.enable=0' in php.ini
        // - Returns "0" in case of direct execution `php -dffi.enable=0 file.php`
        $config = \ini_get(self::EXT_CONFIG_NAME) ?: '0';

I think it can also be "TRUE", at least under windows and with some php versions.

@SerafimArts
Copy link

I think it can also be "TRUE", at least under windows and with some php versions.

I used to think so too https://github.com/php-ffi/env/blob/1.0.0/src/Runtime.php#L82

However, after testing it, I did not find such behavior.

Source:

[ffi]
; FFI API restriction. Possible values:
; "preload" - enabled in CLI scripts and preloaded files (default)
; "false"   - always disabled
; "true"    - always enabled
ffi.enable=true
<?php

var_dump(ini_get('ffi.enable'));

Actual:

E:\Development\php\7.4\php.exe E:\Projects\test\test.php
string(1) "1"
E:\Development\php\8.2\php.exe E:\Projects\test\test.php
string(1) "1"
PS E:\Projects\test> E:\Development\php\7.4\php.exe -d ffi.enable=true test.php
string(1) "1"

And same for 8.1 and 8.2.

I think this behavior was changed in some earlier versions (7.3 and below).

But if required, I can test for other versions up to 5.6 :D

@jcupitt
Copy link
Member

jcupitt commented Feb 7, 2023

west14 was seeing "TRUE" on windows with openserver, see: #183 (comment)

Though I don't know what php version that was.

@SerafimArts
Copy link

Yep, I saw it, but I didn’t manage to reproduce this case even if TRUE is written in capital letters.

But... Wait, there is one assumption related to the differences between NTS / TS

@SerafimArts
Copy link

SerafimArts commented Feb 7, 2023

No, there are no differences when running on PHP 7.4.33 TS

P.S. Trying to paste set variable by ini_set('ffi.enable', 'TRUE') does not affect the behavior (the value from php.ini is used instead)

@SerafimArts
Copy link

SerafimArts commented Feb 7, 2023

P.P.S. However, it is true that the printf function does not exist on Windows and the library cannot be loaded.

@West14
Copy link
Author

West14 commented Feb 7, 2023

west14 was seeing "TRUE" on windows with openserver, see: #183 (comment)

Though I don't know what php version that was.

It depends on the value in php.ini. Looks like ini_get prints the value "as is" if it's wrapped with quotes in the INI. This is the default value in the OpenServer.

@SerafimArts
Copy link

SerafimArts commented Feb 7, 2023

Yes indeed. If enclosed in quotation marks, then the "TRUE" output will be. However, this is an incorrect value and actually means "preload".

Sorry, my comment above (#183 (comment)) was incorrect, did not take this case into account. The correct (given the remark) assertion is the following:

$isPreload = !in_array(ini_get('ffi.enable'), ['1', '0', ''], true);

@effectzer0
Copy link

I have the same problem :(

@jcupitt
Copy link
Member

jcupitt commented Jun 29, 2023

This PR tries to improve library finding again, let's move discussion there.

#206

@jcupitt jcupitt closed this as completed Jun 29, 2023
@jcupitt jcupitt mentioned this issue Oct 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants