trying to understand gsoap - gsoap

I am creating my first web service client using gsoap. I was able to the run the calc example provided with gsoap.
Now I am trying to access String GetData() function from WCF Webservice. I did the wsdl2h and soapcpp2 steps and have generated the .h file. In xxxxproxy.h I see that the prototype of GetData is as follows
/// Web service operation 'GetData' (returns error code or SOAP_OK)
virtual int GetData(_ns1__GetData *ns1__GetData, _ns1__GetDataResponse *ns1__GetDataResponse);
Can someone tell me what should I write in my main.cpp to access GetData. I have following code in main.cpp
#include <QtCore/QCoreApplication>
#include "soapWSHttpBinding_USCOREIAquaLinkProxy.h"
#include "WSHttpBinding_USCOREIAquaLink.nsmap"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
WSHttpBinding_USCOREIAquaLinkProxy webService;
std::cout <<"Sent request"<<std::endl;
std::string result;
if(webService.GetData(?????? )==SOAP_OK)
{
std::cout << "Returned "<< ????? <<std::endl;
}
else
{
webService.soap_stream_fault(std::cerr);
}
return a.exec();
}
Thanks.

The first argument _ns1__GetData in the function GetData is the request argument, the second is the response argument. You should try following:
_ns1__GetData request;
request.???? = ???? // I don't know the WCF Webservice
_ns1__GetDataResponse response;
if(webService.GetData(&request, &response) == SOAP_OK)
{
std::cout << "Returned " << response.????;
}
I don't know the WCF Webservice. But I guess that you have to fill the request instance with some values. What makes me wonder is, that the class names _ns1__GetData and _ns1__GetDataResponse begin with an underscore. I'm using gSoap for a long time and the names were always without beginning underscore.

Related

Does 'this' pointer in bind C++ really matters?

I am trying to experiment bind in C++. Basically I have two class - Invokee. The invokee class registers a test handler that needs to be invoked upon some callbacks. The method here is -
void RegisterTestHandler(int id, TestFunction handler, std::string summary, std::string details);
Similarly, I have another method that actually invokes what has been registered -
void callHandler(int id);
Another class Test which has a function that needs to be invoked on callHandler.
unsigned int globalReset(int val);
In the main function, I am doing the nullptr for the second parameter in the bind. However, it still works and I don't get any crashes. Is it something working because of the compiler optimisation or undefined behaviour or it is something to do with bind concept.
Here is the entire experimental code.
// main.cpp
#include <iostream>
#include "test.h"
#include "invokee.h"
#include <memory>
#include <functional>
// beautify using clang-format in Vscode.
int main(int argc, char **argv)
{
auto *invokeTest = new Invokee();
Test *test = new Test();
std::string summary = "global reset summary";
std::string details = "global reset details";
//Basically there are two object from different class - InvokeTest --> does the registration of the handler.
// Now the InvokeTest has to call the member function of class object - Test.
// ?? How it can do - it can do using bind - basically, the this pointer of Test class is available to invokeTest
// therefore invokeTest can simply invoke the member function of test object.
// until the test point is valid, it can use it to invoke the method of it ?? --> Is it really correct?
delete(test); //experiment deleted the test pointer.
test= nullptr; // explicity set to nullptr
// still it works?? how come ??
invokeTest->RegisterTestHandler(1, std::bind(&Test::globalReset, test, std::placeholders::_1), summary, details);
invokeTest->callHandler(1);
return 0;
}
Here is the invokee.cpp -
#include "invokee.h"
void Invokee::RegisterTestHandler(int id, TestFunction handler, std::string summary, std::string details)
{
this->handlers[id] = handler;
this->summary[id] = summary;
this->details[id] = details;
}
void Invokee::callHandler(int id)
{
auto handler = handlers.find(id);
if (handler != handlers.end())
{
std::cout << "Found the handler --" << std::endl;
handler->second(1);
}
}
Here is the test.cpp
#include <iostream>
#include "test.h"
unsigned int Test::globalReset(int val)
{
std::cout << "global Reset invoked" << std::endl;
return 0;
}

How to use boost.asio to exchange data back and forth btw client and server?

I implemented two simple client and server example, but it does not work. Both client and server just freeze without any messages printed.
client.cpp
int main(int argc, char * argv[])
{
std::string raw_ip = "127.0.0.1";
int port = 3333;
try
{
asio::ip::tcp::endpoint
ep(asio::ip::address::from_string(raw_ip), port);
asio::io_service ios;
asio::ip::tcp::socket sock(ios, ep.protocol());
sock.connect(ep);
asio::streambuf request;
std::ostream request_stream(&request);
request_stream << "request from clinet\n";
asio::streambuf response;
asio::read_until(sock, response, "\n");
std::istream response_stream(&response);
std::cout << response_stream.rdbuf() << std::endl;
}
catch(system::system_error &e)
{
std::cout << "Encounter error: " << e.what() << std::endl;
return e.code().value();
}
}
server.cpp
int main(int argc, char * argv[])
{
std::string raw_ip="127.0.0.1";
int port=3333;
try
{
asio::ip::tcp::endpoint ep(asio::ip::address_v4::any(),port);
asio::io_service ios;
asio::ip::tcp::acceptor acceptor(ios, ep);
acceptor.listen();
asio::ip::tcp::socket sock(ios);
acceptor.accept(sock);
asio::streambuf request;
asio::read_until(sock, request, "\n");
std::istream request_stream(&request);
std::cout << request_stream.rdbuf() << std::endl;
asio::streambuf response;
std::ostream response_stream(&response);
response_stream << "response from server\n";
}
catch(system::system_error &e)
{
std::cout << e.what() << std::endl;
return -1;
}
return 0;
}
Also I am wondering the best way to transfer a large amount of data to/from socket, how do we tell socket that I am done writing data to socket? And how do we know that we have read the last byte of data from socket? Thanks.
You need to call the blocking function 'ios.run()in both the client and server to animateboost::io_service`. In any case, I don't think your app will produce anything usable as is. You should try and use one of the asio examples as a starting point.
The TCP blocking echo client/server example should be a good starting point for what you want to do.
http://www.boost.org/doc/libs/1_64_0/doc/html/boost_asio/example/cpp11/echo/blocking_tcp_echo_client.cpp
http://www.boost.org/doc/libs/1_64_0/doc/html/boost_asio/example/cpp11/echo/blocking_tcp_echo_server.cpp
On a TCP connection, you can use a single asio buffer to ensure all of the data is sent. But you should send a message beforehand to the client so it knows how much data it should expect to receive.

LoadLibrary("bthprops.dll") fails, file not found

The Microsoft documentation for Bluetooth APIs such as BluetoothGetDeviceInfo provide instructions for calling these functions using either static or dynamic imports.
The static import, linking with bthprops.lib, works fine.
#include <windows.h>
#include <BluetoothAPIs.h>
#include <iostream>
int main(int argc, char** argv)
{
BLUETOOTH_DEVICE_INFO binfo = {};
binfo.dwSize = sizeof binfo;
binfo.Address.ullLong = 0xBAADDEADF00Dull;
auto result = ::BluetoothGetDeviceInfo(nullptr, &binfo);
std::wcout << L"BluetoothGetDeviceInfo returned " << result
<< L"\nand the name is \"" << binfo.szName << "\"\n";
return 0;
}
But this isn't ideal in ultra-portable code, because the documentation says they are not supported prior to Windows XP SP2. So one should use dynamic linking and recover from missing functions. However, dynamic loading bthprops.dll as instructed by the MSDN docs fails:
decltype(::BluetoothGetDeviceInfo)* pfnBluetoothGetDeviceInfo;
bool LoadBthprops( void )
{
auto dll = ::LoadLibraryW(L"bthprops.dll");
if (!dll) return false;
pfnBluetoothGetDeviceInfo = reinterpret_cast<decltype(pfnBluetoothGetDeviceInfo)>(::GetProcAddress(dll, "BluetoothGetDeviceInfo"));
return pfnBluetoothGetDeviceInfo != nullptr;
}
How should one dynamically link to these functions?
Apparently this fact is pretty well known to Google but not to MSDN. If you want to dynamically load these functions, use LoadLibrary("bthprops.cpl") which is the correct DLL name, contrary to the nice table in the function documentation.
This works:
decltype(::BluetoothGetDeviceInfo)* pfnBluetoothGetDeviceInfo;
bool LoadBthprops( void )
{
auto dll = ::LoadLibraryW(L"bthprops.cpl");
if (!dll) return false;
pfnBluetoothGetDeviceInfo = reinterpret_cast<decltype(pfnBluetoothGetDeviceInfo)>(::GetProcAddress(dll, "BluetoothGetDeviceInfo"));
return pfnBluetoothGetDeviceInfo != nullptr;
}

Microsoft TSF - Using ITfThreadMgr::GetFocus like IUIAutomation::GetFocusedElement

When I try to attach to Microsoft Text Services Framework (TSF) outside the context of a text service, I can't retrieve the information I need to interact with the active application's text.
#include <SDKDDKVer.h>
#include <stdio.h>
#include <tchar.h>
#include <msctf.h>
#include <atlbase.h>
#include <iostream>
// Macro throws a descriptive WCHAR* exception if(FAILED(hr))
#define OK(hrExpr) do{std::cout<<"IN: "<<#hrExpr<<std::endl; HRESULT returnCode = hrExpr; if( FAILED(returnCode) ){std::cout<<std::endl<<"ERROR! "<<#hrExpr<<" #"<<__FILE__<<":"<<__LINE__<<" returned "<<returnCode<<std::endl; throw L#hrExpr; }else{std::cout << "OK: " << #hrExpr << std::endl;}}while(0)
int _tmain(int argc, _TCHAR* argv[])
{
::CoInitialize(0);
ITfThreadMgr* pThreadMgr = NULL;
TfClientId clientId = NULL;
ITfDocumentMgr* docMgr = NULL;
ITfContext* pContext = NULL;
try
{
std::cout << "Use the next 5 seconds to switch to a TSF-enabled application and make a text selection." << std::endl;
Sleep(5000);
OK( CoCreateInstance( CLSID_TF_ThreadMgr,
NULL,
CLSCTX_INPROC_SERVER,
IID_ITfThreadMgr,
(void**)&pThreadMgr) );
OK( pThreadMgr->Activate(&clientId) );
OK( pThreadMgr->GetFocus(&docMgr) );
if (docMgr == NULL)
{
throw L"NULL document manager";
}
OK( docMgr->GetTop(&pContext) );
// TODO: use ITfContext to get selection or make document edits
}
catch(LPCSTR msg)
{
std::wcout << L"Exception: " << msg << std::endl;
}
catch(LPCWSTR msg)
{
std::wcout << L"Exception: " << msg << std::endl;
}
if (pContext)
pContext->Release();
if (docMgr)
docMgr->Release();
::CoUninitialize();
return 0;
}
I am using WordPad on Windows 7 as my target test application, and I make sure to have focus on WordPad by the time the TSF methods execute.
The program gets as far as trying to get the currently focused ITfDocumentMgr (ITfThreadMgr::GetFocus), but the returned document manager is NULL. According to the API documentation this means there is no currently focused ITfDocumentMgr, however:
If I take a completely different approach: register a custom text service and receive a ITfThreadMgr reference through ITfTextInputProcessor::Activate, I am able to retrieve the focused ITfDocumentMgr for WordPad via ITfThreadMgr::GetFocus. However for various reasons I would prefer not to install a custom inproc text service.
Is there any way to hook into the TSF API across process boundaries, as is possible with AutomationElement.FocusedElement, IUIAutomation::GetFocusedElement or AccessibleObjectFromWindow?
Text Services Framework doesn't work cross-process. There's neither proxies nor stubs available. Sorry.
Incidentally, your code is trying to get the focused doc manager for your process. You create the ITfThreadMgr using CLSCTX_INPROC_SERVER, which starts the thread manager in your process, not in the target.

Boost io_service.accept : Get URI called

I would like to get the URI called with boost.
If http://localhost:8080/users/4 is called, I want to know the URI or just /users/4
#include <boost/bind.hpp>
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
int main()
{
boost::asio::io_service io;
tcp::acceptor acceptor(io, tcp::endpoint(tcp::v4(), 8080));
tcp::socket socket(io);
acceptor.accept(socket);
// Do stuff to get URI
// ...
if (uri == "http://localhost:8080/users/4") {
std::cout << "User 4 uri called" << std::endl;
}
return 0;
}
Look to the ASIO's http server example. The connection::handle_read method parses a request, using the request_parser class instance, as result, an instance of the request structure contains an URI which is required.

Resources