CORBA IIOPNet和OmniORBpy,使用valuetype param问题进行远程方法调用

时间:2011-08-30 06:00:28

标签: .net python corba iiop

我的范围:我正在尝试为两个应用程序创建一个CORBA解决方案,一个在.NET端(服务器),另一个在python(客户端)上。我正在使用IIOPNet生成服务器和IDL,使用OmniORBpy生成Stubs和客户端调用。一般来说,像典型的例子一样简单的调用:Adder。但是,当我尝试使用自定义类调用方法时,它不起作用。

我从服务器端调用此类(我的删除对象):

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

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

}

输入param类类型在服务器端声明如此(非常简单):

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

我使用CLSIDLGenerator生成我的IDL,后来我的python存根像“omniidl -bpython -CPython ...”,直到这里一切正常。

所以我启动服务器(VS调试环境),现在我的客户端代码我解析服务名称,我成功缩小我的远程对象,我创建我的请求对象,但当我尝试这样做:

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

result = remoteObj.DoSomething(request) 

Python没有警告,没有异常,任何类型的消息,(我将omniORB配置文件中的跟踪标签更新到最高[40]但没有任何内容被跟踪),它只是崩溃了,我试过了很多东西,我总是得到相同的结果。这个问题当然与param有关(我猜)。

我正在运行这样的客户端: python client.py -ORBInitRef NameService = corbaname :: localhost:8087

(我的最后一种方法:python对象引用架构和符合值的值类型param在某些时候不匹配)

技术细节: NET 4.0,IIOPNet(最后),Python 2.6,omniORB-4.1.5,omniORBpy-3.5。

感谢每一位帮助,我对此很感动,谢谢。


是的,为MyRemoteObject生成的IDL是这样的: .....

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);
};

.....

但是现在您提到了这一点,我只是注意到在同一个文件(myRemoteObject.idl)上我有一个表示InterfaceRequest类型的结构,但是像这样是空的:

module module1 {
module module2 {
module module3 {

valuetype InterfaceRequest;

};
};
};

当然,我使用正确的内容在其他地方生成IDL:

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

很奇怪,也许是我生成这些东西的顺序,这很重要吗?显然这里有什么不对吗?

最后,我对这几个类(远程和参数类型)的python存根看起来像这样:

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__

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)

因此,即使IDL在结尾处不完全正确(只是猜测),也会使用正确的内容和正确的路径生成python存根。

感谢您的帮助(我已经更改了真实姓名,希望ID无关紧要)并对这么大的帖子感到抱歉。

1 个答案:

答案 0 :(得分:0)

我认为您忘记添加由IDLCompiler生成的接口存根。

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

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

您需要使用以下规则在C#中实现valuetype: [现在不是你的错误,但你很快就会得到这个错误]。

  • 您实现了一个类XYZImpl,其中XYZ是valuetype的类型名称
  • XYZImpl继承自抽象类XYZ(此类由IDLToCLSgenerator生成)
  • XYZImpl与XYZ
  • 位于同一名称空间中
  • XYZImpl可序列化
  • XYZImpl有一个无参数的公共构造函数
  • XYZImpl不是抽象的
  • XYZImpl实现所有继承的抽象方法和属性 Link

记住,你需要打开一个IIOPServerChannel:

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