2011-09-21 19 views
2

我從GIT上的VFR PDF查看器中看到一段ObjC代碼。 它使用CGPDFDictionaryGetString獲取一個指針從PDF註釋的字符串。然後它使用一些字節指針轉換來獲得最終的字符串。 在MonoTouch的沒有CGPDFDictionary.GetString()但只有.GetName() - 這是返回一個字符串的唯一方法,所以我認爲一定是正確的方法,但它不能正常工作。 我可以檢索數組,字典,浮點數和整數就好 - 只有字符串似乎不工作。這個CGPDFDictionaryGetString如何轉換成Monotouch?

請參見下面的小的代碼的例子。

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. 
} 

我把它翻譯這樣的:

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. 
} 

編輯: // TODO: 望着單聲道音源,我可以在主分支看到的GetString - >返回CGPDFString

切換到分支4.2表明,它似乎是在那裏。所以我複製了代碼,但有兩個問題:

  • 我收到有關「不安全」關鍵字的錯誤。它告訴我添加「不安全」的命令行選項。那是什麼,添加它是一個好主意?哪裏?
  • 這似乎無論如何運行,但得到CGPDFString當應用程序掛起。

[的DllImport(Constants.CoreGraphicsLibrary)] 公共的extern靜態的IntPtr CGPDFStringGetLength(IntPtr的pdfStr);

[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'類從空終止的字符串複製到.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

我在選項中添加了一個「unsafe」參數,然後纔看到複選框。但它沒有幫助。我從主服務器複製了代碼,並獲得與使用您提供用於測試的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設有多頁刷卡導航和可點擊的鏈接。