HELP! Issues with the build phase when binding Objective-C library to MonoTouch
I am currently working on the port of ZebraLink's printer libraries for using into MonoTouch project. These libraries exist and where created for the iOS, so I got the .a file and the bunch of header files developed with Objective-C. Once I get some success on it I will gladly upload it to share with anyone interested, but first I gotta get around a couple of issues, I ask for your kind help:
I currently have 3 classes -> Main.cs , enums.cs and helpers.cs
In the Main.cs I follow the basic structure as mentioned in the Binding Objective-C tutorial
using System;
using MonoTouch.Foundation;
namespace btouchtest
{
[BaseType (typeof (NSObject))]
[Model]
interface ZebraPrinterConnection
{
/**
* Returns the maximum time, in milliseconds, to wait for any data to be received.
*/
//- (NSInteger) getMaxTimeoutForRead;
[Export ("getMaxTimeoutForRead")]
int getMaxTimeoutForRead();
/**
* Returns the maximum time, in milliseconds, to wait between reads after the initial read.
*/
//- (NSInteger) getTimeToWaitForMoreData;
[Export ("getTimeToWaitForMoreData")]
int getTimeToWaitForMoreData();
/**
* Returns <c>YES</c> if the connection is open.
*
* @return <c>YES</c> if this connection is open.
*/
//- (BOOL) isConnected;
[Export ("isConnected")]
bool isConnected();
/**
* Opens the connection to a device. If the ZebraPrinterConnection::open method is called on an open connection
* this call is ignored. When a handle to the connection is no longer needed, call ZebraPrinterConnection::close
* to free up system resources.
*
* @return <c>NO</c> if the connection cannot be established.
*/
//- (BOOL) open;
[Export ("open")]
bool open();
/**
* Closes this connection and releases any system resources associated with the connection. If the connection is
* already closed then invoking this method has no effect.
*/
//- (void) close;
[Export ("close")]
void close();
/**
* Writes the number of bytes from <c>data</c> to the connection. The connection must be
* open before this method is called. If ZebraPrinterConnection::write:error: is called when a connection is closed, -1 is returned.
*
* @param data The data.
* @param error Will be set to the error that occured.
* @return The number of bytes written or -1 if an error occurred.
*/
//- (NSInteger) write:(NSData *)data error:(NSError **)error;
[Internal, Export ("write:error:")]
int _write(NSData data, IntPtr error);
/**
* Reads all the available data from the connection. This call is non-blocking.
*
* @param error Will be set to the error that occured.
* @return The bytes read from the connection or <c>nil</c> if an error occurred.
*/
//- (NSData *)read: (NSError**)error;
[Internal, Export ("read:")]
NSData _read(IntPtr error);
/**
* Returns <c>YES</c> if at least one byte is available for reading from this connection.
*
* @return <c>YES</c> if there is data available.
*/
//- (BOOL) hasBytesAvailable;
[Export ("hasBytesAvailable")]
bool hasBytesAvailable();
/**
* Causes the currently executing thread to sleep until <c>hasBytesAvailable</c> equals <c>YES</c>, or for a maximum of
* <c>maxTimeout</c> milliseconds.
*
* @param maxTimeout Maximum time in milliseconds to wait for an initial response f开发者_如何学JAVArom the printer.
*/
//- (void) waitForData: (NSInteger)maxTimeout;
[Export ("waitForData:")]
void waitForData(int maxTimeout);
}
}
In the enums.cs I simply list the enums, no namespace and I use the template of an empty c# file:
public enum PrinterLanguage
{
/**
* Printer control language ZPL
*/
PRINTER_LANGUAGE_ZPL,
/**
* Printer control language CPCL
*/
PRINTER_LANGUAGE_CPCL
}
At this point I have no problems with the build, I can get a .dll using bash
/Developer/MonoTouch/usr/bin/btouch Main.cs -s:enums.cs -out:btouchtest.dll
The issues start when I try to use a "helper class" for exporting methods that require the handling of some pointers. The tutorial is clear with the binding of methods with arguments like (NSError **), so I create the helper.cs file
using System;
using MonoTouch.Foundation;
namespace btouchtest
{
partial class ZebraPrinterConnection
{
int write (NSData data, out NSError error)
{
unsafe
{
IntPtr error;
IntPtr ptr_to_error = (IntPtr) (&error);
_write(data, ptr_to_error);
if (error != IntPtr.Zero)
error = (NSError) Runtime.GetNSObject (error);
else
error = null;
}
}
NSData read (out NSError error)
{
unsafe
{
IntPtr error;
IntPtr ptr_to_error = (IntPtr) (&error);
_read(ptr_to_error);
if (error != IntPtr.Zero)
error = (NSError) Runtime.GetNSObject (error);
else
error = null;
}
}
}
}
The build this time goes like this:
/Developer/MonoTouch/usr/bin/btouch -unsafe -out:btouchtest.dll Main.cs helper.c
And bingo!, instead of a nice .dll, btouch spits all kinds of errors:
Main.cs(8,19): error CS0260: Missing partial modifier on declaration of type `btouchtest.ZebraPrinterConnection'. Another partial declaration of this type exists
helper.cs(7,23): (Location of the symbol related to previous error)
helper.cs(7,23): error CS0261: Partial declarations of `btouchtest.ZebraPrinterConnection' must be all classes, all structs or all interfaces
Main.cs(8,19): (Location of the symbol related to previous error)
helper.cs(13,25): error CS0136: A local variable named `error' cannot be declared in this scope because it would give a different meaning to `error', which is already used in a `parent or current' scope to denote something else
helper.cs(10,21): error CS0531: `btouchtest.ZebraPrinterConnection.write(NSData, out NSError)': interface members cannot have a definition
helper.cs(27,25): error CS0136: A local variable named `error' cannot be declared in this scope because it would give a different meaning to `error', which is already used in a `parent or current' scope to denote something else
helper.cs(24,24): error CS0531: `btouchtest.ZebraPrinterConnection.read(out NSError)': interface members cannot have a definition
Compilation failed: 6 error(s), 0 warnings
btouch: API binding contains errors.
What I get out of this is that in the same namespace I got an interface named "ZebraPrinterConnection" and also a partial class named "ZebraPrinterConnection". I dunno how to handle this because I am just following the guideline.
The other issue comes from using the next snippet for handling (NSError **), and it is the sample shown in the Binding Objective-C tutorial, so something is wrong.
I declare my exported methods:
[Internal, Export ("write:error:")]
int _write(NSData data, IntPtr error);
[Internal, Export ("read:")]
NSData _read(IntPtr error);
because its objective-C signatures are:
(NSInteger) write:(NSData *)data error:(NSError **)error;
(NSData *)read: (NSError**)error;
and I need to implement the helper class, according to the tutorial, for handling the error with something like what is shown before in the source code of the helper class (which in turn is very sound to me, as I need to handle a pointer to a pointer):
int write (NSData data, out NSError error)
{
unsafe
{
IntPtr error;
IntPtr ptr_to_error = (IntPtr) (&error);
_write(data, ptr_to_error);
if (error != IntPtr.Zero)
error = (NSError) Runtime.GetNSObject (error);
else
error = null;
}
}
NSData read (out NSError error)
{
unsafe
{
IntPtr error;
IntPtr ptr_to_error = (IntPtr) (&error);
_read(ptr_to_error);
if (error != IntPtr.Zero)
error = (NSError) Runtime.GetNSObject (error);
else
error = null;
}
}
But btouch hates this!!! When trying to build it yells:
helper.cs(27,25): error CS0136: A local variable named `error' cannot be declared in this scope because it would give a different meaning to `error', which is already used in a `parent or current' scope to denote something else
After everything mentioned ... I downloaded a binding source sample from http://mtcocos2d.googlecode.com/svn/trunk , it is an 'almost working' port of Cocos2D to Monotouch, additionally to the source code one can find a lib.a and .dll available, so I suppose the binding source code can be "btouch"-ed and generate my own lib based on the source code provided ...
/Developer/MonoTouch/usr/bin/btouch -unsafe -out:cocos2d.dll -s:cocos2d.cs enums.cs extensions.cs structs.cs
AND NO!!!!! Btouch spits like 36 errors identical to mine ... so I am doomed ...
I've been comparing the source files from this binding demo and I see no big differences in the general structure, same type of files, same type of interfaces, same type of classes ... all brackets closed ...
I'd really appreciate your help, I'm no expert on C# but I have lots of iOS developing experience ... but in this new job we gotta work under MonoTouch, so I am still learning.
PLEASE HELP!!!! And many thanx in advance!!
It would be useful if you posted snippets (and links) to the objective-c headers. Maybe ZebraPrinter is not suppose to be defined with [Model]. And it is always useful to include in your description the version of MT you are using.
精彩评论