救命!将Objective-C库绑定到MonoTouch时的构建阶段的问题

时间:2011-03-17 19:57:14

标签: objective-c binding xamarin.ios

我目前正在研究ZebraLink打印机库的端口,以便在MonoTouch项目中使用。存在这些库以及为iOS创建的库,因此我获得了.a文件和使用Objective-C开发的一堆头文件。一旦我取得了一些成功,我很乐意上传它与任何有兴趣的人分享,但首先我要解决几个问题,我请求你的帮助:

我目前有3个班级 - > Main.cs,enums.cs和helpers.cs

在Main.cs中,我遵循Binding Objective-C教程中提到的基本结构

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 from the printer.
        */
        //- (void) waitForData: (NSInteger)maxTimeout;
        [Export ("waitForData:")]
        void waitForData(int maxTimeout); 
   }
}

在enums.cs中,我只列出枚举,没有命名空间,我使用空c#文件的模板:

public enum PrinterLanguage
{
    /**
     * Printer control language ZPL
     */
    PRINTER_LANGUAGE_ZPL,

    /**
     * Printer control language CPCL
     */
    PRINTER_LANGUAGE_CPCL
}

此时我对构建没有任何问题,我可以使用bash获得.dll

/Developer/MonoTouch/usr/bin/btouch Main.cs -s:enums.cs -out:btouchtest.dll

当我尝试使用“帮助程序类”导出需要处理某些指针的方法时,问题就开始了。教程很清楚,方法与参数(NSError **)的绑定,所以我创建了helper.cs文件

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

这次的构建是这样的:

/Developer/MonoTouch/usr/bin/btouch -unsafe -out:btouchtest.dll Main.cs helper.c

和宾果!而不是一个漂亮的.dll,btouch吐出各种错误:

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.

我得到的是,在同一个命名空间中,我得到了一个名为“ZebraPrinterConnection”的接口,还有一个名为“ZebraPrinterConnection”的部分类。我不知道如何处理这个因为我只是遵循指南。

另一个问题来自于使用下一个代码片段来处理(NSError **),它是Binding Objective-C教程中显示的示例,所以出了点问题。

我声明了我导出的方法:

[Internal, Export ("write:error:")]
int _write(NSData data, IntPtr error);

[Internal, Export ("read:")]
NSData _read(IntPtr error);

因为它的Objective-C签名是:

(NSInteger) write:(NSData *)data error:(NSError **)error;
(NSData *)read: (NSError**)error;

我需要实现辅助类,根据教程,处理错误的方式类似于之前在帮助类的源代码中显示的内容(这对我来说非常合理,因为我需要处理指针指针):

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

但是btouch讨厌这个!!!当试图建立它时大喊:

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

在提到的所有内容之后......我从http://mtcocos2d.googlecode.com/svn/trunk下载了一个绑定源示例,它是Cocos2D到Monotouch的“几乎工作”端口,除了源代码之外,还可以找到lib.a和.dll可用,所以我想绑定源代码可以是“btouch”-ed并根据提供的源代码生成我自己的lib ...

/Developer/MonoTouch/usr/bin/btouch -unsafe -out:cocos2d.dll -s:cocos2d.cs enums.cs extensions.cs structs.cs

不要!!!!! Btouch吐出的36个错误与我的相同......所以我注定要失败......

我一直在比较这个绑定演示中的源文件,我发现一般结构,相同类型的文件,相同类型的接口,相同类型的类没有太大的区别......所有括号都关闭...... < / p>

我真的很感谢你的帮助,我不是C#的专家,但我有很多iOS开发经验......但是在这个新工作中我们必须在MonoTouch下工作,所以我还在学习。

请帮助!!!!还有很多提前!!

1 个答案:

答案 0 :(得分:0)

如果您将片段(和链接)发布到objective-c标头,那将非常有用。也许ZebraPrinter不能用[Model]来定义。在您的描述中包含您正在使用的MT的版本总是有用的。