Я нашел источник проблемы, и он на самом деле не имеет ничего общего с TBB, а с библиотекой Poco .
Рассмотрим минимальный пример:
#include <Poco/Poco.h>
#include <tbb/tbb.h>
void main()
{
}
Это приведет к ошибке компилятора.
Отслеживание пути
При включении tbb.h , crit_section.h включается в строку 51 tbb.h . Тем не менее, ciritcal_section.hpp включает machine / winwdows_api.h , который выглядит так (ненужные вещи вырезаны):
TBB / машина / winwdows_api.h:
#if _WIN32 || _WIN64
#include <windows.h>
#if _WIN32_WINNT < 0x0600
#define InitializeCriticalSectionEx inlineInitializeCriticalSectionEx
inline BOOL WINAPI inlineInitializeCriticalSectionEx( LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount, DWORD )
{
return InitializeCriticalSectionAndSpinCount( lpCriticalSection, dwSpinCount );
}
#endif
Как видите, windows.h включено перед проверкой макроса _WIN32_WINNT
. Этот макрос определен в sdkddkver.h (который включен в windows.h ), если он еще не определен (в моем случае он установлен в Win10):
sdkddkver.h:
#if !defined(_WIN32_WINNT) && !defined(_CHICAGO_)
#define _WIN32_WINNT 0x0A00
#endif
В windows.h макрос _WIN32_WINNT
определяет, какая версия заголовочных файлов Windows на самом деле включена. Если для _WIN32_WINNT
установлена более ранняя версия, чем в Windows Vista, функция InitializeCriticalSectionEx
не определена.
Эта проблема отслеживается machine / winwdows_api.h (как вы можете видеть в блоке кода этого файла), просто определяя макрос InitializeCriticalSectionEx
, который вызывает соответствующую альтернативную функцию.
Пока все хорошо.
проблема
Корень всего зла лежит в Poco / UnWindows.h библиотеки Poco. При включении заголовка poco в какой-то момент будет включен UnWindows.h .
Poco / UnWindows.h (сокращенно):
#if defined(_WIN32_WINNT)
#if (_WIN32_WINNT < 0x0501)
#error Unsupported Windows version.
#endif
#elif defined(NTDDI_VERSION)
#if (NTDDI_VERSION < 0x05010100)
#error Unsupported Windows version.
#endif
#elif !defined(_WIN32_WINNT)
#define _WIN32_WINNT 0x0501
#define NTDDI_VERSION 0x05010100
#endif
#endif
#include <windows.h>
Препроцессор проверяет, если _WIN32_WINNT
уже определено, и если нет, устанавливает его в 0x0501, который является Windows XP. После включается windows.h . В предыдущей главе я упоминал, что _WIN32_WINNT
определяет, какая версия заголовочных файлов Windows на самом деле включена.
Теперь представьте, самое первое включение в наш проект - заголовок от Poco. Это означает, что _WIN32_WINNT
будет установлен на Windows XP, а windows.h будет включать в себя заголовки Windows Windows XP (что imo уже является плохим признаком).
Но не волнуйтесь, все ухудшается.
Если мы проследим иерархию включения на один уровень выше, мы достигнем Poco / Platform_WIN32.h .
Poco / Platform_WIN32.h (сокращенно):
#include "Poco/UnWindows.h"
...
#if defined (_WIN32_WINNT_WINBLUE)
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
#define _WIN32_WINNT _WIN32_WINNT_WINBLUE
...
Забавно, не правда ли? Во-первых, он включает UnWindows.h , который устанавливает _WIN32_WINNT
и вызывает включение заголовков Windows XP, а затем переопределяет _WIN32_WINNT
как Windows 8.1. Я понятия не имею, почему это происходит, возможно, есть веская причина, ИДК.
Если мы посмотрим на минимальный пример в самом верху, то увидим, что Poco включен до TBB. Что теперь происходит:
- Включить заголовки Poco
- Установить
_WIN32_WINNT
для Windows XP
- Включить заголовки Windows (версия Windows XP, из-за 2)
- Сброс
_WIN32_WINNT
до Windows 8.1
- Включить заголовки TBB (заголовки windows уже включены, поэтому TBB не нужно включать их снова в tbb / windows_api.h )
- TBB проверяет версию Windows через
_WIN32_WINNT
и распознает Windows 8.1 (как установлено Poco)
- TBB считает, что
InitializeCriticalSectionEx
определено, потому что версия Windows - 8.1 (или это? Poco говорит: get rekt), а InitializeCriticalSectionEx
определяется с Windows Vista.
- К сожалению, Poco обеспечил загрузку заголовков Windows XP, поэтому компилятор говорит: нет.
Решение
Либо заранее включите windows.h , либо заранее установите _WIN32_WINNT
:
#define _WIN32_WINNT 0x0A00 // either this
#include <Windows.h> // or this
#include <Poco/Poco.h>
#include <tbb/tbb.h>
void main()
{
}
Может быть, кто-то из авторов Poco может кое-что прояснить здесь. Версия Poco - 1.8.1-1, собранная с x64 (через vcpkg).
Обновление
Поко по вопросу. Обновления можно найти здесь .