2014-09-12 4 views
1

그러나C#에서 고정 길이 int 배열에 void 포인터가 가리키는 데이터를 타입 변환하는 방법은 무엇입니까? 이것은 다음과 같은 SO 질문에 유사하다

cast-void-pointer-to-integer-array

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

는 차이가 나는 우리가 포인터를 사용할 수있는 '안전하지 않은'기능을 사용하여 C#으로이를 달성 할 것입니다 .

다음 코드는 C에서 작동 : 'PTR은'무효 포인터가

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

입니다. 어떻게 이것을 C#에서 얻을 수 있습니까? 나는 이것이 당신이 찾고있는 것을 완전히 확실하지 않다

+0

어떻게 C#에서 포인터를 가져 옵니까? 'int *'로 시작할 수도 있고, 그렇지 않으면 그것을 받아야한다. 'void *'를 받았다면 그것을 사용할 수 있도록 캐스트해야합니다. – xxbbcc

+0

정확하게 그 이유를 설명해 주시겠습니까? 또한 C# 형식 시스템에는 고정 된 크기의 배열이 없습니다. – svick

+0

@xxbbcc 및 : 나는 int 포인터에 대한 void 포인터를 캐스팅 할 수 있다는 것을 알고 있지만 고정 길이 배열에 캐스트하려고합니다. 고정 길이 배열을 입력으로 사용하는 표준 제 3 자 라이브러리 함수가있는 경우 가끔 필요합니다. 예 : 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* 함수 매개 변수로 포인터를받는 경우

, 당신은 함수 내에서 캐스팅해야한다 : 외부 소스로부터 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; 
} 

, 당신은 어떻게 든 얼마나 많은 알고해야 바이트 (또는 int 등)는 포인터를 통해 액세스하는 것이 안전합니다. 데이터는 특수한 값 (예 : 0 또는 기타 끝)으로 구분되거나 포인터를 통해 메모리에 안전하게 액세스하려면 개수 또는 바이트/요소가 필요합니다.

// 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 다양한 포인터 운영에 더 많은 예제가 있습니다

업데이트

다음은 C로 구현 관리되지 않는 함수를 호출하는 예입니다. 또한 배열을 마샬링하는 또 다른 article이 있습니다.

+0

답변 해 주셔서 감사합니다.포인터를 가리키고 포인터를 증가시킨 후 다시 다음 위치에 액세스하는 등 void 포인터가 가리키는 메모리에 액세스 할 수 있다는 것을 알고 있습니다. 그러나이 데이터를 고정 크기 배열을 허용하는 다른 표준 타사 함수에 전달해야한다면 해당 타사 표준 함수에서 위의 논리를 제어 할 수 없습니다. 편집 할 수 없으며 편집하지 않아도됩니다. – genonymous

+0

@genonymous 제 3 자 함수가 정확히 무엇을 기대하는지에 달려 있습니다. C#에서 5 개의 항목 배열에'int *'가 있으면'int'-s 배열 5 개를 만들고 첫 번째 요소의 주소를 얻은 다음 해당 포인터를 제 3 자 호출에 전달할 수 있습니다. 배열은 연속적이므로 첫 번째 요소의 주소, 요소의 크기 및 배열의 ​​항목 수를 알면 배열에 대한 모든 정보가 표시됩니다. – 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에서 그것을하는 방법을 안다. 그리고 그것은 내가 질문에 내포 한 두 가지의 질문에 언급되어있다. 나는 그것을 할 C# 방법을 찾고있다. – genonymous