2014-09-12 7 views
1

Это аналогично следующий С.О. вопрос:Как данные типа, указываемые указателем void на массив с фиксированным размером int в C#?

cast-void-pointer-to-integer-array

c-pointers-pointing-to-an-array-of-fixed-size

Однако разница в том, что я хочу, чтобы добиться этого в C# с помощью «небезопасной» функции, через которую мы можем использовать указатели ,

например.

Следующий код работает в C:

int (*arr)[10] = (int (*)[10]) ptr; 

где 'PTR' является недействительным указатель. Как это может быть достигнуто в C#?

+0

Как вы получаете указатель на C#? Вы можете начать с 'int *' или вы должны получить его как таковой. Если вы получите 'void *', вам нужно будет использовать его, чтобы использовать его. – xxbbcc

+0

Не могли бы вы объяснить, почему именно вы хотите это сделать? Кроме того, я считаю, что система типа C# не имеет фиксированных массивов. – svick

+0

@xxbbcc и: Я понимаю, что могу наложить указатель на указатель на указатель на int, однако я хочу, чтобы это было выполнено в массив фиксированной длины. Иногда это становится необходимым, когда есть некоторая стандартная функция сторонней библиотеки, которая принимает массив фиксированной длины как входной. например void standardFunction (int []). Я не могу передать только целочисленный указатель на эту функцию. – genonymous

ответ

0

Я не совсем уверен, что это то, что вы ищете, но один пример будет выглядеть так:

int[] items = new int[10]; 

unsafe 
{ 
    fixed (int* pInt = &items[0]) 
    { 
     // At this point you can pass the pointer to other functions 
     // or read/write memory using it. 
     *pInt = 5; 
    } 
} 

При принятии адрес массива, вы должны принять адрес первый элемент в массиве - следовательно, &items[0] в приведенном выше примере.

Если вы получаете указатель в качестве параметра void* функции, вы должны бросить его внутри функции:

public static unsafe void F (void* pMem) 
{ 
    int* pInt = (int*) pMem; 

    // Omitted checking the pointer here, etc. This is something 
    // you'd have to do in a real program. 
    *pInt = 1; 
} 

Если вы получаете void* от внешнего источника, вы должны каким-то образом узнать, сколько байты (или int и т. д.) безопасны для доступа через указатель. Данные могут быть разделены специальным значением (например, завершение 0 или что-то еще), или вам понадобится счет или байты/элементы для безопасного доступа к памяти через указатель.

Update

Вот пример вызова неуправляемых функций реализованы в C:

// Function declaration in C 
#define EXPORTFUNC __declspec(dllexport) 
#define MYDLLAPI __declspec(nothrow) WINAPI 

EXPORTFUNC int MYDLLAPI MyFunc1 (byte* pData, int nDataByteCount); 

// Import function in C# 
[DllImport ("My.dll")] 
private static extern int MyFunc1 (byte* pData, int nDataByteCount); 

// Call function with data (in unsafe class/method) 
byte[] byData = GetData (...); // returns byte array with data 

fixed (byte* pData = byData) 
{ 
    int nResult = MyFunc1 (pData, byData.Length); 

    ... 
} 

MSDN имеет больше примеров различных операций с указателями. Кроме того, вот еще article о маршалинговых массивах.

+0

Спасибо за ответ.Я знаю, что я могу получить доступ к памяти, указанной указателем void, заставляя ее указывать указатель на int, а затем увеличивать указатель, а затем снова получать доступ к следующему местоположению и так далее. Однако, если мне нужно передать эти данные в какую-либо другую стандартную стороннюю функцию, которая принимает массив фиксированного размера, я не могу контролировать вышеуказанную логику в этой третьей стандартной функции, потому что я не могу ее редактировать, и я не должен ее редактировать. – genonymous

+0

@genonymous Это зависит от того, что ожидает функция третьей стороны. Если он ожидает 'int *' для массива из 5 элементов, то в C# вы можете создать массив из 5 'int'-s, получить адрес первого элемента и затем передать этот указатель на сторонний вызов. Массивы непрерывны, поэтому зная адрес первого элемента, размер элемента и количество элементов в массиве сообщают вам все о массиве. – xxbbcc

+0

@genonymous Я добавил небольшой пример вызова внешней функции для вас. – xxbbcc

0

Вы можете просто бросить его на int* указатель .. надеясь на лучшее .. очевидно:

// unsafe {} 

var a = stackalloc int[5]; 
a[0] = 1; 
a[1] = 2; 
a[2] = 3; 
a[3] = 4; 
a[4] = 5; 

var v = (void*) a; // cast to void as example 

for (var i = 0; i < 5; i++) 
    Console.WriteLine((*(int*)v)++); // back to int - 1, 2, 3, 4, 5 

Это сказал .. вы должны быть осторожны варьироваться с проверкой границ. AFAIK нет прямого перевода, который допускает оценки.

+0

Спасибо за ответ. Но я знаю выше логики, что я хочу, это прямой перевод, который позволит ограничить. Я знаю, как это сделать на C, и это также упоминается в двух вопросах SO, которые я включил в вопрос. Я ищу способ C# для этого. – genonymous