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 и соответствующий тип значения param, передаваемый по значению, не совпадают в какой-то момент)

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

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

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 реализует все унаследованные абстрактные методы и свойства.

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

int port = 0;
IiopChannel chan = new IiopChannel(port);
ChannelServices.RegisterChannel(chan);
Другие вопросы по тегам