在 MonoTouch 中使用 Redpark SDK

Posted

技术标签:

【中文标题】在 MonoTouch 中使用 Redpark SDK【英文标题】:Using the Redpark SDK in MonoTouch 【发布时间】:2012-09-08 18:15:08 【问题描述】:

我正在尝试将 MonoTouch 与 Redpark SDK 一起使用,并在 C# 中复制一个用 Objective-C 编写的 Redpark 串行电缆示例程序(我可以在 Xcode 中完美运行):

https://github.com/bjepson/iPhone-Arduino-Simple-Switch

我使用了在这里找到的现有绑定:

https://github.com/mono/monotouch-bindings/tree/master/Redpark

并创建了一个 .dll 用于我的项目。在我的项目中,一切都进行得很顺利(我能够让 cableConnected 和 cableDisconnected 委托回调正常工作)直到尝试编写。当我尝试使用 Write 函数时,程序会因 SIGSEGV 崩溃:

Stacktrace:

 at MonoTouch.RedPark.RscMgr.Write (int16,uint) <IL 0x00010, 0x00113>
  at tester2.tester2ViewController.toggleLED (MonoTouch.Foundation.NSObject) [0x00069] in /Users/salgarcia/Projects/tester2/tester2/tester2ViewController.cs:57
  at (wrapper runtime-invoke) object.runtime_invoke_dynamic (intptr,intptr,intptr,intptr) <0xffffffff>
  at MonoTouch.UIKit.UIApplication.Main (string[],string,string) [0x0004c] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIApplication.cs:38
  at tester2.Application.Main (string[]) [0x00000] in /Users/salgarcia/Projects/tester2/tester2/Main.cs:17
  at (wrapper runtime-invoke) object.runtime_invoke_dynamic (intptr,intptr,intptr,intptr) <0xffffffff>

Native stacktrace:

0   tester2                             0x001c2a25 mono_handle_native_sigsegv + 244
1   tester2                             0x001af065 mono_sigsegv_signal_handler + 172
2   libsystem_c.dylib                   0x329f17ed _sigtramp + 48
3   tester2                             0x00003a63 __inline_memcpy_chk + 30
4   tester2                             0x00003a63 __inline_memcpy_chk + 30
5   tester2                             0x00004011 -[RscMgr writeRscMessage:Length:MsgData:] + 220
6   tester2                             0x00004131 -[RscMgr write:Length:] + 100
7   tester2                             0x000438d8 wrapper_managed_to_native_ApiDefinition_Messaging_int_objc_msgSend_short_UInt32_intptr_intptr_int16_uint + 256
8   tester2                             0x001aa024 tester2_tester2ViewController_toggleLED_MonoTouch_Foundation_NSObject + 680
9   tester2                             0x000f76c0 wrapper_runtime_invoke_object_runtime_invoke_dynamic_intptr_intptr_intptr_intptr + 200
10  tester2                             0x001b0843 mono_jit_runtime_invoke + 1054
11  tester2                             0x0022c40f mono_runtime_invoke + 90
12  tester2                             0x001ad14d native_to_managed_trampoline_tester2_tester2ViewController_toggleLED + 220
13  CoreFoundation                      0x3553f3fd -[NSObject performSelector:withObject:withObject:] + 52
14  UIKit                               0x33034e07 -[UIApplication sendAction:to:from:forEvent:] + 62
15  UIKit                               0x33034dc3 -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 30
16  UIKit                               0x33034da1 -[UIControl sendAction:to:forEvent:] + 44
17  UIKit                               0x33034b11 -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 492
18  Foundation                          0x350ff933 __NSFireDelayedPerform + 414
19  CoreFoundation                      0x355b9a33 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 14
20  CoreFoundation                      0x355b9699 __CFRunLoopDoTimer + 364
21  CoreFoundation                      0x355b826f __CFRunLoopRun + 1206
22  CoreFoundation                      0x3553b4a5 CFRunLoopRunSpecific + 300
23  CoreFoundation                      0x3553b36d CFRunLoopRunInMode + 104
24  GraphicsServices                    0x371d7439 GSEventRunModal + 136
25  UIKit                               0x33047cd5 UIApplicationMain + 1080
26  tester2                             0x0001fcc4 wrapper_managed_to_native_MonoTouch_UIKit_UIApplication_UIApplicationMain_int_string___intptr_intptr + 240
27  tester2                             0x001a9744 tester2_Application_Main_string__ + 152
28  tester2                             0x000f76c0 wrapper_runtime_invoke_object_runtime_invoke_dynamic_intptr_intptr_intptr_intptr + 200
29  tester2                             0x001b0843 mono_jit_runtime_invoke + 1054
30  tester2                             0x0022c40f mono_runtime_invoke + 90
31  tester2                             0x0022f123 mono_runtime_exec_main + 306
32  tester2                             0x00232a4f mono_runtime_run_main + 482
33  tester2                             0x001b529f mono_jit_exec + 94
34  tester2                             0x00271c70 main + 2216
35  tester2                             0x00004860 start + 40

=================================================================
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.
=================================================================

我正在寻找可能是什么问题的输入(即串行端口实际上没有打开,我可能为“txbuffer”使用了错误的数据类型,绑定没有正确实施,我没有正确设置委托等)对此的任何反馈将不胜感激!

作为参考,下面是我的 C#/MonoTouch 实现旁边的 Objective-C 实现:

Redpark 库的 Objective-C ".h" 文件

#import <Foundation/Foundation.h>
#import <ExternalAccessory/ExternalAccessoryDefines.h>
#import <ExternalAccessory/EAAccessoryManager.h>
#import <ExternalAccessory/EAAccessory.h>
#import <ExternalAccessory/EASession.h>

#include "redparkSerial.h"



enum
   
    kMsrCts = 0x01,
    kMsrRi =  0x02,
    kMsrDsr = 0x04,
    kMsrDcd = 0x08,

;

enum 
    kRSC_StreamBufferSize = 4096,
    kRSC_MaxMessageDataLength = 230,
    kRSC_SerialReadBufferSize = 4096,
    kRsc_TxFifoSize = 256,
    kRSC_NoPasscode = 0
;


typedef enum DataSizeType

    kDataSize7 = SERIAL_DATABITS_7,
    kDataSize8 = SERIAL_DATABITS_8
 DataSizeType;

typedef enum ParityType

    kParityNone = SERIAL_PARITY_NONE,
    kParityOdd = SERIAL_PARITY_ODD,
    kParityEven = SERIAL_PARITY_EVEN
 ParityType;

typedef enum StopBitsType

    kStopBits1 = STOPBITS_1,
    kStopBits2 = STOPBITS_2
 StopBitsType;


@protocol RscMgrDelegate;

@interface RscMgr : NSObject <NSStreamDelegate> 

    id <RscMgrDelegate> theDelegate;

    // EA api variables
    EASession *theSession;
    EAAccessory *theAccessory;
    NSArray *supportedProtocols;
    NSString *connectedProtocol;

    // rsc port control/info structures
    serialPortConfig portConfig;
    serialPortStatus portStatus;
    serialPortControl portControl;

    // EASession stream handling
    // for collecting RSC Messages
    unsigned char *rxStreamBuffer;
    int rxCount;
    int rxCountTotal;
    int txCountTotal;
    int rxRemain;
    int readLen;

    unsigned char *txStreamBuffer;
    int txIn;
    int txOut;
    int txStreamEmpty;

    // internal dtr and rts state bits
    int dtrState;
    int rtsState;   

    // serial data buffer
    // for collecting serial bytes received from the serial port
    UInt8 *serialReadBuffer;
    int serialReadIn;
    int serialReadOut;
    int serialReadBytesAvailable;

    BOOL encodingEnabled;   
    UInt32 thePasscode;



- (void) setDelegate:(id <RscMgrDelegate>) delegate;


// Initializes the RscMgr and reigsters for accessory connect/disconnect notifications. 
- (id) init;

// establish communication with the Redpark Serial Cable.  This call will also
// configure the serial port based on defaults or prior calls to set the port config
// (see setBaud, setDataSize, ...)
- (void) open;

// simple serial port config interface
// can be called anytime (even after open: call)
- (void) setBaud:(int)baud;
- (void) setDataSize:(DataSizeType)dataSize;
- (void) setParity:(ParityType)parity;
- (void) setStopBits:(StopBitsType)stopBits;

// read write serial bytes
- (int) write:(UInt8 *)data Length:(UInt32)length;
- (int) read:(UInt8 *)data Length:(UInt32)length;
- (int) getReadBytesAvailable;

/* 
 returns a bit field (see redparkSerial.h)
 0-3 current modem status bits for CTS, RI, DSR, DCD, 4-7 previous modem status bits

 MODEM_STAT_CTS  0x01
 MODEM_STAT_RI   0x02
 MODEM_STAT_DSR  0x04
 MODEM_STAT_DCD  0x08
 */
- (int) getModemStatus;

// returns true if DTR is asserted
- (BOOL) getDtr;

// returns true if RTS is asserted
- (BOOL) getRts;

// set DTR state 
- (void) setDtr:(BOOL)enable;

// set RTS state
- (void) setRts:(BOOL)enable;

// advanced (full) serial port config interface (see redparkSerial.h)
- (void) setPortConfig:(serialPortConfig *)config RequestStatus:(BOOL)reqStatus;
- (void) setPortControl:(serialPortControl *)control RequestStatus:(BOOL)reqStatus;
- (void) getPortConfig:(serialPortConfig *) portConfig;
- (void) getPortStatus:(serialPortStatus *) portStatus;

// advanced advanced
// write a raw message
- (int) writeRscMessage:(int)cmd Length:(int)len MsgData:(UInt8 *)msgData;

// GPS cable only - requires loopback connector
- (void) testGpsCable;

@end

@protocol RscMgrDelegate  <NSObject>

// Redpark Serial Cable has been connected and/or application moved to foreground.
// protocol is the string which matched from the protocol list passed to initWithProtocol:
- (void) cableConnected:(NSString *)protocol;

// Redpark Serial Cable was disconnected and/or application moved to background
- (void) cableDisconnected;

// serial port status has changed
// user can call getModemStatus or getPortStatus to get current state
- (void) portStatusChanged;

// bytes are available to be read (user calls read:)
- (void) readBytesAvailable:(UInt32)length;

@optional
// called when a response is received to a getPortConfig call
- (void) didReceivePortConfig;

// GPS Cable only - called with result when loop test completes.  
- (void) didGpsLoopTest:(BOOL)pass;

@end

Objective-C“.h”文件

#import <UIKit/UIKit.h>
#import "RscMgr.h"

#define BUFFER_LEN 1024

@interface HelloArduinoViewController : UIViewController <RscMgrDelegate> 

RscMgr *rscMgr;
UInt8 rxBuffer[BUFFER_LEN];
UInt8 txBuffer[BUFFER_LEN];

UISwitch *toggleSwitch;


@property (nonatomic, retain) IBOutlet UISwitch *toggleSwitch;
- (IBAction)toggleLED:(id)sender;

@end

Objective-C“.m”文件

#import "HelloArduinoViewController.h"

@implementation HelloArduinoViewController
@synthesize toggleSwitch;

- (void)dealloc

    [toggleSwitch release];
    [super dealloc];


- (void)didReceiveMemoryWarning

    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.


#pragma mark - View lifecycle


// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad

    [super viewDidLoad];
    rscMgr = [[RscMgr alloc] init]; 
    [rscMgr setDelegate:self];




- (void)viewDidUnload

    [self setToggleSwitch:nil];
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;


- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);


- (IBAction)toggleLED:(id)sender 
    if (toggleSwitch.on)  // check the state of the button
        txBuffer[0] = (int) '1';
     else 
        txBuffer[0] = (int) '0';
    

    // Send 0 or 1 to the Arduino
    [rscMgr write:txBuffer Length:1];        


#pragma mark - RscMgrDelegate methods

- (void) cableConnected:(NSString *)protocol 
    [rscMgr setBaud:9600];
    [rscMgr open]; 


- (void) cableDisconnected 



- (void) portStatusChanged 



- (void) readBytesAvailable:(UInt32)numBytes 


- (BOOL) rscMessageReceived:(UInt8 *)msg TotalLength:(int)len 
    return FALSE;    


- (void) didReceivePortConfig 


@end

我的 C#/MonoTouch 实现

using System;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using MonoTouch.RedPark;

namespace tester2

    public partial class tester2ViewController : UIViewController
    
        static RscMgr rscMgr;
        MyRedparkDelegate delegate1;

        short[] rxbuffer = new short[1024];
        short[] txbuffer = new short[1024];

        public tester2ViewController () : base ("tester2ViewController", null)
        
        

        public override void DidReceiveMemoryWarning ()
        
            base.DidReceiveMemoryWarning ();
        

        public override void ViewDidLoad ()
        
            base.ViewDidLoad ();
            rscMgr = new RscMgr();
            delegate1 = new MyRedparkDelegate ();
            rscMgr.SetDelegate(delegate1);
        

        public override void ViewDidUnload ()
        
            base.ViewDidUnload ();
            ReleaseDesignerOutlets ();
        

        public override bool ShouldAutorotateToInterfaceOrientation (UIInterfaceOrientation toInterfaceOrientation)
        
            return (toInterfaceOrientation != UIInterfaceOrientation.PortraitUpsideDown);
        

        partial void toggleLED (NSObject sender)
        
            if(toggleSwitch.On) 
                txbuffer[0] = (int) '1';
             else 
                txbuffer[0] = (int) '0';
            
            rscMgr.Write (txbuffer[0], 1);
        

        public class MyRedparkDelegate : RscMgrDelegate
        
            public MyRedparkDelegate ()
            
            
            public override void CableConnected (string protocol)
            
                rscMgr.SetBaud (9600);
                rscMgr.Open ();
            
            public override void CableDisconnected ()
            
            
            public override void PortStatusChanged ()
            
            
            public override void ReadBytesAvailable (uint length)
            
            
        
    

【问题讨论】:

您需要发布 RscMgr 的 Obj-C 头文件,以便有人帮助您。 我认为这需要特殊的硬件来测试? @miguel.de.icaza 只是用于这个特定问题的 redpark 串行电缆,但最后只是一个配备串行通信的设备(我只是在这个示例项目中使用基本的 arduino) 【参考方案1】:

问题在我的MonoTouch实现代码中解决了,发现需要通过引用来传递正在写入的数据,所以将上面代码中的Write改成

     rscMgr.Write(ref txbuffer[0],1);

它按预期工作。它有助于彻底阅读 SDK 下载随附的 Redpark 串行电缆 SDK 用户指南。

【讨论】:

以上是关于在 MonoTouch 中使用 Redpark SDK的主要内容,如果未能解决你的问题,请参考以下文章

RedPark 无法从串口读取数据:UIViewController 与 UINavigationController

帮助在monotouch中绑定一个静态objective-c库

我应该使用哪些 Instruments 工具来了解我的 Monotouch 应用程序的内存使用情况?

Monotouch - 在 monotouch 项目中附加 Sqlite 数据库并部署到 iPad

在 MonoTouch 应用程序中查看内存使用情况

如何在 MonoTouch 中使用 System.IO.Packaging