ネイティブ フレームワークRedpark Serial SDK 1.0.5をバインディング ライブラリ (名前: RedparkBinding) に変換し、プロジェクトの 1 つで使用しています。
ウォークスルー: iOS Objective-C ライブラリの バインド RedparkBinding プロジェクトのビルド結果で、各手順を慎重に実行しました。
しかし、私は奇妙な問題に直面しています。起動時にアプリがクラッシュします (理由: NullReferenceException - SDK 内には、常に null になるシングルトン クラスがあります)。
詳細:
- これは、DEBUG モードと RELEASE モードで発生します。
- サポートされるアーキテクチャは ARM64 です
- リンカーの動作 : リンク フレームワーク SDK のみ
- ネイティブ SDK サンプルは完全に実行されます。
ネイティブ iOS アプリケーションでも使用されているため、ライブラリ自体が期待どおりに機能していることはわかっています。Binding プロジェクトの構成で不足しているものを見つけようとしています。
私の .a ライブラリに関連付けられているソース .h ファイルは次のとおりです。
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
// DEFAULT VALUES
// baudRate == 9600
// dataConfiguration == kDataConfig_8N1
// enableRtsCtsFlowControl == NO
// enableDtrDsrFlowControl == NO
// enableSoftwareFlowControl == NO
// dtr == FALSE
// rts == FALSE
enum SerialPortDataConfiguration
{
kDataConfig_8N1, // 8bit, no parity, one stop bit
kDataConfig_8O1, // 8bit, odd parity, one stop bit
kDataConfig_8E1, // 8bit, even parity, one stop bit
kDataConfig_7O1, // 7bit, odd parity, one stop bit
kDataConfig_7E1, // 7bit, even parity, one stop bit
kDataConfig_8N2, // 8bit, no parity, two stop bits
kDataConfig_8O2, // 8bit, odd parity, two stop bits
kDataConfig_8E2, // 8bit, even parity, two stop bits
};
@class RedSerialPort;
@protocol RedSerialPortDelegate <NSObject>
@optional
// called when serial port's transmit FIFO is empty
-(void) transmitFifoIsEmpty:(RedSerialPort *)thePort;
// called when any of the rx modem signals change state (CTS, DSR, DCD or RI)
// user can check value of each modem signal property to determine current state
// optionally, user can set an observer for the modem signal property interested in
- (void) modemSignalChange:(RedSerialPort *)thePort;
// called when TX or RX Flow Control state changes
- (void) flowControlStateChange:(RedSerialPort *)thePort flowControlIsHalted:(BOOL)isFlowHalted;
@end
@interface RedSerialPort : NSObject
{
}
@property (nonatomic, weak) id <RedSerialPortDelegate> delegate;
@property (readonly) BOOL cts;
@property (readonly) BOOL dsr;
@property (readonly) BOOL dcd;
@property (readonly) BOOL ri;
@property (nonatomic) BOOL dtr;
@property (nonatomic) BOOL rts;
@property (readonly) BOOL isFlowConbtrolHalted;
@property (nonatomic) int baudRate;
@property (nonatomic) enum SerialPortDataConfiguration dataConfiguration;
@property (nonatomic) BOOL enableRtsCtsFlowControl;
@property (nonatomic) BOOL enableDtrDsrFlowControl;
@property (nonatomic) BOOL enableSoftwareFlowControl;
// send NSData bytes over serial connection
// calls sendCompleteBlock when all bytes in the NSData are transferred from UART FIFO
-(BOOL)sendData:(NSData *)data sendDataComplete:(void (^)(void))sendCompleteBlock;
// post a read to the serial port
// recvCompleBlock is called when bytes are received
-(BOOL)recvData:(void (^)(NSData *))recvCompleteBlock;
/* =============================================================*/
enum
{
kFwUpdataComplete = 0,
kFwUpdataInProgress = 1,
kFwUpdataErasingSectors = 2,
kFwUpdataRebootingDevice = 3,
kFwUpdataBadAddress = 0x81,
kFwUpdataVerifyFailed = 0x82,
kFwUpdataWriteError = 0x83,
kFwUpdataBadLength = 0x84,
kFwUpdataFlashTimeout = 0x85
};
// Check if connected serial device has latest firmware
-(BOOL)isFirmwareCurrent;
// update serial device firmware to latest version
// updateProgressBlock will be called with firmare download progress
// progress is a value 0-100 indicating the percent of file downloaded.
// state = kFwUpdataInProgress - download is in progress.
// state = kFwUpdataComplete - download is complete and was successful
// state = kFwUpdataRebootingDevice - normal expected state during update
// state = kFwUpdataErasingSectors - normal expected state during update
// state = 0x8n - an error occurred during download and was stopped. Cable was not updated.
-(void)updateFirmware:(void (^)(int progress, uint8_t state))updateProgressBlock;
@end
@protocol RedSerialDeviceManagerDelegate <NSObject>
//
// called when a device is discovered
//
- (void) deviceDetected:(RedSerialPort *)thePort;
//
// called when device connection is broken, object is now orphaned
//
- (void) deviceDisconnected:(RedSerialPort *)thePort;
@end
@interface RedSerialDeviceManager : NSObject
{
}
@property (nonatomic, weak) id <RedSerialDeviceManagerDelegate> delegate;
// return singleton RedSerialDeviceManager
+ (RedSerialDeviceManager *)sharedManager;
// Call to enumerate connected device or register for notifications
// app should call this once at app launch
- (void) startDiscovery;
// application must call this when re-entering foreground to resume communication
// session with accessory
-(void) resume;
// called to clean up existing communication sessions with device
// app must call when going into background
- (void) stop;
@end
NS_ASSUME_NONNULL_END
そして、これがsharpieで作成されたC#関連のインターフェースです
using System;
using Foundation;
using ObjCRuntime;
namespace RedparkLibrary
{
// @protocol RedSerialPortDelegate <NSObject>
[Protocol, Model(AutoGeneratedName = true)]
[BaseType(typeof(NSObject))]
interface RedSerialPortDelegate
{
// @optional -(void)transmitFifoIsEmpty:(RedSerialPort * _Nonnull)thePort;
[Export("transmitFifoIsEmpty:")]
void TransmitFifoIsEmpty(RedSerialPort thePort);
// @optional -(void)modemSignalChange:(RedSerialPort * _Nonnull)thePort;
[Export("modemSignalChange:")]
void ModemSignalChange(RedSerialPort thePort);
// @optional -(void)flowControlStateChange:(RedSerialPort * _Nonnull)thePort flowControlIsHalted:(BOOL)isFlowHalted;
[Export("flowControlStateChange:flowControlIsHalted:")]
void FlowControlStateChange(RedSerialPort thePort, bool isFlowHalted);
}
// @interface RedSerialPort : NSObject
[BaseType(typeof(NSObject))]
interface RedSerialPort
{
[Wrap("WeakDelegate")]
[NullAllowed]
RedSerialPortDelegate Delegate { get; set; }
// @property (nonatomic, weak) id<RedSerialPortDelegate> _Nullable delegate;
[NullAllowed, Export("delegate", ArgumentSemantic.Weak)]
NSObject WeakDelegate { get; set; }
// @property (readonly) BOOL cts;
[Export("cts")]
bool Cts { get; }
// @property (readonly) BOOL dsr;
[Export("dsr")]
bool Dsr { get; }
// @property (readonly) BOOL dcd;
[Export("dcd")]
bool Dcd { get; }
// @property (readonly) BOOL ri;
[Export("ri")]
bool Ri { get; }
// @property (nonatomic) BOOL dtr;
[Export("dtr")]
bool Dtr { get; set; }
// @property (nonatomic) BOOL rts;
[Export("rts")]
bool Rts { get; set; }
// @property (readonly) BOOL isFlowConbtrolHalted;
[Export("isFlowConbtrolHalted")]
bool IsFlowConbtrolHalted { get; }
// @property (nonatomic) int baudRate;
[Export("baudRate")]
int BaudRate { get; set; }
// @property (nonatomic) enum SerialPortDataConfiguration dataConfiguration;
[Export("dataConfiguration", ArgumentSemantic.Assign)]
SerialPortDataConfiguration DataConfiguration { get; set; }
// @property (nonatomic) BOOL enableRtsCtsFlowControl;
[Export("enableRtsCtsFlowControl")]
bool EnableRtsCtsFlowControl { get; set; }
// @property (nonatomic) BOOL enableDtrDsrFlowControl;
[Export("enableDtrDsrFlowControl")]
bool EnableDtrDsrFlowControl { get; set; }
// @property (nonatomic) BOOL enableSoftwareFlowControl;
[Export("enableSoftwareFlowControl")]
bool EnableSoftwareFlowControl { get; set; }
// -(BOOL)sendData:(NSData * _Nonnull)data sendDataComplete:(void (^ _Nonnull)(void))sendCompleteBlock;
[Export("sendData:sendDataComplete:")]
bool SendData(NSData data, Action sendCompleteBlock);
// -(BOOL)recvData:(void (^ _Nonnull)(NSData * _Nonnull))recvCompleteBlock;
[Export("recvData:")]
bool RecvData(Action<NSData> recvCompleteBlock);
// -(BOOL)isFirmwareCurrent;
[Export("isFirmwareCurrent")]
bool IsFirmwareCurrent { get; }
// -(void)updateFirmware:(void (^ _Nonnull)(int, uint8_t))updateProgressBlock;
[Export("updateFirmware:")]
void UpdateFirmware(Action<int, byte> updateProgressBlock);
}
// @protocol RedSerialDeviceManagerDelegate <NSObject>
[Protocol, Model(AutoGeneratedName = true)]
[BaseType(typeof(NSObject))]
interface RedSerialDeviceManagerDelegate
{
// @required -(void)deviceDetected:(RedSerialPort * _Nonnull)thePort;
[Abstract]
[Export("deviceDetected:")]
void DeviceDetected(RedSerialPort thePort);
// @required -(void)deviceDisconnected:(RedSerialPort * _Nonnull)thePort;
[Abstract]
[Export("deviceDisconnected:")]
void DeviceDisconnected(RedSerialPort thePort);
}
// @interface RedSerialDeviceManager : NSObject
[BaseType(typeof(NSObject))]
interface RedSerialDeviceManager
{
[Wrap("WeakDelegate")]
[NullAllowed]
RedSerialDeviceManagerDelegate Delegate { get; set; }
// @property (nonatomic, weak) id<RedSerialDeviceManagerDelegate> _Nullable delegate;
[NullAllowed, Export("delegate", ArgumentSemantic.Weak)]
NSObject WeakDelegate { get; set; }
// +(RedSerialDeviceManager * _Nonnull)sharedManager;
[Static]
[Export("sharedManager")]
RedSerialDeviceManager SharedManager { get; }
// -(void)startDiscovery;
[Export("startDiscovery")]
void StartDiscovery();
// -(void)resume;
[Export("resume")]
void Resume();
// -(void)stop;
[Export("stop")]
void Stop();
}
// @interface RedparkBinding : NSObject
[BaseType(typeof(NSObject))]
interface RedparkBinding
{
}
}
.a ファイルの LinkWith オプションは次のとおりです。
[assembly: LinkWith("libRedparkBinding.a”, SmartLink = true, ForceLoad = true)]
そして Makefile ファイル:
XBUILD=/Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild
PROJECT_ROOT=./RedparkBinding
PROJECT=$(PROJECT_ROOT)/RedparkBinding.xcodeproj
TARGET=RedparkBinding
all: lib$(TARGET).a
lib$(TARGET)-arm64.a:
$(XBUILD) -project $(PROJECT) -target $(TARGET) -sdk iphoneos -arch arm64 -configuration Release clean build
-mv $(PROJECT_ROOT)/build/Release-iphoneos/lib$(TARGET).a $@
lib$(TARGET).a: lib$(TARGET)-arm64.a
xcrun -sdk iphoneos lipo -create -output $@ $^
clean:
-rm -f *.a *.dll
また、必要なすべてのファイル(ネイティブ ライブラリ フレームワーク、ネイティブ ライブラリ サンプル コード、バインディング コード、SDK ユーザー ガイド) をここに添付します。
コミュニティからの提案に感謝します。