Swift Client - Intf errors

Hello,

I’m struggling to get started creating a simple test client in Swift (iOS simulation) - following https://docs.remotingsdk.com/IDEs/Xcode/ConnectToServer/

I’ve generated the intf and ServerAccess files from a RODL and added reference to RemObjectsSDK.framework (Debug-iphonesimulator). However, upon building, I get lots of errors, e.g.

Value of type ‘DataProviderService_Proxy’ has no member '___message’
Value of type ‘DataProviderService_Proxy’ has no member ‘___clientChannel’

where DataProviderService is the service name.

I’ve tried using Swift 3.2 and 4.0 and I’m using Xcode 9.2.

Any ideas? Is there a compatibility issue? Do you have a basic hello world project I could try and build?

Thanks,
Mark

I may have found the issue:

The ROServiceImporter (macos) seems to have 3 underscores before message/clientChannel but the ROProxy class only has 2.

Please can you confirm that’s the issue and can it be resolved? Or I can just search/replace!

Thanks,
Mark

are you mixing beta and release, somehow? we recently changed from 2 to 3 underscores, it that’s only in he beta, and the beta library should match the generated code…

I’m using the Importer you gave me in topic “ROServiceImporter (mac) crashes on import”

I’ve also noticed that there is an inconsistency in the number of underscores preceeding localMessage (sometimes 2, sometimes 3) in the same method,

Also, there are Date issues, such as:

Cannot assign value of type ‘Date?’ to type ‘NSDate!’

Regards,
Mark

I’ve tried to use the latest beta (library and importer) and there are still conflict between the intf generated and the library.

The importer generates using 2 underscores and is therefore labelled deprecated, there is still inconsistancy with the underscores proceeding the localMessage and there is still the Date issue.

Mark

Hmm, the importer in the latest beta generates two underscores still? that should have been changed. i’ll review. The NSDate issue is not something i’m aware of, i’ll need to have a look at that tomorrow… Does it reproduce with any RODL that uses the DateTime type?

Thanks, logged as bugs://79692

Found a couple places where this was missed, should be fixed for the next beta. (I assume for now you’re good with a manual search/replace as workaround, until we have a fixed build?

Ah, got it. this was fixed, but unfortunately the fix isn;'t active ion ROServiceImporter (fixed for the next beta). as a workaround, you can use the rodl2code command line tool; it uses the same codeine, but there the fix is active.

my apologies for the inconvenience.

bugs://79692 got closed with status fixed.

Thank you. I now have a usuable Intf file - well it builds at least.

Not sure what I doing wrong, and here’s where simple Swift client tutorials would be useful (I have failed to find any) but I’m ending up with an exception:

BinMessage: Invalid string length read from stream.

when calling a method that has inout parameters. Not sure whether this is due to some other code gen issue or whether I cam doing anything wrong.

	var userId: Int32 = 0
	var errorMessage: String! = ""

	let request = service.dataProviderService.beginLogin("serial", "username", "password")
	let result = service.dataProviderService.endLogin(request, &userId, &errorMessage)

Any suggestions or do you have any swift client examples to share?

Regards,
Mark

can you post the codegen for the method in question, and how it is defined? it does sound like some mismatch - either codegen bug or client and server not using the exact same definition of the method (say because it changed). what platform is the server?

DataProviderGateway.RODL (6.1 KB)
DataProviderIntf.zip (4.2 KB)

I’ve attached the RODL and Intf files. Server is .NET (only version 8.x) - this could well be the problem but over the years version compatibility has normally been quite good.

Mark

Hmm, it seems indeed that the inoiut param isn’t being sent, only read. can you adjust the method as such:

	@discardableResult
	public func beginLogin(_ DetectorIdentification: String!, _ UserName: String!, _ Password: String!) -> ROAsyncRequest! {
		let __localMessage: ROMessage! = (self.___message.copy() as! ROMessage)
		__localMessage.initialize(asRequest: self.___clientChannel, libraryName: "DataProviderGatewayLibrary", interfaceName: self.__getActiveInterfaceName(), messageName: "Login")
		__localMessage.writeUtf8String(DetectorIdentification, withName: "DetectorIdentification")
		__localMessage.writeUtf8String(UserName, withName: "UserName")
		__localMessage.writeUtf8String(Password, withName: "Password")
		__localMessage.writeUtf8String(ErrorMessage, withName: "ErrorMessage")
		__localMessage.finalizeMessage()
		return self.___clientChannel.asyncDispatch(__localMessage, with: self, start: true)
	}

and see if that fixes the problem? I’ll investigate WHY this is missing, and if its a general Cocoa codeine problem or specific to the Swift one, tomorrow.

Hmm, no actually this looks fine.

<Operation Name="Login" UID="{E42DD455-0000-46AA-AE3D-AF7040DCBD2A}">
<Parameters>
<Parameter Name="Result" DataType="Boolean" Flag="Result">
</Parameter>
<Parameter Name="DetectorIdentification" DataType="Utf8String" Flag="In" >
</Parameter>
<Parameter Name="UserName" DataType="Utf8String" Flag="In" >
</Parameter>
<Parameter Name="Password" DataType="Utf8String" Flag="In" >
</Parameter>
<Parameter Name="UserID" DataType="Integer" Flag="Out" >
</Parameter>
<Parameter Name="ErrorMessage" DataType="Utf8String" Flag="Out" >
</Parameter>
</Parameters>
</Operation>

ErrorMessage is Out, not InOut, so this is correct (Apple Swift just does;t support true out-only params, thats why the method is declared as inout. so that’s fine. endLogin looks good too:

	public func endLogin(_ ___asyncRequest: ROAsyncRequest!, _ UserID: inout Int32, _ ErrorMessage: inout String!) -> Bool {
		var ___result: Bool
		let ___localMessage: ROMessage! = ___asyncRequest.responseMessage
		___result = ___localMessage.readBoolean(withName: "Result")
		UserID = ___localMessage.readInt32(withName: "UserID")
		ErrorMessage = ___localMessage.readUtf8String(withName: "ErrorMessage")
		objc_sync_enter(self.___message)
		self.___message.clientID = ___localMessage.clientID
		objc_sync_exit(self.___message)
		return ___result
	}

do you get the BinMessage: Invalid string length read from stream. on the server (ie reading the incoming message — which would propagate back to the client, but prefixed with “An exception occurred on the server:”) or on the client (ie reading the response message)?

Do you use CodeFirst or a RODL, server side? if the latter, can you send me the _Invk file for this service, as well, so I can compare that?

Also, can you give me the call stack for the exception? that might help narrow this down, as well…

Not reported to be a server exception.

Stacktrace:

2018-03-05 08:51:53.509105+0000 Asset Inventory[1445:44762] *** Terminating app due to uncaught exception ‘ROException’, reason: ‘BinMessage: Invalid string length read from stream.’
*** First throw call stack:
(
0 CoreFoundation 0x000000010cd9512b __exceptionPreprocess + 171
1 libobjc.A.dylib 0x00000001090cef41 objc_exception_throw + 48
2 RemObjectsSDK 0x00000001089fe990 +[ROBinHelpers unexpectedBinaryLength] + 0
3 RemObjectsSDK 0x0000000108a24ed9 -[ROBinReaderWriter readUtf8String:] + 137
4 RemObjectsSDK 0x00000001089fde21 -[ROBinMessage readUtf8StringWithName:] + 65
5 Asset Inventory 0x00000001086b9d58 _T015Asset_Inventory30DataProviderService_AsyncProxyC8endLoginSbSQySo14ROAsyncRequestCG_s5Int32VzSQySSGztF + 1032
6 Asset Inventory 0x000000010869f272 _T015Asset_Inventory18MainViewControllerC11buttonClickySo8UIButtonCF + 466
7 Asset Inventory 0x000000010869f3dc _T015Asset_Inventory18MainViewControllerC11buttonClickySo8UIButtonCFTo + 60
8 UIKit 0x0000000109eb9972 -[UIApplication sendAction:to:from:forEvent:] + 83
9 UIKit 0x000000010a038c3c -[UIControl sendAction:to:forEvent:] + 67
10 UIKit 0x000000010a038f59 -[UIControl _sendActionsForEvents:withEvent:] + 450
11 UIKit 0x000000010a037e86 -[UIControl touchesEnded:withEvent:] + 618
12 UIKit 0x0000000109f2f807 -[UIWindow _sendTouchesForEvent:] + 2807
13 UIKit 0x0000000109f30f2a -[UIWindow sendEvent:] + 4124
14 UIKit 0x0000000109ed4365 -[UIApplication sendEvent:] + 352
15 UIKit 0x000000010a820a1d __dispatchPreprocessedEventFromEventQueue + 2809
16 UIKit 0x000000010a823672 __handleEventQueueInternal + 5957
17 CoreFoundation 0x000000010cd38101 CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION + 17
18 CoreFoundation 0x000000010cdd7f71 __CFRunLoopDoSource0 + 81
19 CoreFoundation 0x000000010cd1ca19 __CFRunLoopDoSources0 + 185
20 CoreFoundation 0x000000010cd1bfff __CFRunLoopRun + 1279
21 CoreFoundation 0x000000010cd1b889 CFRunLoopRunSpecific + 409
22 GraphicsServices 0x000000010eaa49c6 GSEventRunModal + 62
23 UIKit 0x0000000109eb85d6 UIApplicationMain + 159
24 Asset Inventory 0x00000001086cb7e7 main + 55
25 libdyld.dylib 0x000000010d8efd81 start + 1
26 ??? 0x0000000000000001 0x0 + 1
)

RODL based.

DataProviderGatewayLibrary_Invk.cs (9.9 KB)

4   RemObjectsSDK                       0x00000001089fde21 -[ROBinMessage readUtf8StringWithName:] + 65
5   Asset Inventory                     0x00000001086b9d58 _T015Asset_Inventory30DataProviderService_AsyncProxyC8endLoginSbSQySo14ROAsyncRequestCG_s5Int32VzSQySSGztF + 1032

ok, so that seems to be reading the message that fails. If you set a breakpoint on the line ErrorMessage = ___localMessage.readUtf8String(withName: "ErrorMessage"), did the userID get read correctly hand have the right value?

The invoker code looks good and matches what I’d expect:

            @__Message.WriteBoolean("Result", Result);
            @__Message.WriteInt32("UserID", UserID);
            @__Message.WriteUtf8String("ErrorMessage", ErrorMessage);

very strange.

any chance you could extract this problem into a small server + sample clients (ideally macOS) that I can run locally to investigate this further?

Neither UserID or the Result get read correctly.

iOS client is all I have at the moment and all it consists of is a button calling code as posted previously. Tricky, to supply a server (.NET) as it’s already in production with Android/Windows Mobile clients.

Do you have a simple test server/client I can try and go back to basics with?

Thanks,
Mark

I’m trying to reproduce the issue locally, now.