3

こんにちは私はグーグルアドボードをV6に更新しようとしていますが、以下をバインドして管理された世界に公開するのに問題があります

私は次の構造体を持っています

typedef struct GADAdSize {
  CGSize size;
  NSUInteger flags;
} GADAdSize;

モノタッチ側でやった

[StructLayout(LayoutKind.Sequential)]
public struct GADAdSize
{
    public SizeF size;
    public uint flags;
}

私は次のコードを持っています

extern GADAdSize const kGADAdSizeBanner;
extern GADAdSize const kGADAdSizeMediumRectangle;

[フィールド]属性を使用してバインドすることはできません。ドキュメントでは、フィールド属性は次の目的でのみ使用できると指定されているためです。

  • NSString参照
  • NSArrayリファレンス
  • 32ビットint(System.Int32)
  • 32ビットフロート(System.Single)
  • 64ビットフロート(System.Double)

だから私は私が考えることができる次の2つの方法を試しました

[DllImport ("__Internal")]
    extern static IntPtr kGADAdSizeMediumRectangle ();

public static GADAdSize MediumRectangle 
{
    get 
    {
        object obj = Marshal.PtrToStructure(kGADAdSizeMediumRectangle(), typeof(GADAdSize));
        return (GADAdSize) obj;
    }
}

public static GADAdSize Banner 
{
    get 
    {
        var handle = Dlfcn.dlopen ("libGoogleAdMobAds", 0);
        IntPtr ptr = Dlfcn.GetIntPtr(handle, "kGADAdSizeBanner");   
        Dlfcn.dlclose (handle);     
        object obj = Marshal.PtrToStructure(ptr, typeof(GADAdSize));
        return (GADAdSize) obj;
    }
}

そして両方の方法でそれはクラッシュします

DLLImportを使用すると、Marshal.PtrToStructure()を呼び出すときにnull引数の例外が発生し、2番目の例外ではDLLNotFoundExceptionSystem.ArgumentNullExceptionが発生します

助けてくれてありがとう

アレックス


編集:

申し訳ありませんが、@ Poupouは、System.ArgumentNullExceptionをスローします。ハンドル値は0であり、ptr値は0です。

スタックトレースは次のとおりです。

System.ArgumentNullException: Argument cannot be null.
Parameter name: src
  at (wrapper managed-to-native) System.Runtime.InteropServices.Marshal:PtrToStructure (intptr,System.Type)
  at AlexTouch.GoogleAdMobAds.GADAdSizeConstants.get_Banner () [0x00000] in <filename unknown>:0
  at MobclixText.MobclixTextViewController.ViewDidLoad () [0x00006] in /Users/Alex/Projects/MobclixText/MobclixText/MobclixTextViewController.cs:33
  at (wrapper managed-to-native) MonoTouch.ObjCRuntime.Messaging:void_objc_msgSend (intptr,intptr)
  at MonoTouch.UIKit.UIWindow.MakeKeyAndVisible () [0x00010] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIWindow.g.cs:98
  at MobclixText.AppDelegate.FinishedLaunching (MonoTouch.UIKit.UIApplication app, MonoTouch.Foundation.NSDictionary options) [0x00031] in /Users/Alex/Projects/MobclixText/MobclixText/AppDelegate.cs:44
  at (wrapper managed-to-native) MonoTouch.UIKit.UIApplication:UIApplicationMain (int,string[],intptr,intptr)
  at MonoTouch.UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x0004c] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIApplication.cs:38
  at MobclixText.Application.Main (System.String[] args) [0x00000] in /Users/Alex/Projects/MobclixText/MobclixText/Main.cs:17

これはハンドルが0であるためだと思います。

コメントについて

特別なフラグの1つ(man dlsym)でdlsymを使用すると役立つ場合があります。

使い方の例を教えてください=)??

アレックス


編集2:

こんにちは@Poupouとあなたの答えに感謝しますが

IntPtr RTLD_MAIN_ONLY = (IntPtr) (-5);
IntPtr ptr = Dlfcn.GetIntPtr (RTLD_MAIN_ONLY, "kGADAdSizeBanner");

私はまだ他のアイデアptrと同等になりますか?0

アレックス


編集3:

わかりました、今次を試しています

IntPtr RTLD_MAIN_ONLY = Dlfcn.dlopen (null, 0);
IntPtr ptr = Dlfcn.dlsym (RTLD_MAIN_ONLY, "kGADAdSizeBanner");              
Console.WriteLine("RTLD_MAIN_ONLY: " + RTLD_MAIN_ONLY);
Console.WriteLine("ptr: " + ptr);

Dlfcn.dlopen (null, 0);ここで行ったように、ハンドル値を取得しています-2が、ネイティブリンカーがシンボルを削除していると思いますが、これを防ぐにはどうすればよいですか?

どうもありがとうございました@Poupou

アレックス

4

2 に答える 2

4

そこで、値を取得する方法を見つけました。最初の部分は、(既存のシンボルを非表示にすることなく)シンボルをエクスポートするようにリンカーを説得することです。これは、(ローカル)シンボルのエイリアス(デフォルトではグローバル)を作成することで実行できます。例えば

-gcc_flags="-Xlinker -alias -Xlinker _kGADAdSizeBanner -Xlinker _MTAdSizeBanner"

その後、コード:

IntPtr RTLD_MAIN_ONLY = Dlfcn.dlopen (null, 0);
IntPtr ptr = Dlfcn.dlsym (RTLD_MAIN_ONLY, "MTAdSizeBanner");
object obj2 = Marshal.PtrToStructure(ptr, typeof(GADAdSize));

GADAdSize値が320x50ののインスタンスを提供します。

必要なすべてのシンボルを再エクスポートする必要がありますが(yuck)、これを[LinkWith]属性(iirc)に含めることができるはずなので、エンドユーザーの要件にはなりません。

于 2012-05-17T18:49:41.457 に答える
1

2番目の解決策は、通常使用されるものです。指定されたライブラリからシンボルを動的にロードします。OTOHこれはiOSのシステムライブラリでのみ機能します。

なんで ?提供されたライブラリはメインの実行可能ファイルと静的にリンクされるためです。[DllImport("__Internal")これは、通常のp/invokeに使用する必要があるのと同じ理由です。

シンボルに戻るとdldym、メインの実行可能ファイル(またはロードされたすべてのコード)で動作するためのいくつかのオプションがあります。man dlsymそれらを表示するには、ターミナルウィンドウでを実行します。それは(それを試しませんでした)以下を使用して機能する可能性があります:

 IntPtr RTLD_MAIN_ONLY = (IntPtr) -5;
 IntPtr ptr = Dlfcn.GetIntPtr (RTLD_MAIN_ONLY, "kGADAdSizeBanner"); 

注1:Dlfcn.GetIntPtr基本的にラップするユーティリティメソッドdlsymです。

注2:他のオプションも確認してください:-) null以外の(not)ポインターを取得した場合は、それを構造体IntPtr.Zeroにマーシャリングしてみてください。SizeF

于 2012-05-10T13:15:37.413 に答える