Странная ошибка: неразрешенный символ при компиляции с PHP7 в Windows

У меня странная проблема: у меня есть проект, который использует PHP7 (php7ts.lib) в этом.

PHP7 скомпилирован самостоятельно с VS 2015:

--enable-mbstring=static --with-gd=static --with-iconv=static
--enable-soap --enable-sockets --disable-ipv6 --with-dom
--disable-bcmath --disable-cgi --disable-cli --enable-embed
--with-bz2=static --enable-com-dotnet --enable-ctype
--enable-mbregex=static --disable-mbregex-backtrack --enable-odbc --with-mp

То же самое с более уменьшенным количеством параметров:

--disable-all --without-libxml --without-dom --enable-sockets
--enable-embed --enable-com-dotnet --enable-ctype --enable-odbc
--enable-debug

BZip2 тоже скомпилирован сам и работает. Компиляция PHP7 также работает, я получаю .lib а также .dll файл. Затем я компилирую проект и получаю странные ошибки:

error LNK2019: unresolved external symbol __imp__emalloc@@4 referenced in function
unresolved external symbol __imp__efree@@4
unresolved external symbol __imp__zval_dtor_func@@4
unresolved external symbol __imp__convert_to_string@@4
fatal error LNK1120: 4 unresolved externals

Проблема в том, что с VS2013 и PHP 5.6, скомпилированными мной, все работало. Странно то, что неразрешенные символы указывают на то, что не выглядит специфичным для библиотеки.

Я использую deps отсюда: http://windows.php.net/downloads/php-sdk/deps-7.0-vc14-x86.7z

Я знаю, что мне чего-то не хватает, но из этих сообщений я не вижу, чего мне не хватает.

Изменить: некоторые новые — возможно, полезные — идеи

Хорошо, теперь я могу получить больше информации, может быть, это поможет нам найти решение.

Во-первых, я строю это в режиме отладки с 32-битной архитектурой.

В cpp файл, есть эти строки (в качестве примера для __imp__efree@@4 ошибка:

#if PHP_VERSION_ID >= 70000
#   define FREE_ZVAL(z) efree_rel(z)
#endif

Когда я собираюсь к определению efree_rel(z)Я вижу эту строку (которая имеет отношение к Zend):

#define efree_rel(ptr)                          _efree((ptr) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)

Собираюсь к определению _efree, Я вижу это:

ZEND_API void   ZEND_FASTCALL _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);

Это означает, что эта функция взята из PHP7 / Zend. Эта строка была в файле zend_alloc.h, Итак, насколько я знаю, я должен посмотреть, если этот файл экспортируется в lib или же dll файл. Таким образом, вывоз экспорта дает мне (для lib):

Dump of file php7ts_debug.lib
File Type: LIBRARY
Exports
ordinal    name
_efree@@20

И для dll:

Dump of file php7ts_debug.dll
File Type: DLL
Section contains the following exports for php7ts_debug.dll
00000000 characteristics
56EAF08F time date stamp Thu Mar 17 18:59:43 2016
0.00 version
1 ordinal base
1531 number of functions
1531 number of names
ordinal hint RVA      name
192   18 0028FFE0 _efree@@20 = @ILT+24528(_efree@@20)

Я уверен, что я работаю на Corrent libпотому что переименование библиотеки дает мне ошибку, что lib пропал, отсутствует.

Но проблема еще не решена

3

Решение

Вам необходимо обновить проект до проекта VS2015.
Все неразрешенные функции имеют соглашение о вызовах ZEND_FASTCALL (zend_portability.h):

#if defined(__GNUC__) && ZEND_GCC_VERSION >= 3004 && defined(__i386__)
# define ZEND_FASTCALL __attribute__((fastcall))
#elif defined(_MSC_VER) && defined(_M_IX86) && _MSC_VER == 1700
# define ZEND_FASTCALL __fastcall
#elif defined(_MSC_VER) && _MSC_VER >= 1800 && !defined(__clang__)
# define ZEND_FASTCALL __vectorcall
#else
# define ZEND_FASTCALL
#endif

Статическая библиотека php7ts.lib была собрана с использованием соглашений о вызовах VS2015 и __vectorcall (https://msdn.microsoft.com/en-us/library/dn375768.aspx):

К именам функций добавляются два знака «at» (@@), за которыми следует число байтов (в десятичной дроби) в списке параметров.

2

Другие решения

У меня была похожая проблема в Visual Studio 2017 Community, выдающая ошибку:

error LNK2019: unresolved external symbol __imp__emalloc@@40 referenced in function "struct _zend_string * __cdecl zend_string_alloc(unsigned __int64,int)" (?zend_string_alloc@@YAPEAU_zend_string@@_KH@Z)

Решение, которое работало для меня, должно было установить Zend_Debug до 0

#define ZTS 1
//#define PHP_COMPILER_ID "VC14"#define ZEND_WIN32 1
#define PHP_WIN32 1
#define ZEND_DEBUG 0

/*
#ifdef _DEBUG
#define ZEND_DEBUG 1
#else
#define ZEND_DEBUG 0
#endif
*/

Также убедитесь, что в свойствах вашего проекта для генерации кода установлено значение Многопоточная отладка (/ MTd).

введите описание изображения здесь

2