1

我正在尝试将 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)
            {
            }
        }
    }
}
4

1 回答 1

1

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

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

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

于 2013-02-09T22:59:13.133 回答