2013-04-17 6 views
2

다음과 같은 도움이 필요합니다. C++ API (소스에 액세스 할 수 없음)가있어 char * 특성을 반환하는 메서드 또는 char * 특성이 포함 된 구조체를 반환하는 데 어려움을 겪고 있습니다. API의 문서에 따르면 반환 값은 다음과 같습니다.C#에서 일련의 Null 종료 문자열에 대한 포인터를 마샬링하는 방법은 무엇입니까?

반환 값
함수가 성공하면 반환 값은 호스트 시스템의 각 프로젝트에 대해 하나의 일련의 null 종료 문자열로 끝나는 포인터입니다 두 번째 null 문자. 다음 예는 널 종료 문자를 나타내는 <null>와 버퍼 내용을 보여줍니다 함수가 실패하면

project1<null>project2<null>project3<null><null> 

을, 반환 값은 NULL입니다

제가하는 데 문제는입니다 C 번호 만에 반환 된 포인터 이 경우 첫 번째 값 ... project1을 포함합니다. 전체 목록을 관리 측면에서 반복 재생하려면 어떻게해야합니까?

다음은 C# 코드입니다 :

[DllImport("vmdsapi.dll", EntryPoint = "DSGetProjectList", CallingConvention = CallingConvention.Cdecl)] 
    public static extern IntPtr DSGetProjectList(); 

호출 방법 :

IntPtr ptrProjectList = DSAPI.DSGetProjectList(); 
    string strProjectList = Marshal.PtrToStringAnsi(ptrProjectList).ToString(); 

strProjectList은 첫 번째 항목이 포함되어 있습니다.
여기 ...

다음
DllImport char *DSGetProjectList dsproto((void)); 

... 내가 테스트 목적으로 사용했습니다 콘솔 응용 프로그램 ++은 C에서 몇 가지 예제 코드 API의 헤더 파일에서 정보 것입니다

char *a; 
    a = DSGetProjectList(); 
    while(*a) { 
    printf("a=%s\n", a); 
    a += 1 + strlen(a); 
    } 

각 반복은 모든 프로젝트를 목록에 올바르게 표시합니다.

+1

사용하는 C++ API의 서명과 적어도 C# 코드를 제공해야합니다. 이 API를 호출합니다. – zakinster

+0

C++ API를 호출하는 C# 코드를 추가하십시오 – mmpatel009

+0

결과 (길이)를 신중하게 확인하지 않으십니까? –

답변

2

문제는 C++ char *을 Marshal.PtrToStringAnsi을 사용하는 C# 문자열로 변환 할 때 첫 번째 null 문자에서 멈추는 문제입니다.

char*을 직접 문자열로 변환해서는 안됩니다.

당신은 Marshal.Copy를 사용하여 IntPtrbyte[] A와로 표현되는 char*을 복사 한 다음 (관리되는 배열에서 문자열을 추출 Matthew Watson's answer 참조) 필요한만큼의 문자열을 추출하지만, 당신이 다중 문자열을 얻을해야합니다 수 먼저 크기.

마찬가지로 leppieMarshal.PtrToStringAnsi을 사용하여 첫 번째 문자열을 추출한 다음 포인터를이 문자열 크기만큼 증가시키고 다음 문자열을 추출하는 식으로 제안합니다. 당신은 when이 (마지막 NULL 문자로부터) 빈 문자열을 추출 할 때 멈춘다.같은

뭔가가 :

IntPtr ptrProjectList = DSAPI.DSGetProjectList(); 
List<string> data; 
string buffer; 
do { 
    buffer = Marshal.PtrToStringAnsi(ptrProjectList); 
    ptrProjectList += buffer.size() + 1; 
    data.Add(buffer); 
}while(buffer.size() > 0) 
+1

그리고 멈출 때 포인터를 'strlen + 1'로 증가시키는 것이 어떻습니까? – leppie

+0

그렇습니다. 또 다른 가능성이 있습니다.하지만 조심스럽게 적시에 중지해야합니다. 관리되는 배열을 반복하면 C# 프로그래머가 가장 쉽게 사용할 수 있습니다. – zakinster

+0

zakinster ... 당신은 남자입니다. 여러분의 도움과 빠른 답변에 감사드립니다. 그것은 100 % 일하고 있습니다. 정말 감사. – Jean

0

문자열 이러한 종류의 Multi-String라고하며는 Windows API에서 매우 일반적입니다.

마샬링하는 것은 피싱입니다. 문자열이 아닌 char[] 배열로 마샬링 한 다음 char[] 배열을 문자열 집합으로 변환해야합니다.

See here for an example solution. 관련 코드를이 답변에 복사했지만, 내가 보낸 링크에서 복사됩니다.

static List<string> MultiStringToList(char[] multistring) 
{ 
    var stringList = new List<string>(); 
    int i = 0; 

    while (i < multistring.Length) 
    { 
     int j = i; 

     if (multistring[j++] == '\0') 
      break; 

     while (j < multistring.Length) 
     { 
      if (multistring[j++] == '\0') 
      { 
       stringList.Add(new string(multistring, i, j - i - 1)); 
       i = j; 
       break; 
      } 
     } 
    } 

    return stringList; 
} 
관련 문제