ROServiceImporter and Objective C

Hello,

I was able to build a very simple server using Delphi and FMX that would run on Mac OS X, after that I used the ROServiceImporter to import Objective C files for the native Mac OS X client, the server is built using code first, however, I spent too much time altering the code generated for the AccessServer class to make it work and make Xcode happy!

Can you please have a look and let me know if the generated code is correct, for the header for example, your generated code is:

#import <Foundation/Foundation.h>
#import <RemObjectsSDK/RemObjectsSDK.h>
@class ServerAccess;
@interface ServerAccess ROClientChannelDelegate
{
	ServerAccess *_sharedInstance;
	NSURL *__p_serverURL;
}
@property (nonatomic, strong) ServerAccess *sharedInstance;
@property (nonatomic, strong, readonly) NSURL *serverURL;
@property (nonatomic, strong) Demo9Service_AsyncProxy *demo9Service;
@end

I modified it to be able to create an instance of this class:
#import <Foundation/Foundation.h>
#import <RemObjectsSDK/RemObjectsSDK.h>
import “DemoSDK9_Intf.h” // No import!!!

//@class ServerAccess;
@interface ServerAccess : NSObject<ROClientChannelDelegate>
{
	ServerAccess *_sharedInstance;
	NSURL *__p_serverURL;
}
+ (ServerAccess *)createServerAccess;
@property (nonatomic, strong) ServerAccess *sharedInstance;
@property (nonatomic, strong) NSURL *serverURL; // Changed it to be able to set it up!!!
@property (nonatomic, strong) Demo9Service_Proxy *demo9Service;
@end

The implementation file generated by the import utility is as follows:

@implementation ServerAccess

static __strong ServerAccess *_sharedInstance;

+ (ServerAccess *)sharedInstance
{
	if (self->_sharedInstance == nil)
		self->_sharedInstance = [[ServerAccess alloc] init];
	return self->_sharedInstance;
}

@synthesize serverURL = __p_serverURL;

- (Demo9Service_AsyncProxy *)demo9Service
{
	id service = [[RORemoteService alloc] inittargetURL:self.serverURL serviceName:@"Demo9Service"];
	service.channel.delegate = self;
	return [[Demo9Service_AsyncProxy alloc] initservice:service];
}

@end

Modified to work as follows:

#import "DemoSDK9_ServerAccess.h"

@implementation ServerAccess

static __strong ServerAccess *_sharedInstance;

+ (ServerAccess *)createServerAccess
{
	if (_sharedInstance == nil)
		_sharedInstance = [[ServerAccess alloc] init];
	return _sharedInstance;
}

@synthesize serverURL = __p_serverURL;

- (Demo9Service_Proxy *)demo9Service
{
	RORemoteService *service = [[RORemoteService alloc] initWithTargetURL:self.serverURL serviceName:@"Demo9Service"];
	service.channel.delegate = self;
    return [[Demo9Service_Proxy alloc] initWithService:service];
}

@end

The code looks good, but i’m not a compiler ;). What does it fail on/what is the problem?

:slight_smile:

  • Error in the generated ServerAccess not to inherit from a known class
  • No import statement for the server interfaces
  • Usage of “->” operator
  • Referencing Self in a static method!!!

Regards,
Nader

The bright side:
After fixing the generated code, I got what I want, a FireMoney server on Mac and an Objective C client :slight_smile:

curious. can you send me your RODL?

I didn’t use RODL, I just started a fire monkey project, then added a module for remoting SDK, uncommented the NewMethod and modified it to return a Unicodestring. In the main fire monkey form I used a Indy http server and a bin message exactly similar to “First (code first)” demo plumbing.

I believe i have all the ObjC codegen issues fixed. How does the attached ROServiceImporter work for you?

ROServiceImporter.app.zip (3.4 MB)

1 Like

Thanks Marc, yes it did.

1 Like

Another issue :slight_smile:

I defined in my service class (in Delphi) a “Single” typed parameters, but the importer service didn’t recognize them in the generated code, the generated Objective C import is “Single” too:
- (void)aMethod:(int32)Index :(Single *)A :(Single *)B :(Single *)C :(Single *)D;
As you can see, it considered the passed parameters reference types “*”, this is in the imported interface header, in the implementation file, write nulls and reference parameter types needs to be fixed too:

- (void)aMethod:(int32)Index :(Single *)A :(Single *)B :(Single *)C :(Single *)D
{
	ROMessage *__localMessage = ((ROMessage *)([self.__message copy]));
	[__localMessage initializeAsRequestMessage:self.__clientChannel libraryName:@"DemoService" interfaceName:[self __getActiveInterfaceName] messageName:@"aMethod"];
	[__localMessage writeInt32:Index withName:@"Index"];
	[__localMessage write(null):A withName:@"A"];
	[__localMessage write(null):B withName:@"B"];
	[__localMessage write(null):C withName:@"C"];
	[__localMessage write(null):D withName:@"D"];
	[__localMessage finalizeMessage];
	[self.__clientChannel dispatch:__localMessage];
	objc_sync_enter(self.__message);
	self.__message.clientID = __localMessage.clientID;
	objc_sync_exit(self.__message);
}

Thanx, I’ll have a look tomorrow.

No worries Marc, I think I should be using Double data type :sweat:

Probably. But it should still not fail like that. I’ll check and fix. Sorry for not getting to it sooner, I’ll definitely check Monday morning.

Thanks, logged as bugs://75216

Sorry for the delay. Indeed, ROSDK does not support singles on the wire. This sound like a big in RO/Delphi that to exposes “Single” as name in the RODL. I’ll (a) log an issue to get that fixed, and (b) improve CodeGen to handle that better and n to emit “(null)”. i assume this tis Delphi/CodeFirst, right?

CodeGen is fixed, will now emit

[__localMessage writeUnknownType:foo withName:@"foo"];

for unknown types.

Thanks, how to get the update please?
Regards

The codegen fix will be in the next beta; the actual fix Delphi side probably too (but thats just logged, not done yet). That said, your fix is to just use Double instead of Single, which IS the proper solution.

Suggestion: building components that utilize osx distributed objects (the builtin osx ports API)

bugs://75216 got closed with status fixed.

bugs://75231 got closed with status nochangereq.