.netpythoncorbaiiop

CORBA IIOPNet and OmniORBpy, remote method call with valuetype param issue


My scope: I'm trying to create a CORBA solution for two apps one at .NET side (server) and the other on python (client). I'm using IIOPNet for server and IDLs generation and OmniORBpy for Stubs generations and client calls. In general is working for simple calls like the typical example: Adder. But when a i try to call a method with a custom class it doesn't work.

I have this class on server side(my Remove Object) to be called from the client :

public class MyRemoteObject : MarshalByRefObject
{
    public override object InitializeLifetimeService()
    {
        return null;
    }

    public bool DoSomething(InterfaceRequest requestData)
    {
        return true;
    }

}

The input param class type is declared like this on server side (quite simple):

[Serializable]    
public class InterfaceRequest
{
    public int SiteId;
    public int UserId;
}

I generate my IDLs using CLSIDLGenerator and later my python stubs like "omniidl -bpython -CPython ...", until here everything is OK.

So i start the server (VS debug environment) and now on my client code i resolve the service name, i narrow my remote object successfully and i create my request object but when i try to do this:

request = InterfaceRequest()
request.SiteId = 1
request.UserId = 3

result = remoteObj.DoSomething(request) 

Python blows up with no warning, no exception, any message of any kind, (i updated trace label on my omniORB config file to the highest [40] but nothing is getting traced), it simply crashes, i have tried a lot of stuff and i get always same result. The problem is related to the param of course (i guess).

I'm running the client side like this: python client.py -ORBInitRef NameService=corbaname::localhost:8087

(My last approach: python object reference architecture and conforming value type param passed by value are not matching at some point)

Tech details: NET 4.0, IIOPNet (last), Python 2.6, omniORB-4.1.5, omniORBpy-3.5.

Every help is appreciated, i'm little stuck with this, Thanks.


Yes the IDL generated for MyRemoteObject is this one: .....

module module1 {
module module2 {
module module3 {
module module4 {

interface MyRemoteObject {

boolean TestConnection(in double value) 
raises (::Ch::Elca::Iiop::GenericUserException);

bool DoSomenthing(in ::module1::module2::module3::InterfaceRequest requestData) 
raises (::Ch::Elca::Iiop::GenericUserException);
};

.....

But now that you mentioned this, i just noticed that on that very same file (myRemoteObject.idl) i have a structure representing the InterfaceRequest type but empty like this:

module module1 {
module module2 {
module module3 {

valuetype InterfaceRequest;

};
};
};

And of course i generate that IDL somewhere else with the right content:

valuetype InterfaceRequest {
public long SiteId;
public long UserId;
};

Weird, maybe is the order in which i'm generating this stuff, is that important?, obviously there is something wrong here right?

Finally my python stubs for these couple of classes (remote and parameter type) looks like this:

class _objref_MyRemoteObject (CORBA.Object):
    _NP_RepositoryId = MyRemoteObject._NP_RepositoryId

    def __init__(self):
        CORBA.Object.__init__(self)

    def TestConnection(self, *args):
        return _omnipy.invoke(self, "TestConnection", _0_module1.module2.module3.module4.MyRemoteObject._d_TestConnection, args)

    def DoSomething(self, *args):
        return _omnipy.invoke(self, "DoSomething", _0_module1.module2.module3.module4.MyRemoteObject._d_DoSomething, args)

    __methods__ = ["TestConnection", "DoSomething"] + CORBA.Object.__methods__

And the InterfaceRequest:

class InterfaceRequest (_0_CORBA.ValueBase):
    _NP_RepositoryId = "IDL:module1/module2/module3/InterfaceRequest:1.0"

    def __init__(self, *args, **kwargs):
        if args:
            if len(args) != 2:
                raise TypeError("InterfaceRequest() takes 2 arguments "
                                "(%d given)" % len(args))
            self.SiteId = args[0]
            self.UserId = args[1]
        if kwargs:
            self.__dict__.update(kwargs)

So even if the IDLs are not quite right (just guessing) at the end the python stubs are getting generated with the right content and right paths.

Thanks for the help (i have changed real names, hope id doesn't matter) and sorry about so large post.


Solution

  • I think that you forgot to add the interface stub, generated by IDLCompiler.

    public class MyRemoteObject : MarshalByRefObject, module1.module2.module3.MyRemoteObject
    {
        public override object InitializeLifetimeService()
        {
            return null;
        }
    
        public bool DoSomething(InterfaceRequest requestData)
        {
            return true;
        }    
    }
    

    You need to implement the valuetype in C# using these rules bellow: [It's not your error now, but you gonna get this error soon or later].

    Just remembering, you need to open an IIOPServerChannel doing:

    int port = 0;
    IiopChannel chan = new IiopChannel(port);
    ChannelServices.RegisterChannel(chan);