Преобразовать / портировать код PDWORD в C#

#c# #c #arrays #integer

#c# #c #массивы #целое число

Вопрос:

Я конвертирую некоторый код с C на C #, и мне нужно некоторое представление о том, как работать с такими строками:

 PDWORD rgb32_data = (PDWORD) malloc(640*480*4);
  

Насколько я понимаю, PDWORD тип представляет целое число без знака (32 бита). Какая была бы хорошая стратегия C # для реализации подобной структуры?

РЕДАКТИРОВАТЬ: Я понял, что мне нужно использовать IntPtr для замены PDWORD, но IntPtr будет содержать одно значение, а не множество значений, как в массиве. Есть предложения по C #?

EDIT2: Uint[] s у меня не работают — к сожалению, единственный способ заставить программу скомпилироваться со всеми ее зависимостями — это ввести IntPtr в качестве аргумента, а не IntPtr[] .

Спасибо.

РЕДАКТИРОВАТЬ — я отметил решение, кроме того, мне нужно было сделать следующее:

Поскольку мне нужен был приведение IntPtr, я добавил этот код

         IntPtr rgb32_ptr; 
        GCHandle handle = GCHandle.Alloc(rgb32_data, GCHandleType.Pinned);
        try
        {
            rgb32_ptr = handle.AddrOfPinnedObject();
        }
        finally
        {
            if (handle.IsAllocated)
            {
                handle.Free();
            }
        }
  

чтобы получить то же самое значение IntPtr.

Ответ №1:

Согласно MSDN, PDWORD определяется как:

 typedef DWORD*  PDWORD;
  

Итак, это указатель на a DWORD , который, как также говорит MSDN, является 32-разрядным целым числом без знака — другими словами, a uint .

Обратите внимание, что ваша строка кода C выделяет память для массива размером 640 * 480 = 307 200 DWORD секунд.

Вы могли бы перевести это непосредственно как:

 uint[] rgb32_data = new uint[640 * 480];
  

Но код может действительно захотеть использовать его просто как последовательность байтов в памяти, поэтому вместо этого вы можете захотеть использовать массив байтов

 byte[] rgb32_data = new byte[640 * 480 * 4];
  

и используйте методы в классе BitConverter (особенно ToInt32() метод), если вы считаете, что это ближе к тому, как оригинальная программа обрабатывает данные.

Комментарии:

1. Хороший улов. Я должен был понять, что он хочет выделить массив. Поскольку исходный код делает это PDWORD , я подозреваю, что первое — массив целых чисел без знака.

2. Да, это то, что я сделал. В дополнение к этому, поскольку мне требовалось приведение IntPtr, я добавил этот код GCHandle handle = GCHandle. Выделить (rgb32Source, GCHandleType. Закреплено); попробуйте { rgb32_data = обрабатывать. Добавить prof pinnedobject(); } наконец { если (обрабатывать. Выделено) { дескриптор. Освободить(); } }

Ответ №2:

Вы можете использовать небезопасные указатели и Marshal.AllocHGlobal()

     Program()
    {            
        unsafe
        {
            IntPtr ptr = Marshal.AllocHGlobal(640 * 480 * 4);

            uint* ptr2 = (uint*)ptr.ToPointer();

            for (int i = 0; i < 640*480; i  )
            {
                ptr2[i] = 0;
            }

            Marshal.FreeHGlobal(ptr);
        }
    }
  

Ответ №3:

PDWORD — это указатель на 32-разрядное целое число без знака. В C # это было бы ref uint32 . Или IntPtr если вы используете 32-разрядную среду выполнения.

Это зависит от того, как вы собираетесь его использовать. Если вы передаете его в неуправляемый код, то я бы предложил ref UInt32 . Если вы используете его для выделения памяти (например, возвращаемое значение из функции Windows API, которая выделяет память), тогда вы хотели бы использовать IntPtr .

Комментарии:

1. Как бы я использовал IntPtr? Я добавил это в свою правку. Разве IntPtr не выдал бы мне просто одно значение? Какой тип ссылки я мог бы использовать?

2. @sparkFinder: Вам просто нужно выделить массив. Ответ Лукаса Джонса, вероятно, то, что вы ищете.

3. Это то, что я сделал изначально — к сожалению, единственный способ заставить программу скомпилироваться со всеми ее зависимостями — это ввести IntPtr в качестве аргумента, а не IntPtr[]

4. @sparkFinder: Я не могу представить, что здесь нужно использовать массив IntPtr . Можете ли вы предоставить нам больше контекста?

5. Мне сложно это сделать, просто методу, который в конечном итоге принимает rgb32_data в качестве аргумента, нужен IntPtr в качестве аргумента. Как я смогу упаковать свой код, используя его? Я думал использовать IntPtr [] вместо uint [], который также был предложен здесь, но я могу использовать только IntPtr (что и пытался сказать мой предыдущий комментарий). Я новичок в C #, поэтому, возможно, я просто упускаю из виду какую-то ключевую концепцию. Приветствия 🙂

Ответ №4:

PDWORD — это указатель на DWORD. Существует несколько вариантов преобразования кода в C # в зависимости от того, как он будет использоваться.

Для самого DWORD вы можете использовать System.UInt32 в качестве эквивалента. Маршалировать.В качестве замены можно использовать AllocHGlobal, но нам нужно посмотреть, как он будет использоваться. Вы обращаетесь к памяти самостоятельно или, возможно, передаете ее другой неуправляемой функции?