Простой ответ: везде, где находится ваш exe-файл, ALL DLL EmguCV и DLL OpenCV. Что происходит во время разработки, не имеет никакого отношения к развертыванию.
Мне удобно разместить DLL EmguCV в папке с моим EXE, а в папке с именем x64 помещены все DLL-файлы OpenCV. Папка x64 - это ALSo в той же папке, что и ваш exe.
Doug
Это полезно для взаимодействия с неуправляемым кодом. Любые указатели, переданные неуправляемым функциям, должны быть исправлены (ака. Закреплены), чтобы сборщик мусора не перемещал базовую память.
Если вы используете P / Invoke, тогда маршаллер по умолчанию будет связывать объекты для вас , Иногда необходимо выполнить настраиваемую сортировку, и иногда необходимо связать объект дольше, чем длительность одного вызова P / Invoke.
поведение стиля reinterpret_cast
Если вы выполняете манипуляции с битами, это может быть невероятно полезно
, многие реализации высокопроизводительных хэш-кодов используют UInt32 для хеш-значения (это упрощает смену). Поскольку .Net требует Int32 для метода, который вы хотите быстро преобразовать uint в int. Поскольку не имеет значения фактическое значение, только то, что все биты в значении сохранены, требуется реинтерпрет.
public static unsafe int UInt32ToInt32Bits(uint x)
{
return *((int*)(void*)&x);
}
отмечает, что именование моделируется на BitConverter.DoubleToInt64Bits
Продолжая в хешинговой вене, преобразование структуры на основе стека в байт * позволяет легко использовать хэш-функции байта:
// from the Jenkins one at a time hash function
private static unsafe void Hash(byte* data, int len, ref uint hash)
{
for (int i = 0; i < len; i++)
{
hash += data[i];
hash += (hash << 10);
hash ^= (hash >> 6);
}
}
public unsafe static void HashCombine(ref uint sofar, long data)
{
byte* dataBytes = (byte*)(void*)&data;
AddToHash(dataBytes, sizeof(long), ref sofar);
}
также небезопасно (от 2.0 и далее) позволяет использовать stackalloc. Это может быть очень полезно в ситуациях с высокой производительностью, когда необходим небольшой массив переменной длины, такой как временное пространство.
Все эти применения были бы крепко в «только если ваше приложение действительно нуждается в производительности» и, следовательно, неприменим для общего использования, но иногда вам это действительно нужно.
исправлено, если вы хотите взаимодействовать с некоторой полезной неуправляемой функцией (их много), которая принимает c-style массивы или строки. Таким образом, это не только по соображениям производительности, но и по правильности в сценариях взаимодействия.
Я считаю, что небезопасный код используется, если вы хотите получить доступ к чему-то вне среды выполнения .NET, т.е. это не управляемый код (без сбора мусора и т. д.). Сюда входят необработанные обращения к API Windows и всему этому джазу.
Нам пришлось использовать фиксированное, когда адрес передается в устаревшую C DLL. Поскольку DLL поддерживала внутренний указатель на вызовы функций, все ад бы разрывался, если GC сжимал кучу и перемещал вещи вокруг.
Это говорит о том, что разработчики .NET Framework хорошо справлялись с проблемным пространством - убедитесь, что среда «управляемого кода» может делать все, что может сделать традиционный (например, C ++) подход с его небезопасным кодом / указатели. Если это не возможно, небезопасные / фиксированные функции есть, если они вам понадобятся. Я уверен, что у кого-то есть пример, где нужен небезопасный код, но на практике он редко встречается - это скорее точка, не так ли? :)
Я использовал небезопасные блоки для управления Bitmap-данными. Необработанный указатель-доступ значительно быстрее, чем SetPixel / GetPixel.
unsafe
{
BitmapData bmData = bm.LockBits(...)
byte *bits = (byte*)pixels.ToPointer();
// Do stuff with bits
}
«фиксированный» и «небезопасный» обычно используется при выполнении взаимодействия или при необходимости дополнительной производительности. То есть. String.CopyTo () использует небезопасные и фиксированные в своей реализации.