문제

동적으로 합의 된 배열을 통해 데이터를 반환하는 일련의 기본 기능을 다루고 있습니다. 함수는 참조 포인터를 입력으로 가져간 다음 결과 배열을 가리 킵니다.

예를 들어:

typedef struct result
{
   //..Some Members..//
}

int extern WINAPI getInfo(result**);

호출 후 '결과'는 널리 터진 결과 배열*을 가리 킵니다*.

이 관리되지 않은 배열에서 관리되는 목록을 만들고 싶습니다. 다음을 수행 할 수 있습니다.

struct Result
{
   //..The Same Members..//
}

public static unsafe List<Result> getManagedResultList(Result** unmanagedArray)
{
    List<Result> resultList = new List<Result>();

    while (*unmanagedArray != null)
    {
       resultList.Add(**unmanagedArray);
       ++unmanaged;
    }
    return result;
}

이것은 작동합니다. 내가 다루어야 할 모든 유형의 구조물에 대해 지루하고 추악 할 것입니다 (~ 35). 배열의 구조물 유형에 걸쳐 일반적인 솔루션을 원합니다. 이를 위해 나는 시도했다 :

public static unsafe List<T> unmanagedArrToList<T>(T** unmanagedArray)
{ 
    List<T> result = new List<T>();
    while (*unmanagedArray != null)
    {
        result.Add((**unmanagedArray));
        ++unmanagedArray;
    }
    return result;
}

그러나 "주소를 가져 가거나 크기를 얻거나 관리 유형 ( 't')에 대한 포인터를 선언 할 수 없기 때문에 컴파일하지 않습니다.

또한 안전하지 않은 코드를 사용하지 않고이 작업을 수행하려고했지만 Marshal.copy ()가 관리되지 않는 배열의 크기를 알아야하는 문제를 해결했습니다. 안전하지 않은 코드를 사용하여 이것을 결정할 수 있었 으므로이 경우 Marshal.copy ()를 사용하는 데 도움이되지 않는 것 같습니다.

내가 무엇을 놓치고 있습니까? 누군가이 문제에 대한 일반적인 접근법을 제안 할 수 있습니까?

도움이 되었습니까?

해결책

모든 포인터의 크기와 표현이 동일하다는 합리적인 가정을 할 수 있습니다 (C# 사양이이를 보장하는지 확실하지 않지만 실제로는 그렇습니다). 그래서 당신은 당신을 대할 수 있습니다 T** ~처럼 IntPtr*. 또한, 나는 방법을 알지 못한다 Marshal.Copy 내장 유형에 대한 과부하 만 있기 때문에 여기에서 도움이 될 것입니다. 그래서:

public static unsafe List<T> unmanagedArrToList<T>(IntPtr* p)
{ 
    List<T> result = new List<T>();
    for (; *p != null; ++p)
    {
        T item = (T)Marshal.PtrToStructure(*p, typeof(T));
        result.Add(item);
    }
    return result;
}

물론 명백한 캐스트가 필요합니다 IntPtr* 이것을 호출 할 때마다 적어도 코드 복제는 없습니다.

다른 팁

당신은 말했습니다 :

Marshal.copy ()는 관리되지 않는 배열의 크기를 알아야합니다. 안전하지 않은 코드를 사용하여 이것을 결정할 수있었습니다

당신이 놓친 것 같습니다 Marshal.sizeof ().

게시물에서 언급 한 바에 따르면 문제를 해결하기에 충분할 수 있습니다. (또한 함수의 매개 변수는 t ** 대신 객체 **이어야 할 수도 있습니다.)

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top