调用与 btouch 绑定并返回对象的方法时出现异常 System.InvalidCastException。单触错误?

Posted

技术标签:

【中文标题】调用与 btouch 绑定并返回对象的方法时出现异常 System.InvalidCastException。单触错误?【英文标题】:Exception System.InvalidCastException when calling a method bound with btouch that returns an object. MonoTouch bug? 【发布时间】:2011-03-17 10:10:59 【问题描述】:

我正在尝试使用 btouch 绑定 Objective-C 库的类型。我设法用 btouch 编译了我的 API 定义文件,并成功调用了不返回参数或返回字符串或整数等基本参数的方法。但是,当我尝试调用返回 API 定义文件中定义的其他类的实例对象的方法时,会抛出异常 System.InvalidCastException。因此,在下面的示例清单中,UltraliteManager 类的静态 OpenConnection 方法在从 MonoTouch 项目调用时会引发此异常。

这是 Objective-C 的头文件:

#import <Foundation/Foundation.h>

@interface UltraliteConnection : NSObject 
@private
    void * ulconnection;

- (id) initWithULConnection: (void*) connect;
- (void) dealloc;
- (void) close;
- (void) executeStatement: (NSString*) sql;
@end

@interface UltraliteManager: NSObject 
+ (void) initialize;
+ (void) fini;
+ (UltraliteConnection*) openConnection: (NSString*)connectionParms;
@end

这是 Objective-C 的实现(仅显示相关的实现):

@implementation UltraliteConnection
- (id) initWithULConnection: (void*) connect

    [super init];
    ulconnection = connect;
    [self retain];
    return self;

- (void) dealloc 

    [super dealloc];

- (void) close

    ULError error;
    ((ULConnection*) ulconnection)->Close(&error);
    [self release];

@end

@implementation UltraliteManager
+ (UltraliteConnection*) openConnection: (NSString*)connectionParms

    ULError error;
    ULConnection * connbase;
    UltraliteConnection * connwrap;
    connbase = ULDatabaseManager::OpenConnection([connectionParms UTF8String],
                                                 &error, 
                                                 NULL);
    connwrap = [[UltraliteConnection alloc] initWithULConnection:connbase];
    [connwrap release];
    return connwrap;

@end

这是 API 定义文件:

using MonoTouch.Foundation;

namespace Ultralite 
    [BaseType (typeof (NSObject))]
    interface UltraliteConnection 
        [Export("close")]
        void Close ();
        [Export("executeStatement:")]
        void ExecuteStatement(string sql);
    
    [BaseType (typeof (NSObject))]
    interface UltraliteManager 
        [Static, Export ("initialize")]
        string Initialize ();
        [Static, Export ("fini")]
        void Fini ();
        [Static, Export ("openConnection:")]
        UltraliteConnection OpenConnection (string connectionParms);
    

我发现如果我从我的 openConnection 实现中返回 NULL(即用 return nil; 替换行 return connwrap;)然后该方法返回而不抛出一个例外。所以在我看来,这个异常与将 UltraliteConnection 对象返回给 MonoTouch 有关。

有人知道是什么导致了这个问题,我该如何解决?

【问题讨论】:

如果需要,我的 MonoTouch 版本号是 3.2.4.9004 EVALUATION。此外,我发现此链接指向似乎描述了我遇到的问题的错误报告:mail-archive.com/mono-bugs@lists.ximian.com/msg67928.html 【参考方案1】:

我已经设法解决了这个问题,它确实似乎是 MonoTouch 中的一个错误。我的解决方法是使用 outdir 参数集调用 btouch,然后在我的项目中包含生成的 C# 文件。所以,不要这样做:

btouch ultralite.cs enum.cs

我做到了:

btouch ultralite.cs enum.cs -outdir=.

这在 ObjCRuntimeUltralite(我的命名空间的名称)两个文件夹中生成了文件。我从项目的引用中删除了 ultralite.dll,而是从 btouch 生成的这两个目录中复制并包含了文件。使用包含的 C# 文件而不是 dll 作为参考,我在问题中提到的 OpenConnection 方法正确执行并返回了连接对象。

我从未对我的 Objective-C 包装器库和 API 定义文件进行任何更改,因此这绝对是 btouch 中的一个错误。或者,也许我在最初对 btouch 的调用中遗漏了一些其他必需的参数。也许 MonoTouch 的某个人可以对此有所了解。

但是,归根结底,我的库最终被导入并在 MonoTouch 中正常工作。 :) 我希望这些信息对遇到此问题的其他人有所帮助。

【讨论】:

【参考方案2】:

我认为问题在于本机 UltraliteConnection 对象正在使用特定方法进行初始化 - initWithULConnection:

既然是这种情况,您必须在UltraliteConnection 对象的 API 定义中实现构造函数:

[Export ("initWithULConnection:")]  
IntPtr Constructor (ULConnection connbase);

当然,您还需要绑定 ULConnection 对象才能使其工作。

你有MonoTouch的评估版没关系,它和商业版一样,你不能用它部署到设备和App Store。

【讨论】:

嗯...我不确定...不过尝试一下。 感谢您的回复,迪米特里斯。不过,我看不出这有什么帮助,因为我实际上并不希望能够从 MonoTouch 构造这个 UltraliteConnection 对象。事实上,即使构造函数在那里,也不能从 MonoTouch 中使用,因为作为参数传入的基类是 Ultralite C++ 库中的一个连接对象,它只能在我的 Objective-C 包装器中使用图书馆。 这就是你征服 SQL Ultralite 库的方式吗?我将使用 SWIG 亲自尝试一下,对您的发现感到好奇。

以上是关于调用与 btouch 绑定并返回对象的方法时出现异常 System.InvalidCastException。单触错误?的主要内容,如果未能解决你的问题,请参考以下文章

《方法调用和返回》

Xamarin Studio btouch 不支持的字段类型:NSUuid

Android ViewBinding 有时会在绑定对象处返回 null,因此在尝试访问视图时出现空指针异常

没有参数的iOS委托方法难以绑定

python-面向对象(绑定方法与非绑定方法)

三.绑定方法与非绑定方法