这个 CGPDFDictionaryGetString 如何转换为 Monotouch?
我有一段来自 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(常量.CoreGraphicsLibrary)] 公共外部静态 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;
}
I have a piece of ObjC code from the great VFR PDF Viewer on GIT.
It is using CGPDFDictionaryGetString
to get a pointer to a string from a PDF annotation. Then it uses some byte pointer conversion to get the final string.
In Monotouch there is no CGPDFDictionary.GetString()
but only a .GetName()
- this is the only method that returns a string, so I assumed that must be the correct method but it does not work.
I can retrieve arrays, dictionaries, floats and integers just fine - only the strings don't seem to work.
See the small code examples below.
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.
}
I translated it like that:
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.
}
EDIT:
Looking at the Mono sources I can see this in the Master branch:
// TODO: GetString -> returns a CGPDFString
Switching to branch 4.2 reveals that it seems to be there. So I copied the code from there but have two issues:
- I get an error about the "unsafe" keyword. It tells me to add the "unsafe" command line option. What is that and is it a good idea to add it? Where?
- It seems to run anyway but the app hangs when getting the 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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果您在源代码中使用unsafe关键字,那么您需要在构建程序集时启用unsafe。在 MonoDevelop 中,您可以通过以下方式执行此操作:
注意:如果没有这个,您之前的构建应该无法工作。
在这种情况下,master 和 monotouch-4.2 之间的源代码应该相同。我会检查一下,但您可能正在查看 GIT 中的特定修订版(在代码更新之前推送)。我会检查确定并编辑帖子。
更新:这是 master 的链接 (即可用的最新代码)并且它显示:
可用。但是,它确实依赖于不安全代码(在 PdfStringToString 内),如果您复制/粘贴此代码的程序集中不允许存在不安全代码,则您不应该能够编译该代码。
UPDATE2 :返回的值是 UTF8 编码的,因此从它创建的字符串需要正确解码(另一个 System.String 构造函数允许这样做)。上面的 master 链接应该已经指向固定版本。
If you use the unsafe keyword in your source then you need to enable unsafe when building your assembly. In MonoDevelop you can do this by:
Note: Your previous build should not have worked without this.
Source code between master and monotouch-4.2 should be identical in this case. I'll check but it's likely that you were looking at a specific revision in GIT (the was pushed before the code was updated). I'll check to be sure and edit the post.
UPDATE : This is the link to master (i.e. latest code available) and it shows:
to be available. However it does depend on unsafe code (inside PdfStringToString) which you should not have been able to compile without allowing unsafe code in the assembly where you copy/pasted this code.
UPDATE2 : The value returned is UTF8 encoded so the string created from it needs to be decoded properly (another System.String constructor allows this). The above link to master should already point to the fixed version.
我不太喜欢使用不安全的块,并且找到了一种无需使用不安全的块即可实现此方法的方法。最初我确实尝试了不安全的样式,但是由于字符串存储在 UTF8 中,因此需要进行转换。
这里有一篇完整的博客文章工作示例,包括此处的完整源代码,具有多页滑动导航和可点击链接。
I'm not a big fan of using unsafe blocks, and worked out a way to implement this method without using one. Initially I did try the unsafe style, however as the string is stored in UTF8 it needs to be converted.
There's a full blog post here and working sample including complete source here featuring multipage swipe navigation and clickable links.