2012-05-09 3 views
3

Привет им пытается обновить Google admboads на V6, но им возникли некоторые проблемы, чтобы связать следующими и подвергать его управляемого мируMonoTouch Binding не может использовать поля

Я имею следующую структуру

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

и я сделал это на MonoTouch стороне

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

у меня есть следующий код

extern GADAdSize const kGADAdSizeBanner; 
extern GADAdSize const kGADAdSizeMediumRectangle; 

я не могу связать его с помощью [Field] Атрибут поскольку документы указывают, что поле атрибута может быть использован только для

  • NSString ссылки
  • NSArray ссылки
  • 32-битных Интс (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 я получаю nullargument исключение при вызове Marshal.PtrToStructure(), а второй - DLLNotFoundException System.ArgumentNullException

Thanks заранее за любую помощь

Alex


Edit:

К сожалению @Poupou мой плохой, он бросает System.ArgumentNullException значение описателя его 0 также ПТР ценят свою 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 .

Об комментарий

Использование dlsym одним из специальных флагов (человек dlsym) может помочь.

Не могли бы вы предоставить мне пример о том, как использовать его, пожалуйста, =) ??

Alex


Edit 2:

Здравствуйте @Poupou и спасибо за ваш ответ, но с

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

Я все еще получаю ptr равно 0 любой другой идеи ??

Alex


Edit 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); как его сделали here теперь я получаю значение ручки -2 но я думаю родной компоновщик, теперь он удаляет символ, как я могу предотвратить это?

Большое спасибо за ваше время @Poupou

Alex

+0

* DLLNotFoundException *? Я удивлен, что такое значение 'handle'? и трассировка стека? Поскольку библиотека была статически связана, она не будет найдена. Использование 'dlsym' с одним из специальных флагов (' man dlsym') может помочь. – poupou

+0

@poupou, пожалуйста, см. Мое обновление, надеюсь, что вы можете помочь мне и за вашу информацию. – dalexsoto

ответ

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), поэтому это не будет требованием для конечных пользователей.

+0

Попробуем его сегодня вечером и сообщим, если это сработало ;-) спасибо большое sebastien – dalexsoto

+0

Спасибо большое Спасибо большое Sebastien, который сработал ты мой герой ;-) просто спросил еще одну вещь в отчете об ошибке, надеюсь, ты сможешь мне помочь. Еще раз спасибо – dalexsoto

+0

@poupou У меня такая же проблема, но с динамической библиотекой. любое предложение – khaled

1

Ваше второе решение, что обычно используется. Он динамически загружает символы из указанной библиотеки . 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: посмотрите на другие варианты :-) Если вы указали ненулевой (не IntPtr.Zero) указатель, вы можете попытаться его маршалировать в структуру SizeF.

+0

Здравствуйте, @Poupou благодарит за вашу помощь, см. Мое обновление. – dalexsoto

+0

Сначала убедитесь, что символ включен в ваш основной (собственный) исполняемый файл (то есть, что родной компоновщик не удалил его, иначе ничего не будет работать), а затем прочитайте 'man dlsym' для других специальных значений. – poupou

+0

Итак, чтобы получить дескриптор моего основного исполняемого файла, я должен использовать 'var handle = Dlfcn.dlopen (« __Internal », 0);'? Извините, я новичок в этом инструменте – dalexsoto

Смежные вопросы