CORBA IIOPNet и OmniORBpy, удаленный вызов метода с проблемой параметра valuetype

Моя область: я пытаюсь создать решение 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;
}

Я генерирую свои IDL, используя CLSIDLGenerator, а затем мои заглушки Python, такие как «omniidl -bpython -CPython ...», пока здесь все не будет в порядке.

Итак, я запускаю сервер (среда отладки 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.

Каждая помощь приветствуется, я немного застрял с этим, спасибо.


Да, IDL, сгенерированный для MyRemoteObject, таков: .....

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 генерируются с правильным содержимым и правильными путями.

Спасибо за помощь (я изменил настоящие имена, надеюсь, идентификатор не имеет значения) и извините за такой большой пост.


person michel    schedule 30.08.2011    source источник
comment
Есть ли «интерфейс MyRemoteObject» в IDL? Вам необходимо реализовать интерфейс IDL, например: открытый класс MyRemoteObject : MarshalByRefObject, moduleIDL.module2.MyRemoteObject.   -  person Makah    schedule 31.08.2011
comment
Я обновил сообщение сгенерированными IDL и заглушками. Спасибо, я работаю с Windows 7 64 бит, на всякий случай это может быть проблемой (но я сомневаюсь, потому что все остальное работает, кроме этого типа вызовов).   -  person michel    schedule 31.08.2011


Ответы (1)


Я думаю, что вы забыли добавить заглушку интерфейса, сгенерированную IDLCompiler.

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

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

Вам нужно реализовать тип значения в C#, используя следующие правила: [Сейчас это не ваша ошибка, но рано или поздно вы получите эту ошибку].

  • вы реализовали класс XYZImpl, где XYZ — это имя типа значения
  • XYZImpl наследуется от абстрактного класса XYZ (этот класс генерируется IDLToCLSgenerator)
  • XYZImpl находится в том же пространстве имен, что и XYZ.
  • XYZImpl сериализуем
  • XYZImpl имеет публичный конструктор без параметров.
  • XYZImpl не является абстрактным
  • XYZImpl реализует все унаследованные абстрактные методы и свойства Link

Просто вспомните, что вам нужно открыть IIOPServerChannel, выполнив:

int port = 0;
IiopChannel chan = new IiopChannel(port);
ChannelServices.RegisterChannel(chan);
person Makah    schedule 31.08.2011
comment
Я действительно не понимаю, почему я должен наследовать обратно от интерфейсов, которые я сгенерировал из своих классов в первую очередь, мне здесь не хватает части рабочего процесса, в любом случае я создал пустой интерфейс для своего класса InterfaceRequest, который теперь называется InterfaceRequestImpl в NET сторону вручную и ЭТО РАБОТАЕТ!!!. Однако не могли бы вы объяснить мне, что вы делаете с dll, созданным IDLToCLSCompiler.exe, включаете ли вы его в качестве ссылки в свой проект и наследуете ли вы все типы от соответствующих интерфейсов? делать это вручную, пока я могу. Спасибо. - person michel; 01.09.2011
comment
Это не уродливо. IDL — это контракты, такие как API вашего сервиса. Предположим, вы не будете менять его каждый раз. - person Makah; 01.09.2011
comment
InterfaceRequest — это ваш тип значения, вам не нужно создавать гипотетический интерфейс. Просто создайте класс с именем InterfaceRequestImpl и наследуйте от абстрактного класса InterfaceRequest (из dll, сгенерированного в IDLToCLSCompiler.exe). Если бы у нас не было этих правил для монтирования типа значения, ORB не смог бы найти класс для создания экземпляра. Именно так IIOP.NET должен найти вашу реализацию. [сложно написать в двух словах :-) ] - person Makah; 01.09.2011