调用与 btouch 绑定并返回对象的方法时出现 System.InvalidCastException 异常。 MonoTouch 错误?
我正在尝试使用 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 connwrap; 替换为 return nil;),然后该方法返回而不抛出异常。所以在我看来,这个异常与 UltraliteConnection 对象返回到 MonoTouch 有关。
任何人都知道是什么导致了这个问题以及我该如何解决它?
I am trying to bind the types of an Objective-C library using btouch. I have managed to compile my API definition file with btouch and have successfully called methods that return no parameters or which return basic parameters like string or integer. However, when I try call methods that return instance objects for other classes defined in the API definition file, I get an exception System.InvalidCastException thrown. So in the example listing that follows, the static OpenConnection method of the UltraliteManager class throws this exception when called from a MonoTouch project.
This is the Objective-C header file:
#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
This is the Objective-C implementation (abridged to show just the relevant implementations):
@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
And this is the API definition file:
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);
}
}
I have found that if I return NULL from my implementation of openConnection (ie. replace the line return connwrap; with return nil;) then the method returns without throwing an exception. So it seems to me that this exception has to do with returning of the UltraliteConnection object to MonoTouch.
Anyone have any idea what is causing this problem and how I can resolve it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我已经设法解决这个问题,它确实似乎是 MonoTouch 中的一个错误。我的解决方法是使用 outdir 参数集调用 btouch,然后将生成的 C# 文件包含在我的项目中。因此,我没有这样做:
btouch ultralite.cs enum.cs,
而是:
btouch ultralite.cs enum.cs -outdir=.
这在两个文件夹中生成了文件 >ObjCRuntime 和 Ultralite(我的命名空间的名称)。我从项目的引用中删除了 ultralite.dll,而是复制并包含 btouch 生成的这两个目录中的文件。通过包含 C# 文件而不是 dll 作为参考,我在问题中提到的 OpenConnection 方法正确执行并返回连接对象。
我从未对我的 Objective-C 包装器库和 API 定义文件进行过任何更改,因此这肯定是 btouch 中的一个错误。或者也许我在最初对 btouch 的调用中遗漏了一些其他必需的参数。也许 MonoTouch 的某人可以对此有所启发。
但是,最重要的是,我的库终于导入并在 MonoTouch 中正常工作。 :) 我希望这些信息对遇到此问题的其他人有所帮助。
I have managed to work around this issue and it does indeed seem to be a bug in MonoTouch. My workaround was to call btouch with the outdir parameter set and then include the generated C# files in my project. So, instead of doing this:
btouch ultralite.cs enum.cs
I did:
btouch ultralite.cs enum.cs -outdir=.
This generated files in two folders ObjCRuntime and Ultralite (the name of my namespace). I removed the ultralite.dll from the references of my project, and instead copied and included the files from these two directories that btouch generated. With the C# files included instead of the dll as reference, the OpenConnection method that I referred to in my question executed correctly and returned the connection object.
I never made any changes to my Objective-C wrapper library, nor the API definition file, so it definitely seems to be a bug in btouch. Or maybe I was missing some other required argument in my original call to btouch. Maybe someone from MonoTouch could shed some light on this.
But, bottom line, my library is finally imported and working correctly in MonoTouch. :) I hope that this information is helpful to anyone else who encounters this problem.
我认为问题在于本机
UltraliteConnection
对象正在使用特定方法 -initWithULConnection:
进行初始化。既然是这种情况,您必须在
UltraliteConnection
对象的 API 定义中实现一个构造函数:当然,您还需要绑定 ULConnection 对象才能使其工作。
即使您拥有 MonoTouch 的评估版也没关系,它与商业版相同,只是无法将其部署到设备和 App Store。
I think the problem is that the native
UltraliteConnection
object is being initialized with a specific method -initWithULConnection:
.Since this is the case, you have to implement a constructor in your API definition of the
UltraliteConnection
object:And of course, you will also need to bind the ULConnection object for this to work.
It doesn't matter that you have the evaluation version of MonoTouch, it is the same as the commercial, you just can't deploy to devices and the App Store with it.