Intel TBB — InitializeCriticalSectionEx: идентификатор не найден, ошибка компилятора

У меня есть проект VS (C ++), основанный на OpenCV и TBB, поэтому я создал листы свойств для каждой библиотеки и включил их в проект. Все работало нормально, и код скомпилирован.

Вчера я начал использовать vcpkg менеджер пакетов. Я установил OpenCV и TBB через vcpkg, и все, казалось, работало. Я создал пустой проект, включил заголовки обоих и проверил, работают ли новые скомпилированные библиотеки. После проверки я вернулся к своему основному проекту и удалил листы свойств, чтобы я мог использовать библиотеки из vcpkg. Я не изменил код с момента последней успешной компиляции.

Но когда я пытаюсь скомпилировать код сейчас, я получаю эту ошибку два раза (в main.cpp и в подмодуле)

tbb \ crit_section.h (53): ошибка C3861: «InitializeCriticalSectionEx»: идентификатор не найден

Кто-нибудь знает, что здесь происходит или почему происходит эта ошибка?

Обновить

Я нашел ошибку сам. Я добавляю тег poco-library, потому что на самом деле это конфликт между TBB и Poco.

3

Решение

Я нашел источник проблемы, и это на самом деле не имеет ничего общего с TBB, но с Библиотека Poco.

Рассмотрим минимальный пример:

#include <Poco/Poco.h>
#include <tbb/tbb.h>

void main()
{
}

Это вызовет ошибку компилятора.

Когда в том числе tbb.h, critical_section.h включен в строку 51 tbb.h. Тем не мение, ciritcal_section.hpp включает в себя машина / winwdows_api.h который выглядит следующим образом (ненужные вещи вырезаны):

Т / машина / 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 не определено.

Эта проблема отслеживается машина / 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 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. Что теперь происходит:

  1. Включить заголовки Poco
  2. Задавать _WIN32_WINNT в Windows XP
  3. Включить заголовки окон (версия Windows XP, из-за 2)
  4. Сброс _WIN32_WINNT в Windows 8.1
  5. Включить заголовки TBB (заголовки Windows уже включены, поэтому TBB не нужно включать их снова в Т / windows_api.h)
  6. TBB проверяет версию Windows через _WIN32_WINNT и распознает Windows 8.1 (как установлено Poco)
  7. TBB думает InitializeCriticalSectionEx определяется, потому что версия Windows 8.1 (или это? Poco говорит: получить рект) и InitializeCriticalSectionEx определяется начиная с Windows Vista.
  8. К сожалению, 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).

Обновить

Poco по этому вопросу. Обновления можно найти Вот.

8

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

Других решений пока нет …

По вопросам рекламы [email protected]