Ответ 1
Директивы прагмы должны быть вставлены непосредственно в файл include. Таким образом, везде, где вы включаете файл, объявляется неуправляемый раздел.
Извините, что вам нужно изменить свой файл include.
У меня есть проект, который включает в себя некоторые высокопроизводительные родные заголовки С++, которые сильно используют шаблоны. Для этого проекта мы также обертываем заголовки и добавляем некоторый код, чтобы показать функциональность С# и других языков .NET. Мы будем называть этот заголовок "layout.h", и мы будем считать его третьим заголовком, который я не могу изменить.
В смешанной сборке С++/CLI относительно легко сделать ошибку и # включить из места в коде, где #pragma неуправляемый (или #pramga управляется (push, off)). Когда это происходит, шаблоны генерируют IL, и я получаю дополнительные управляемые/неуправляемые переходы при запуске кода, а производительность идет вниз.
Мой вопрос заключается в том, есть ли способ выполнить проверку времени компиляции перед #include, чтобы компиляция завершилась неудачно, если я случайно #including из неправильного контекста.
// File1.cpp, compiled in a mixed mode C++/CLI assembly with /clr
ASSERT_UNMANAGED()
#include <layout.h>
Моя наивная 1-я попытка проверена #ifdef _MANAGED, но это всегда определяется, находится ли я в неуправляемом блоке кода #pragma или нет.
Директивы прагмы должны быть вставлены непосредственно в файл include. Таким образом, везде, где вы включаете файл, объявляется неуправляемый раздел.
Извините, что вам нужно изменить свой файл include.
Вы можете написать код ASSERT_MANAGED
или ASSERT_UNMANAGED
, который будет использовать конструкцию, доступную ТОЛЬКО при компиляции управляемых или неуправляемых. Объявление ref class
- это пример, доступный только при использовании управляемого.
Это несколько грязное решение, но оно будет работать.
Здесь возможное решение, использующее тот факт, что встроенные функции всегда компилируются как нативный (неуправляемый) код:
#include <intrin.h>
#define ASSERT_UNMANAGED() \
int TestFunc(void) { \
__pragma(warning(push)) \
__pragma(warning(error:4793)) \
auto aumt = [] () { return _bextr_u64(65537, 0, 8); }; \
__pragma(warning(pop)) \
return int(aumt()); }
#pragma unmanaged // Comment out this line and the assertion fails!
ASSERT_UNMANAGED()
#pragma managed
ОБНОВЛЕНИЕ: Конечно, если вам нужны предупреждения, а не ошибка компиляции, вы можете удалить 3 строки __pragma(warning())
.