CORBA IIOPNet 和 OmniORBpy,带有值类型参数的远程方法调用问题

Posted

技术标签:

【中文标题】CORBA IIOPNet 和 OmniORBpy,带有值类型参数的远程方法调用问题【英文标题】:CORBA IIOPNet and OmniORBpy, remote method call with valuetype param issue 【发布时间】:2011-08-30 06:00:28 【问题描述】:

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

我在服务器端有这个类(我的删除对象)要从客户端调用:

public class MyRemoteObject : MarshalByRefObject

    public override object InitializeLifetimeService()
    
        return null;
    

    public bool DoSomething(InterfaceRequest requestData)
    
        return true;
    


输入参数类类型在服务器端是这样声明的(很简单):

[Serializable]    
public class InterfaceRequest

    public int SiteId;
    public int UserId;

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

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

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

result = remoteObj.DoSomething(request) 

Python 在没有任何警告、没有例外、任何类型的消息的情况下爆炸,(我将omniORB 配置文件上的跟踪标签更新为最高 [40] 但没有任何跟踪),它只是崩溃了,我尝试了很多东西,我总是得到相同的结果。问题当然与参数有关(我猜)。

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

(我的最后一种方法:python 对象参考架构和按值传递的符合值类型参数在某些时候不匹配)

技术细节: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__

还有接口请求:

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 无关紧要)并且对于这么大的帖子感到抱歉。

【问题讨论】:

IDL 中是否有“接口 MyRemoteObject”?您需要实现 IDL 接口,例如:“public class MyRemoteObject : MarshalByRefObject, moduleIDL.module2.MyRemoteObject”。 我已经用生成的 IDL 和存根更新了帖子。谢谢,我使用的是 Windows 7 64 位,以防万一这可能是一个问题(但我对此表示怀疑,因为除了这种类型的调用外,其他一切都在工作)。 【参考方案1】:

我认为您忘记添加由 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);

【讨论】:

我真的不明白为什么我必须首先从我的类生成的接口继承回来,我在这里缺少工作流程的一部分,无论如何我创建了一个空接口我的 InterfaceRequest 类现在在 NET 端手动调用 InterfaceRequestImpl 并且它可以工作!!!。但是,您介意解释一下您如何处理由 IDLToCLSCompiler.exe 生成的 dll,您是否将其作为参考包含在您的项目中并从它们相应的接口继承所有类型?对我来说,这看起来很丑陋,我更喜欢只要我可以手动做。谢谢。 不丑。 IDLs 是一个契约,就像你的服务 API。假设您不会每次都更改它。 InterfaceRequest 是你的值类型,你不需要创建一个假设的接口。只需创建一个名为 InterfaceRequestImpl 的类,并从抽象类 InterfaceRequest 继承(来自 IDLToCLSCompiler.exe 中生成的 dll)。如果我们没有这些规则来挂载值类型,ORB 就找不到要实例化的类。这是 IIOP.NET 必须找到您的实现的方式。 [很难用几句话写出来:-)]

以上是关于CORBA IIOPNet 和 OmniORBpy,带有值类型参数的远程方法调用问题的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Windows 10 上安装omniORB 和omniORBpy?

Python:在Windows64(Windows 7)环境下安装OmniOrbpy

Corba 客户端 - Python 和 Corba 服务器 - Java

CORBA 和 MOM 集成

JMS 和 CORBA 的区别?

CORBA:尝试配置和运行 OpenORB 时出现问题