Update Interface generating swift file

oxygene

(FireSide Experience) #1

I am trying to update the interface file in VS 2017 with a project that is a mix of Oxygene and C#. I want the interface file to be in Oxygene (the current one is) but when I update it, it automatically makes a swift file with the message

“Elements project is using mixed languages or an unknown langage. Will generate Silver (Swift) code.
Created file ZentraServerLibrary_Intf.swift”

How can I make this generate a .pas file?

Thanks!


(antonk) #2

If more than 1 language is used in an Elements project then the default CodeGen will be used (that is the Swift one). If you need some concrete codegen then you need to stick to this language in the entire project.


(FireSide Experience) #3

ok, thank Antonk


(FireSide Experience) #4

In general, would you stick to one Elements language per Elements project?


(antonk) #5

What exactly do you mean? It is up to you which language(s) to use in an Elements project.


(FireSide Experience) #6

In this project, I use oxygene and Hydrogene. I started the project with oxygene only and the interface file was in oxygene. There was an update to the RODL file so I needed to update the interface file (Hydrogene files were added) and it made the interface a Silver file. Now all my oxygen and hydrogene references to the interface are broke because to my understanding you can’t use namespaces in Silver so it can’t find them. I am probably not understanding something correctly. Any help with this would be great.

I like using mixed languages because some of the team are c# only and other are oxygene (Delphi) only so it works nice but not sure how to make the swift interface file work.

So in general I was wondering if R.O. recommends sticking to one language per project. So use oxygene for one .Net project and maybe hydrogene for another.

I hope that makes it clearer. :slight_smile:


(FireSide Experience) #7

ok I just needed to change the namespace in the projects that are in the solution. The interface is in a shared project. everything works now with the swift interface. :slight_smile:


(antonk) #8

Nope, there is no such recommendation.

Anyway, I’ll log an issue to consider adding a dropdown with preferred language for code generation to this dialog.


(RemObjects) #9

Thanks, logged as bugs://79931


(marc hoffman) #10

that’s an odd error though. that gives that? mixing languages is totally fine…


(FireSide Experience) #11

and the word language is misspelled :wink:


(FireSide Experience) #12

Another note. And I probably will try to have to build an example of this but this is in reference to a problem we were having with the service tester.

https://talk.remobjects.com/t/new-service-tester-crash-v1317/13766

I am building a “service tester” from scratch that runs automated test scripts against a RO Server. Much like Service Tester but you can schedule a bunch of tests to run and schedule them. Anyway, we had an issue with the TPerson object in Service tester (see link above). I use this same object with the new project and when I used the swift interface file I got an error when running a test concerning the TPerson object (I am assuming).

image

It logs the person in fine but raises an exception which I catch and display. If I switch back to the oxygene interface file the error goes away. The TPerson is an out parameter passed in the service method. It is supposed to return the person logged in info. Maybe using the swift interface the TPerson object isn’t handled right.

In the meantime, I switched back to the oxygene interface and updated it by copying the generated code from the Service Builder which worked fine.

The login class that is called and run looks like this.

	public class Login: RootServiceMethod
{
    private String user;
    private String password;
    private TPerson person;
    private Boolean loggedIn;

    public String User
    {
        get { return user; }
        set { user = value; }
    }

    public String Password
    {
        get { return password; }
        set { password = value; }
    }

    public TPerson Person
    {
        get { return person; }
        set { person = value; }
    }

    public Boolean LoggedIn
    {
        get { return loggedIn; }
        set { loggedIn = value; }
    }

    public void Execute(TaskItem taskItem)
    {
        try
        {
            taskItem.Log.AddText(true, "Logging in " + User + ".");

            ILoginService loginService = CoLoginService.Create(taskItem.ServerConnection.ROMessage,
                taskItem.ServerConnection.ROChannel);

            if (loginService.ZentraLogin(user, password, out person))
            {
                loggedIn = true;
                taskItem.ServerConnectionInfo.SessionID = taskItem.ServerConnection.ROMessage.ClientID.ToString();                    
            }

            taskItem.User.Name = User;
            taskItem.Log.AddText(true, "Login was successful for " + User + ".");
        }
        catch (Exception e)
        {
            taskItem.Log.AddText(true, e.Message);
            taskItem.Log.AddText(true, "Login for " + User + " failed!");
        }
    }
}

(marc hoffman) #13

Hmm, hard to diagnose from just the screenshot. Any chance I could get a runnable project so I can see the NRE in action, and debug it?


(FireSide Experience) #14

Let me see what I can put together. :slight_smile:


(antonk) #15

Could you at least print the full stacktrace for this exception?


(marc hoffman) #16

Anton, looking at the generated code, I see:

public override func ReadComplex(_ serializer: RemObjects.SDK.Serializer¡) {
        if serializer.RecordStrictOrder {
            super.ReadComplex(serializer)
            self.SessionID = serializer.ReadWideString(“SessionID”)
        } else {
            self.AccessLevel = (serializer.Read(“AccessLevel”, dynamicType(TZentraAccessLevelEnum), RemObjects.SDK.StreamingFormat.Default) as! TZentraAccessLevelEnum)
            self.CompanyCode = serializer.ReadWideString(“CompanyCode”)
            self.CompanyKey = serializer.ReadInt32(“CompanyKey”)
            self.CompanyName = serializer.ReadWideString(“CompanyName”)
            self.Key = serializer.ReadInt32(“Key”)
            self.Name = serializer.ReadWideString(“Name”)
            self.Name_ISO8859_1 = serializer.ReadWideString(“Name_ISO8859_1")
            self.Remarks = serializer.ReadWideString(“Remarks”)
            self.SessionID = serializer.ReadWideString(“SessionID”)
            self.Sign = serializer.ReadWideString(“Sign”)
            self.Status = (serializer.Read(“Status”, dynamicType(TContactStatusEnum), RemObjects.SDK.StreamingFormat.Default) as! TContactStatusEnum)
            self.Templates = (serializer.Read(“Templates”, dynamicType(TTemplateRecordKey¡[]), RemObjects.SDK.StreamingFormat.Default) as! TTemplateRecordKey¡[])
            self.TemplatesStr = serializer.ReadWideString(“TemplatesStr”)
        }
    }

vs

method ReadComplex(serializer: RemObjects.SDK.Serializer); override;
       begin
           if serializer.RecordStrictOrder then begin
               self.Key := serializer.ReadInt32(‘Key’);
               self.Sign := serializer.ReadWideString(‘Sign’);
               self.Name := serializer.ReadWideString(‘Name’);
               self.Name_ISO8859_1 := serializer.ReadWideString(‘Name_ISO8859_1’);
               self.CompanyKey := serializer.ReadInt32(‘CompanyKey’);
               self.CompanyCode := serializer.ReadWideString(‘CompanyCode’);
               self.CompanyName := serializer.ReadWideString(‘CompanyName’);
               self.AccessLevel := (serializer.Read(‘AccessLevel’, typeOf(TZentraAccessLevelEnum), RemObjects.SDK.StreamingFormat.Default) as TZentraAccessLevelEnum);
               self.Templates := (serializer.Read(‘Templates’, typeOf(array of TTemplateRecordKey), RemObjects.SDK.StreamingFormat.Default) as array of TTemplateRecordKey);
               self.TemplatesStr := serializer.ReadWideString(‘TemplatesStr’);
               self.Status := (serializer.Read(‘Status’, typeOf(TContactStatusEnum), RemObjects.SDK.StreamingFormat.Default) as TContactStatusEnum);
               self.Remarks := serializer.ReadWideString(‘Remarks’);
           end
           else begin
               self.AccessLevel := (serializer.Read(‘AccessLevel’, typeOf(TZentraAccessLevelEnum), RemObjects.SDK.StreamingFormat.Default) as TZentraAccessLevelEnum);
               self.CompanyCode := serializer.ReadWideString(‘CompanyCode’);
               self.CompanyKey := serializer.ReadInt32(‘CompanyKey’);
               self.CompanyName := serializer.ReadWideString(‘CompanyName’);
               self.Key := serializer.ReadInt32(‘Key’);
               self.Name := serializer.ReadWideString(‘Name’);
               self.Name_ISO8859_1 := serializer.ReadWideString(‘Name_ISO8859_1’);
               self.Remarks := serializer.ReadWideString(‘Remarks’);
               self.Sign := serializer.ReadWideString(‘Sign’);
               self.Status := (serializer.Read(‘Status’, typeOf(TContactStatusEnum), RemObjects.SDK.StreamingFormat.Default) as TContactStatusEnum);
               self.Templates := (serializer.Read(‘Templates’, typeOf(array of TTemplateRecordKey), RemObjects.SDK.StreamingFormat.Default) as array of TTemplateRecordKey);
               self.TemplatesStr := serializer.ReadWideString(‘TemplatesStr’);
           end;
       end;

note how most of the serializer.RecordStrictOrder case is missing, but for Swift only. weird?


(antonk) #17

The code is generated from the same CodeDom tree. Still it seems the listed ReadComplex methods are defined for different structures (note that second listing doesn’t mention the SessionID field).

The first listing seems to be fine - for structures with ancestors first data representing ancestors is read and then fields added in the structure are deserialized.


(marc hoffman) #18

Anton,

yeah, question is, why is it generated wrong for Swift? can you find out?


(RemObjects) #19

bugs://79931 got closed with status fixed.