Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MonoTouch Binding cannot use fields

Hello im trying to update google admboads to V6 but im having some trouble to bind the following and expose it to managed world

I have the following struct

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

and I did this on monotouch side

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

I have the following code

extern GADAdSize const kGADAdSizeBanner;
extern GADAdSize const kGADAdSizeMediumRectangle;

I can't bind it using [Field] Attribute since docs specify that Field attribute can only be used for

  • NSString references
  • NSArray references
  • 32-bit ints (System.Int32)
  • 32-bit floats (System.Single)
  • 64-bit floats (System.Double)

So I tried the following 2 ways i could think of

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

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

and

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

And on both ways it crashes

Using the DLLImport I get a nullargument exception when calling Marshal.PtrToStructure() and the second one rises an DLLNotFoundException System.ArgumentNullException

Thanks in advance for any help

Alex


Edit:

Sorry @Poupou my bad, it throws a System.ArgumentNullException the handle value its 0 also the ptr value its 0

and the stacktrace is:

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

I guess this is due to handle being 0.

About your comment

Using dlsym with one of the special flags (man dlsym) might help.

Could you provide me an example on how to use it please =) ??

Alex


Edit 2:

Hello @Poupou and thanks for your answer, but with

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

I still get ptr equals to 0 any other idea??

Alex


Edit 3:

Ok, im trying the following now

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); as its done here now I'm getting a handle value -2 but I guess native linker it's removing the symbol now, how can I prevent this from happening??

Thanks a lot for your time @Poupou

Alex

like image 211
dalexsoto Avatar asked Jul 28 '26 17:07

dalexsoto


1 Answers

Your second solution is what is normally used. It dynamically loads the symbols from the specified library. OTOH this works only for system libraries on iOS.

Why ? because your own supplied libraries will be linked statically with your main executable. That's the same reason that [DllImport("__Internal") must be used for normal p/invoke.

Back to symbols, dldym has some options to work on the main executable (or all loaded code). Do a man dlsym on a terminal window to see them. That might (did not try it) work using:

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

Note 1: Dlfcn.GetIntPtr is an utility method that basically wraps dlsym;

Note2: look at the other options as well :-) If you get a non-null (not IntPtr.Zero) pointer then you can try to marshal it into a SizeF structure.

like image 140
poupou Avatar answered Jul 30 '26 06:07

poupou



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!