Данную заметку можно рассматривать как логическое продолжение предыдущей. Лыжи таки поехали. Местами я был идиотом, местами пришлось отлаживать gSOAP 2.7.14 для того, чтобы самому найти уже известный баг (который нашли за неделю до меня). Но в итоге все заработало.
Довольно своеобразная штука этот gSOAP. С одной стороны, очень удобно: берешь WSDL, натравливаешь на него wsdl2h, затем soapcpp2 и вуаля – в твоем распоряжении набор классов для обращения к удаленной стороне (ну или для реализации собственного сервиса).
Но с другой стороны… Видно, что gSOAP вырос из C-шной реализации. И уши этого наследия торчат из всех щелей. Взять, например, управление памятью. gSOAP хранит указатели на все динамически созданные в процессе десериализации SOAP-запроса объекты. И, если пользователь не взял их под собственную ответственность, автоматически уничтожает их. Но все это хорошо только для ответов сервера (если говорить о клиенте). А ведь запрос к серверу так же нужно подготовить. И вот тут-то начинается форменное корявство. Например, gSOAP генерирует структуры типа вот такой:
class SOAP_CMAC PPGw__Sms : public PPGw__Request
{
public:
int dataCodingScheme;
std::string *fromNumber;
xsd__base64Binary *header;
PPGw__PremiumInfo *premiumInfo;
std::string *protocolIdentifier;
std::string *reportLevel;
std::string *toNumber;
LONG64 validityPeriod;
public:
...
PPGw__Sms() :
dataCodingScheme(0),
fromNumber(NULL),
header(NULL),
premiumInfo(NULL),
protocolIdentifier(NULL),
reportLevel(NULL),
toNumber(NULL),
validityPeriod(0) { this->soap_default(NULL); }
virtual ~PPGw__Sms() { }
};
Можно видеть, что конструктор инициализирует элементы нулями, а деструктор ничего не делает. В это и весь фокус. Либо атрибуту PPGw__Sms назначается значение, время жизни которого определяет программист. Либо же ему назначается значение, время жизни которого будет определять gSOAP. В первом случае (когда мы отвечаем за объекты) код подготовки запроса будет иметь вид:
void
do_send_sms( PPGwBindingProxy & proxy )
{
std::cout << "...sending sms..." << std::endl;
std::string baID = "***";
std::string text_sms_selector = "TextSms";
std::string text_of_message = "Just a Test!";
std::string to_number = "+420***";
std::string msg_id = "c0465d63-38f0-4f31-93b3-0dc80a063baf";
PPGw__TextSms text_sms;
text_sms.text = &text_of_message;
text_sms.dataCodingScheme = 0;
text_sms.toNumber = &to_number;
text_sms.baID = &baID;
text_sms.msgID = &msg_id;
PPGw__MessageContainer mc;
mc.selector = &text_sms_selector;
mc.textSms = &text_sms;
PPGw__send request;
request.mc = &mc;
PPGw__sendResponse response;
int error_code = proxy.send( &request, &response );
if( error_code )
...
А во втором случае (чтобы память почистил за нас gSOAP), вот такой:
void
do_send_sms( PPGwBindingProxy & proxy )
{
std::cout << "...sending sms..." << std::endl;
PPGw__TextSms * text_sms = soap_new_PPGw__TextSms( &proxy, -1 );
(text_sms->text = soap_new_std__string( &proxy, -1 ))->assign( "Just a Test!" );
text_sms->dataCodingScheme = 0;
(text_sms->toNumber = soap_new_std__string( &proxy, -1 ))->assign( "+420***" );
(text_sms->baID = soap_new_std__string( &proxy, -1 ))->assign( "***" );
(text_sms->msgID = soap_new_std__string( &proxy, -1 ))->assign(
"c0465d63-38f0-4f31-93b3-0dc80a063baf" );
PPGw__MessageContainer * mc = soap_new_PPGw__MessageContainer( &proxy, -1 );
(mc->selector = soap_new_std__string( &proxy, -1 ))->assign( "TextSMS" );
mc->textSms = text_sms;
PPGw__send * request = soap_new_PPGw__send( &proxy, -1 );
request->mc = mc;
PPGw__sendResponse response;
int error_code = proxy.send( request, &response );
if( error_code )
...
Как по мне, так и первый, так и второй варианты – это страх и ужас, особенно второй.
Видимо, это из-за того, что и сам gSOAP написан в таком же стиле. Когда я пытался найти причину ошибки, мне приходилось заглядывать в такие функции в дебрях gSOAP, в которых директивы условной компиляции были практически через строчку. Как вся эта хрень еще поддерживается и развивается авторами – фиг знает.
А кроссплатформенных альтернатив gSOAP-у под C++, в общем-то, и нет. Была какая-то реализация SOAP-а от Apache (Apache Axis C++) – но там не видно обновлений с 2005-го года. Еще у разработчиков библиотеки POCO есть какой-то собственный POCO Remoting. Но он сильно дороже gSOAP-а, не умеет (как я понимаю) транслировать WSDL в C++, да и вообще его способности поддерживать именно SOAP слегка под вопросом (поскольку там для SOAP-а есть только некий SoapLite).
В связи с этим появляется соблазн взять и склепать собственный wsdl2cpp, который бы из WSDL генерировал заточенные под POCO или Qt нормальные C++ные классы. И продавать бы такой инструмент эдак по $200 за версию + upgrade на следующую версию за $75. Ей Богу, была бы такая альтернатива gSOAP-у – выбрал бы сейчас ее не задумываясь.
14 комментариев:
И продавать бы такой инструмент эдак по $200 за версию + upgrade на следующую версию за $75
А зачем мучиться если есть агроменное семейство "Java EE технологий". Отдаженное, от разных производителей, разного уровня масштабируемости и - бесплатно?
Потому что есть случаи, как наш -- большое C++ приложение, в которое нужно встроить поддержку SOAP-а. Делать симбиоз из C++ и Java (C#, Ruby, Python) -- это не меньший геморрой, чем использовать какой-нибудь gSOAP. Тем более, что такая интеграция будет обходиться увеличением как рантайма, так и дистрибутива.
Небольшая статистика. gSOAP 2.7.14, вышедший 20 дней назад, был загружен с SF более 1500 раз. Предшествующая версия 2.7.13 -- более 13000 раз. Это, конечно, не показатели Boost-а, но для очень специфической вещи весьма не плохо. Т.е. спрос есть. И можно было бы им воспользоваться.
Мыслей опосля и был такой вариант плюс - если встравиваемому приложению нужно работать с SOAP сервисом, а сделать прокси, переводящий в более удобный формат для обработки (по аналогии Opera Mini) нет возможности.
Насчет заработка на таком ПО... я пессимист, а это субъективно :)
Насчет заработка на таком ПО... я пессимист, а это субъективно :)
В последние годы мне кажется, что зарабатывать на средствах разработки вообще очень тяжело. OpenSource здесь рулит неимоверно. Бесплатные компиляторы, бысплатные библиотеки, бесплатные IDE -- заработать здесь можно, имхо, только на чем-то очень специализированном.
OpenSource здесь рулит неимоверно. Бесплатные ...
Вот и мне так кажется ;)
В первом постинге я невнятно и скомкал два вопроса - 1. выбор технологии для решения задач (сам бооольшой скептик в отношении нахлобучивания технологий, "а поверх http наше руби приложение на расширенной нашей натив библиотекой VM будет обращаться к эрланг серверу, который дергает сервлеты на jetty а те принимают решение, писать в SQL или в Berkley DB") 2. возможность заработать на инструменте.
только на чем-то очень специализированном.
Оно и стоить тогда должно не х00 у.е.
Проблема заработать на универсальном ПО (то есть для абстрактного заказчика) - сама универсальна:
Пристанище недовольных
С деньгами в AppStore ситуация также печальна. ...
сам бооольшой скептик в отношении нахлобучивания технологий, "а поверх http наше руби приложение на расширенной нашей натив библиотекой VM будет обращаться к эрланг серверу, который дергает сервлеты на jetty а те принимают решение, писать в SQL или в Berkley DB"
С таким нахлобучиванием регулярно вылазят проблемы на каких-нибудь нестандартных ситуациях. Которые почему-то для тебя становятся штатными... Но это уже совсем офтопик :)
только на чем-то очень специализированном.
Оно и стоить тогда должно не х00 у.е.
Цифра в $200 появилась просто из-за того, что коммерческая лицензия на gSOAP стоит $195 :)
Т.е. как бы смысл был в том, чтобы продавать за те же деньги, но с более удобной ручкой :))
Re: А кроссплатформенных альтернатив gSOAP-у под C++, в общем-то, и нет. Была какая-то реализация SOAP-а от Apache (Apache Axis C++) – но там не видно обновлений с 2005-го года.
Ошибся всего одной цифрой ;)
http://ws.apache.org/axis2
2Dmitry Vyukov: а у тебя есть опыт его использования? Например, я не увидел, может ли он из WSDL заглушки клиента/сервера генерировать?
Разобрался: для генерации кода по WSDL, нужно ставить Axis2/Java -- там есть соответствующий инструмент.
Редиски. Мало того, что это чистый C, так еще и Java нужна для разработки. gSOAP круче! :)
http://www.prog.org.ru/topic_16542_0.html
"WSDL, SOAP, Web-Services + Qt (обзор, обсуждение, сбор ссылок)"
для Qt есть 2 спец-заточенных инструмента - KdSoap и FEAST. первый бесплатный для GPL проектов, второй платный совсем.
Но я склюняюсь все-же к мысли про gSoap - в принципе для работы с STL-типами в Qt есть методы конвертации, а во вторых - вроде как gSoap можно настроить на собственный набор типов/контейнеров... не разбирался пока как именно правда...
ну и у меня с gSoap втоде все начало взлетать. единственное gSoap не умеет хорошо работать с русскими буквами в именах полей... но пока это терпимо.
@Denjs:
спасибо за ссылки. Мы у себя gSOAP уже в нескольких проектах применили. Если привыкнуть, то нормально.
А с русскими буквами в WSDL-ях пока не сталкивались :)
>>А с русскими буквами в WSDL-ях пока не сталкивались :)
в вы вебсервисы от 1Це поюзайте ;)
там и имена полей русские "и вообще"))))
>вы вебсервисы от 1Це поюзайте ;)
Не-не-не! :)
Отправить комментарий