2

我有一段来自 GIT 上出色的 VFR PDF 查看器的 ObjC 代码。它CGPDFDictionaryGetString用于从 PDF 注释中获取指向字符串的指针。然后它使用一些字节指针转换来获得最终的字符串。在 Monotouch 中,CGPDFDictionary.GetString()只有一个.GetName()- 这是唯一返回字符串的方法,所以我认为它必须是正确的方法,但它不起作用。我可以很好地检索数组、字典、浮点数和整数——只有字符串似乎不起作用。

请参阅下面的小代码示例。

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

编辑: 查看 Mono 源,我可以在 Master 分支中看到: // TODO: GetString -> 返回一个 CGPDFString

切换到分支 4.2 表明它似乎在那里。所以我从那里复制了代码,但有两个问题:

  • 我收到有关“不安全”关键字的错误。它告诉我添加“不安全”命令行选项。那是什么,添加它是个好主意吗?在哪里?
  • 它似乎仍然运行,但在获取 CGPDFString 时应用程序挂起。

[DllImport (Constants.CoreGraphicsLibrary)] public extern static 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;
    }
4

2 回答 2

1

如果您在源代码中使用unsafe关键字,则需要在构建程序集时启用unsafe 。在 MonoDevelop 中,您可以通过以下方式执行此操作:

  • 右键单击项目;
  • 选择选项菜单;
  • 选择常规图标;
  • 单击允许“不安全”代码复选框
  • 单击确定按钮
  • 然后重建。

注意:如果没有这个,你以前的构建不应该工作。

在这种情况下, mastermonotouch-4.2之间的源代码应该是相同的。我会检查,但很可能您正在查看 GIT 中的特定修订版(在更新代码之前已推送)。我会检查以确保并编辑帖子。

更新:这是master的链接(即可用的最新代码),它显示:

public bool GetString (string key, out string result)

可用。但是,它确实取决于不安全代码(在 PdfStringToString 内部),如果在复制/粘贴此代码的程序集中不允许不安全代码,则您应该无法编译这些代码。

UPDATE2:返回的值是 UTF8 编码的,因此从它创建的字符串需要正确解码(另一个 System.String 构造函数允许这样做)。上面指向 master 的链接应该已经指向固定版本。

于 2011-09-21T21:20:31.683 回答
0

我不是使用 unsafe 块的忠实拥护者,并且想出了一种不使用不安全块来实现此方法的方法。最初我确实尝试了不安全的样式,但是由于字符串存储在 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;
} 

此处有完整的博客文章和工作示例,包括此处的完整源代码,其中包含多页滑动导航和可点击链接。

于 2011-09-27T07:36:10.107 回答