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