2011-09-21 3 views
2

GIT의 위대한 VFR PDF 뷰어에서 ObjC 코드 조각이 있습니다. CGPDFDictionaryGetString을 사용하여 PDF 주석에서 문자열에 대한 포인터를 가져옵니다. 그런 다음 최종 포인터를 얻기 위해 일부 바이트 포인터 변환을 사용합니다. Monotouch에는 이 없지만 .GetName() 만 있습니다. 이것은 문자열을 반환하는 유일한 방법이므로 올바른 방법이어야한다고는 생각되지만 작동하지 않습니다. 배열, 사전, 수레 및 정수를 검색 할 수 있습니다. 문자열 만 작동하지 않는 것 같습니다.이 CGPDFDictionaryGetString은 어떻게 Monotouch로 변환됩니까?

아래의 작은 코드 예를 참조하십시오. >를 반환 -하여 GetString가 : // TODO : 나는 마스터 지점에서 볼 수 모노 소스를 보면 :

string sUri = null; // This returns FALSE. Hence my sUri is NULL. Seems like GetName() is not the analogy to CGPDFDictionaryGetString. if(oActionDic.GetName("URI", out sUri)) { // I never get here. } 

편집

가 :

CGPDFStringRef uriString = NULL; 
// This returns TRUE in the ObjC version and uriString is a valid pointer to a string. 
if (CGPDFDictionaryGetString(actionDictionary, "URI", &uriString) == true) 
{ 
    // Do some pointer magic - how to do this in MT? Do I have to at all? 
    const char *uri = (const char *)CGPDFStringGetBytePtr(uriString); 
    // *uri now contains a URL, I can see it in the debugger. 
} 

나는 그런 식으로 번역 CGPDFString

브랜치 4.2로 전환하면 해당 브랜치가있는 것으로 나타납니다. 그래서 거기에서 코드를 복사했지만 두 가지 문제가 있습니다 :

  • "안전하지 않은"키워드에 대해 오류가 발생합니다. 그것은 "안전하지 않은"명령 행 옵션을 추가하라고 알려줍니다. 그것은 무엇이며 그것을 추가하는 것이 좋은 생각입니까? 어디에?
  • 어쨌든 실행되는 것처럼 보이지만 CGPDFString을 가져올 때 응용 프로그램이 멈 춥니 다.

[같이 DllImport (Constants.CoreGraphicsLibrary)] 공개 통근 정전기를 IntPtr CGPDFStringGetLength (pdfStr을 IntPtr); 당신이 당신의 소스에 안전하지 않은 키워드를 사용하는 경우

[DllImport (Constants.CoreGraphicsLibrary)] 
    public extern static IntPtr CGPDFStringGetBytePtr (IntPtr pdfStr); 

    public static string PdfStringToString (IntPtr pdfString) 
    { 
     if (pdfString == IntPtr.Zero) 
      return null; 

     int n = (int)CGPDFStringGetLength (pdfString); 
     unsafe 
     { 
      return new String ((char *)CGPDFStringGetBytePtr (pdfString), 0, n); 
     } 
    } 

    [DllImport (Constants.CoreGraphicsLibrary)] 
    extern static bool CGPDFDictionaryGetString (IntPtr handle, string key, out IntPtr result); 

    public static bool GetStringFromPdfDictionary (CGPDFDictionary oPdfDic, string key, out string result) 
    { 
     if (key == null) 
      throw new ArgumentNullException ("key"); 
     IntPtr res; 
     if (CGPDFDictionaryGetString (oPdfDic.Handle, key, out res)) 
     { 
      result = PdfStringToString (res); 
      return true; 
     } 
     result = null; 
     return false; 
    } 
+0

안전하지 않은 이유는 무엇입니까? 필요없는 것처럼 보입니다. –

+0

그리고 안전하지 않은 블록에서만 허용되는 포인터 연산 대신 무엇을합니까? – Krumelur

+0

'Marshal' 클래스를 사용하여 null로 끝나는 문자열을 .net 문자열 –

답변

1

는 당신은 당신의 어셈블리를 구축 할 때 안전하지 않은를 활성화해야합니다. MonoDevelop에서는 다음을 수행 할 수 있습니다.

  • 프로젝트를 마우스 오른쪽 버튼으로 클릭하십시오.
  • 선택 옵션 메뉴;
  • 선택 일반 아이콘;
  • 가 '안전하지 않은'코드 확인란
  • 클릭
  • 그런 다음 다시 확인 버튼을 허용을 클릭합니다.

참고 : 이전 빌드에서는이 기능을 사용하지 않아야합니다.

소스 코드 monotouch-4.2 마스터 사이 이 경우에 동일하게해야한다. 확인 하겠지만 코드가 업데이트되기 전에 푸시 된 GIT의 특정 버전을보고있을 가능성이 큽니다. 나는 확실히 확인하고 게시물을 편집 할 것입니다.

UPDATE :이 master 링크 (즉, 최신의 가능한 코드)이며 보여준다

public bool GetString (string key, out string result) 

가능한다. 그러나 안전하지 않은 코드 (PdfStringToString 내부)에 의존합니다.이 코드는이 코드를 복사/붙여 넣은 어셈블리에서 안전하지 않은 코드를 허용하지 않고는 컴파일 할 수 없었습니다.

UPDATE2 : 반환 된 값은 UTF8로 인코딩되므로 생성 된 문자열을 올바르게 디코딩해야합니다 (다른 System.String 생성자에서 허용됨). 위의 마스터 링크는 이미 고정 버전을 가리켜 야합니다.

+1

으로 복사합니다. 그런데 버그를 제출했습니다. 975입니다. GetString()에 더 정확한 줄이 필요합니다. "new String ((char *) CGPDFStringGetBytePtr (pdfString), 0, n)" – Krumelur

+0

옵션에 "안전하지 않은"매개 변수를 추가하기 전에 확인란. 그러나 도움이되지 않습니다. 마스터에서 코드를 복사하고 테스트 용으로 제공 한 monotouch.dll을 사용할 때와 같은 (부정확 한) 결과를 얻습니다. 따라서 바이트를 문자로 변환 할 때 문제가되는 것은 아닙니다. – Krumelur

+0

버그 보고서를 작성해 주셔서 감사합니다. 나는 몇 시간 후 (저녁 식사 후) 그리고 버그 리포트에 대한 추가 발견 사항 (또는 수정 사항 :-)을 살펴볼 것이다. – poupou

0

저는 안전하지 않은 블록을 사용하는 데 큰 팬이 아니며이 방법을 사용하지 않고이 방법을 구현하는 방법을 연구했습니다. 처음에는 불안전 한 스타일을 시도했지만 문자열이 UTF8로 저장되면 변환해야합니다.

private bool PDFDictionaryGetString (IntPtr handle, string key, out string result) 
{ 
    IntPtr stringPtr; 
    result = null; 

    if (CGPDFDictionaryGetString(handle, "URI", out stringPtr)) { 

     if (stringPtr == IntPtr.Zero) 
       return false; 

     // Get length of PDF String 
     uint n = (uint) CGPDFStringGetLength (stringPtr); 

     // Get the pointer of the string 
     var ptr = CGPDFStringGetBytePtr (stringPtr); 
     // Get the bytes 
     var data = NSData.FromBytes(ptr, n); 
     // Convert to UTF8 
     var value = NSString.FromData(data, NSStringEncoding.UTF8); 

     result = value.ToString(); 
     return true; 
    } 
    return false; 
} 

완전한 소스 here 다중 슬쩍 탐색을 특징으로하고 클릭 가능한 링크를 포함한 전체 블로그 게시물 here 및 작업 예제가있다.