3
votes

I'm working on creating a MonoTouch binding for the Brother PJ-673 portable printer. This is to be used in a Xamarin.iOS iPad/iPhone application. Brother provides an SDK in Objective-C, which can be found at http://www.brother.com/product/dev/mobile/ios/download/index.htm

To start I have used the Xamarin MonoTouch Binding Objective-C guide and created a bindings project which seemed to work fine. Below is a glimpse of my ApiDefinition.cs file (used Objective Sharpie for the first draft of the file and then changed it manually)

using System;
using System.Drawing;
using MonoTouch.CoreGraphics;
using MonoTouch.ObjCRuntime;
using MonoTouch.Foundation;
using MonoTouch.UIKit;

namespace BrotherTouchPrinterBinding
{
    [BaseType (typeof (NSObject), Name = "BRPtouchNetworkInfo")]
    public partial interface BrotherPrintTouchNetworkInfo {

        [Export ("strIPAddress", ArgumentSemantic.Copy)]
        string IPAddress { get; set; }

        [Export ("strLocation", ArgumentSemantic.Copy)]
        string Location { get; set; }

        [Export ("strModelName", ArgumentSemantic.Copy)]
        string ModelName { get; set; }

        [Export ("strSerialNumber", ArgumentSemantic.Copy)]
        string SerialNumber { get; set; }

        [Export ("strNodeName", ArgumentSemantic.Copy)]
        string NodeName { get; set; }

        [Export ("strMACAddress", ArgumentSemantic.Copy)]
        string MACAddress { get; set; }
    }

    [BaseType (typeof (NSObject), Name = "BRPtouchNetwork",
       Delegates = new string[] {"WeakDelegate"},
        Events = new Type [] { typeof (BrotherPrintTouchNetworkDelegate) })]
    public partial interface BrotherPrinterTouchNetwork {

        [Export ("startSearch:")]
        int StartSearch (int nTimeout);

        [Export ("getPrinterNetInfo:")] 
        NSObject [] GetPrinterNetInfo ();

        [Export ("initWithPrinterName:")]
        void InitWithPrinterName (string strPrinterName);

        [Export ("setPrinterName:")]
        bool SetPrinterName (string strPrinterName);

        [Wrap ("WeakDelegate")][NullAllowed]
        BrotherPrintTouchNetworkDelegate Delegate { get; set; }

        [Export("delegate")][NullAllowed]
        NSObject WeakDelegate { get; set; }
    }

    [BaseType (typeof (NSObject), Name = "BRPtouchNetworkDelegate")]
    [Protocol]
    [Model]
    public partial interface BrotherPrintTouchNetworkDelegate {

        [Export ("didFinishedSearch:")]
        void DidFinishedSearch (NSObject sender);
    }

    [BaseType (typeof (NSObject), Name = "BRPtouchPrintInfo" )]
    public partial interface BrotherPrintTouchPrintInfo {

        [Export ("strPaperName", ArgumentSemantic.Retain)]
        string PaperName { get; set; }

        [Export ("ulOption")]
        uint Option { get; set; }

        [Export ("nPrintMode")]
        int PrintMode { get; set; }

        [Export ("nDensity")]
        int Density { get; set; }

        [Export ("nOrientation")]
        int Orientation { get; set; }

        [Export ("nHalftone")]
        int Halftone { get; set; }

        [Export ("nHorizontalAlign")]
        int HorizontalAlign { get; set; }

        [Export ("nVerticalAlign")]
        int VerticalAlign { get; set; }

        [Export ("nPaperAlign")]
        int PaperAlign { get; set; }

        [Export ("nExtFlag")]
        int ExtFlag { get; set; }

        [Export ("nAutoCutFlag")]
        int AutoCutFlag { get; set; }

        [Export ("nAutoCutCopies")]
        int AutoCutCopies { get; set; }
    }

    [BaseType (typeof (NSObject), Name = "BRPtouchPrinterData")]
    public partial interface BrotherPrintTouchPrinterData {

        [Export ("getPrinterList:")]
        NSObject [] GetPrinterList ();
    }

    [BaseType (typeof (NSObject), Name = "BRPtouchPrinter")]
    public partial interface BrotherPrintTouchPrinter {

        [Export ("setIPAddress:")]
        void SetIPAddress (string ipAddress);

        [Export ("sendFile::")]
        int SendFile (string strFile, int nTimeout);

        [Export ("sendData::")]
        int SendData (NSData dataData, int nTimeout);

        [Export ("sendFileEx:timeout:")]
        int SendFileEx (string strFile, int nTimeout);

        [Export ("sendDataEx:timeout:")]
        int SendDataEx (NSData dataData, int nTimeout);

        [Export ("initWithPrinterName:")]
        IntPtr Constructor (string strPrinterName);

        [Export ("setPrinterName:")]
        bool SetPrinterName (string strPrinterName);

        [Export ("isPrinterReady:")]
        bool IsPrinterReady ();

        [Export ("getPTStatus:")]
        int GetPtStatus (PTSTATUS status);

        [Export ("printImage:copy:timeout:")]
        int PrintImage (CGImage imageRef, int nCopy, int nTimeout);

        [Export ("setPrintInfo:")]
        int SetPrintInfo (BrotherPrintTouchPrintInfo printInfo);

        [Export ("setCustomPaperFile:")]
        bool SetCustomPaperFile (string strFilePath);

        [Export ("setEncryptKey:keyEx:")]
        bool SetEncryptKey (string strKey, string strKeyEx);

        [Export ("startPrint:")]
        int StartPrint ();

        [Export ("endPrint:")]
        void EndPrint ();
    }
}

The MonoTouch binding project compiles successfully, so next I created a small test application. The code below is how I create native instances of relevant Brother types:

partial void PrintTouchDown (NSObject sender)
        {       
            // Initialize printer settings
            BrotherPrintTouchPrintInfo printInfo = new BrotherPrintTouchPrintInfo();

            printInfo.PaperName = "A4_CutSheet";
            printInfo.PrintMode = (int)PrintMode.PRINT_FIT;
            printInfo.Density = 5;
            printInfo.Orientation = (int)Orientation.ORI_PORTRATE;
            printInfo.Halftone = (int)Halftone.HALFTONE_ERRDIF;
            printInfo.HorizontalAlign = (int)HorizontalAlign.ALIGN_CENTER;
            printInfo.VerticalAlign = (int)VerticalAlign.ALIGN_MIDDLE;
            printInfo.PaperAlign = (int)PaperAlign.PAPERALIGN_LEFT;
            printInfo.ExtFlag |= 0;

            // Initialize PJ-673 printer
            BrotherPrintTouchPrinter printer = new BrotherPrintTouchPrinter("Brother PJ-673");
            printer.SetIPAddress("10.20.2.104");
            printer.SetPrintInfo(printInfo);

            //printer.PrintImage(selectedImage.CGImage, 1, 1000);
        }

Everything works fine until the call printer.SetPrinterInfo(printInfo) This is where the app crashed with no exception. The application output is:

mono-rt: Stacktrace:

mono-rt:   at <unknown> <0xffffffff>
mono-rt:   at (wrapper managed-to-native) MonoTouch.ObjCRuntime.Messaging.int_objc_msgSend_IntPtr (intptr,intptr,intptr) <IL 0x00027, 0xffffffff>
mono-rt:   at BrotherTouchPrinterBinding.BrotherPrintTouchPrinter.SetPrintInfo (BrotherTouchPrinterBinding.BrotherPrintTouchPrintInfo) <IL 0x0002f, 0x000df>
mono-rt:   at BrotherTouchPrinter.iOS.BrotherTouchPrinter_iOSViewController.PrintTouchDown (MonoTouch.Foundation.NSObject) [0x00069] in /Users/claudiu/Projects/BrotherTouchPrinterBinding/BrotherTouchPrinter.iOS/BrotherTouchPrinter.iOSViewController.cs:82
mono-rt:   at (wrapper runtime-invoke) <Module>.runtime_invoke_void__this___object (object,intptr,intptr,intptr) <IL 0x00052, 0xffffffff>
mono-rt:   at <unknown> <0xffffffff>
mono-rt:   at (wrapper managed-to-native) MonoTouch.UIKit.UIApplication.UIApplicationMain (int,string[],intptr,intptr) <IL 0x0009f, 0xffffffff>
mono-rt:   at MonoTouch.UIKit.UIApplication.Main (string[],string,string) [0x0004c] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIApplication.cs:38
mono-rt:   at BrotherTouchPrinter.iOS.Application.Main (string[]) [0x00008] in /Users/claudiu/Projects/BrotherTouchPrinterBinding/BrotherTouchPrinter.iOS/Main.cs:16
mono-rt:   at (wrapper runtime-invoke) <Module>.runtime_invoke_void_object (object,intptr,intptr,intptr) <IL 0x00050, 0xffffffff
mono-rt: 
Native stacktrace:

mono-rt: 
=================================================================
Got a SIGSEGV while executing native code. This usually indicates
a fatal error in the mono runtime or one of the native libraries 
used by your application.
=================================================================

Any help solving this issue is greatly appreciated. I'm quite new to Xamarin development and I'm not sure what can I do to troubleshoot the issue. I'm pretty sure it's something related to my MonoTouch bindings since the Brother SDK contains a working sample application written in Objective-C, so I don't think there is a problem with the library itself.

Thanks

1
Did you ever find an answer to this?jharr100
I am not even able to get pass the first line. I am getting the following error. Could not create an native instance of the type 'bpsdkBinding.BRPtouchPrintInfo': the native class hasn't been loaded. It is possible to ignore this condition by setting ObjCRuntime.Class.ThrowOnInitFailure to false.Anand
Does anyone have a fully working link between iOS, Xamarin, and the Brother print SDK? I've gotten it compiling and running, but it's not actually printing anything, (and there are no error messages I can find.) github.com/moginheden/brotherPrint (The android version in this solution does work.)Brian Heward
I wasn't capturing the int the PrintImage function returned, that was the error message. I've updated my github project with working code for both iOS and Android if anyone finds this comment and wants an example of Xamarin <-> brother printer that actually prints.Brian Heward

1 Answers

0
votes

The stacktrace you provided shows:

mono-rt: at BrotherTouchPrinterBinding.BrotherPrintTouchPrinter.PrintImage (MonoTouch.CoreGraphics.CGImage,int,int)

which is:

  1. after the call to printer.SetPrinterInfo(printInfo), so it does not seems to crash there

  2. a line commented in your source.

Are you sure the source code (above) match the stack trace ?

Or do you mean the crash occurs later (at print time) but only when printer.SetPrinterInfo(printInfo) was called ?

note: you can edit your question to add / update information