2

GITのすばらしいVFRPDFビューアからのObjCコードを持っています。CGPDFDictionaryGetStringPDF注釈から文字列へのポインタを取得するために使用しています。次に、バイトポインタ変換を使用して最終的な文字列を取得します。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ソースを見ると、マスターブランチでこれを見ることができます: // TODO:GetString->CGPDFStringを返します

ブランチ4.2に切り替えると、そこにあるように見えます。そこで、そこからコードをコピーしましたが、2つの問題があります。

  • 「unsafe」キーワードについてエラーが発生します。「安全でない」コマンドラインオプションを追加するように指示されます。それは何ですか、それを追加するのは良い考えですか?どこ?
  • とにかく実行されているようですが、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では、次の方法でこれを行うことができます。

  • プロジェクトを右クリックします。
  • [オプション]メニューを選択します。
  • 一般アイコンを選択します。
  • [安全でないコードを許可する]チェックボックスをクリックします
  • [ OK ]ボタンをクリックします
  • 次に、再構築します。

注:以前のビルドは、これがないと機能しませんでした。

この場合、 mastermonotouch-4.2の間のソースコードは同一である必要があります。確認しますが、GITの特定のリビジョンを見ている可能性があります(コードが更新される前にプッシュされました)。確認して投稿を編集します。

更新:これはマスターへのリンク(つまり、利用可能な最新のコード)であり、次のように表示されます。

public bool GetString (string key, out string result)

利用可能になります。ただし、安全でないコード(PdfStringToString内)に依存します。このコードをコピーして貼り付けたアセンブリで安全でないコードを許可せずにコンパイルすることはできませんでした。

UPDATE2:返される値はUTF8でエンコードされているため、そこから作成された文字列を適切にデコードする必要があります(別のSystem.Stringコンストラクターでこれが可能です)。上記のマスターへのリンクは、すでに修正バージョンを指しているはずです。

于 2011-09-21T21:20:31.683 に答える
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;
} 

ここに完全なブログ投稿があり、マルチページのスワイプナビゲーションとクリック可能なリンクを備えた完全なソースを含む実用的なサンプルがここにあります。

于 2011-09-27T07:36:10.107 に答える