(English) Unmanaged C++ client for WCF service.

Этот пост пока не переведен на русский язык. Читать на English

Оставите комментарий ?

50 Комментарии。

  1. WCF services development made easy in VS 2008? at blinnov’s blog - pingback on Январь 22, 2008 в 3:54 пп
  2. Great article!!!

    I was wondering what are the changes needed to be done on order to have gSoap connect via wsHttpbinding binding? I have tried to modify the example described above with no luck….

    Any help will be appreciated (I need to use wsHttpbinding due to authentication, security etc)

    Thanks

  3. Hi,

    Thanks!

    I’m afraid no gSoap client can work with wsHttpBinding. At least I did not succeed with it too :(
    It definitely has something to do with authentication method in wsHttpBinding. gSoap does not seem to support it so far.

  4. Congratulation for the article!

    Can I use gSoap with NetTCPBingind?

  5. Thanks hunsoul,

    Didn’t try that but I suspect it won’t work as gSoap is supposed to work over HTTP, while NetTCPBinding is using (presumably) binary protocol.

  6. Im a beginner programmer. I have only visual studio 2005 and dot net frame work installed on my machine. I have installed the gsoap .rar file. How do i go about the installation of gsoap?

  7. Hi. I tried following your steps and added all the files into my project. However I get the following linker error:

    Linking…
    stdsoap2.obj : error LNK2001: unresolved external symbol _namespaces
    Debug/TestingWebService.exe : fatal error LNK1120: 1 unresolved externals
    Error executing link.exe.

    Can you help me with this?

  8. Hi,

    That indicates that you most likely did not include stdsoap2.cpp into your project.

  9. I tried this once again.

    Added the following generated files to my c++ project

    soapBasicHttpBinding_USCOREIPortfoliosProxy.cpp
    soapBasicHttpBinding_USCOREIPortfoliosProxy.h

    soapC.cpp
    soapH.h

    stdsoap2.cpp
    stdsoap2.h

    soapStub.h

    I also included

    BasicHttpBinding_USCOREIPortfolios.nsmap (tried not including it also)

    When I compile, I get the following linker error:

    Linking…
    stdsoap2.obj : error LNK2001: unresolved external symbol _namespaces
    Debug/TestingWebService.exe : fatal error LNK1120: 1 unresolved externals
    Error executing link.exe.

    I tried creating a c++ project on VC 6.0 as well as VS 2008 but same issues.

    Any help?

  10. Which gSOAP version are you using?

  11. The version I have is gSoap 2.7. Should I be using another version?

  12. Sorry. I actually downloaded gsoap_2.7.12.tar

  13. Hi. Im now able to compile my project successfully.

    however when i call the wcf service method, I get a HTTP 415 error — Unsupported Media type.

    Do you know why I could be getting this error?

    the code snippet is:

    _ns3__ShowPortfolios param;
    _ns3__ShowPortfoliosResponse response;

    int in = 1;
    param.userKey = ∈

    BasicHttpBinding_USCOREIPortfoliosProxy myProxy;
    if(myProxy.ShowPortfolios(&param,&response) == SOAP_OK)
    {
    cout << «here»;
    }

  14. There are good chances your service is not configured to accept Basic HTTP binding. At least when I was playing with it I was getting similar errors.

  15. Hi there once again. I have been working with gSoap for a week now. I am facing an issue in getting data from WCF. There is a service which serializes certain file data into a Stream and returns that to the client.

    The service has certain message header attributes and a message body attribute for the file stream.

    The problem I’m facing is, I’m able to receive the message headers, but when I watch the output variable for the stream data, it is empty.

    Another thing I noticed is that soap->buf does contain some of the data (which means the service is returning some data).

    The proxy classes are so confusing that I can’t figure out where the issue is.

    Please let me know if you can help.

    Thanks,
    Vishal

  16. I can only think that WCF service serializes that stream as a compound data type, which cannot be serialized by gSOAP by itself. Take a look at wsdl to see how stream is send.

  17. You’re right. WCF is serializing the data as a compound data type.

    Here is the class which is used:

    [Serializable]
    class SerializeFileInfo
    {
    public SerializeFileInfo(string name, byte[] buffer)
    {
    fileName = name;
    fileBuffer = buffer;
    }

    string fileName;
    public string FileName
    {
    get
    {
    return fileName;
    }
    }

    byte[] fileBuffer;
    public byte[] FileBuffer
    {
    get
    {
    return fileBuffer;
    }
    }
    }

    This gets serialized into a SYstem.IO.Stream using the BinaryFormatter.

    The client side proxy class for the stream is:

    class SOAP_CMAC xsd__base64Binary
    {
    public:
    unsigned char *__ptr;
    int __size;
    char *id; /* optional element of type xsd:string */
    char *type; /* optional element of type xsd:string */
    char *options; /* optional element of type xsd:string */
    struct soap *soap; /* transient */
    public:
    virtual int soap_type() const { return 15; } /* = unique id SOAP_TYPE_xsd__base64Binary */
    virtual void soap_default(struct soap*);
    virtual void soap_serialize(struct soap*) const;
    virtual int soap_put(struct soap*, const char*, const char*) const;
    virtual int soap_out(struct soap*, const char*, int, const char*) const;
    virtual void *soap_get(struct soap*, const char*, const char*);
    virtual void *soap_in(struct soap*, const char*, const char*);
    xsd__base64Binary() : __ptr(NULL), __size(0), id(NULL), type(NULL), options(NULL), soap(NULL) { }
    virtual ~xsd__base64Binary() { }
    };

    However, all its members are empty.

  18. Here is the message body definition on WCF side:

    [MessageBodyMember(Namespace = Namespaces.DataContractSchemasNamespace, Name = "FileByteStream",Order=1)]
    public System.IO.Stream FileByteStream { get; set; }

    However, when I browse the WSDL, it just shows:

    I cannot see a mention of FileByteStream anywhere in the WSDL.

    Just to mention this service is working fine when I call it through an ASPX page and it does download the files.

  19. Take a look at official gSoap manual, 18.5. It looks like gSOAP did not generate deserializer for your custom type by some reason.

  20. I am not surprized WSDL does not implicitly contain FileByteStream. I am almowt sure you’ll have to define your own deserializer for that structure in c++ client.

  21. I see the following code generatedby gSoap

    SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns7__StreamBody__(struct soap*, const char*, int, const ns7__StreamBody__ *, const char*);
    SOAP_FMAC3 ns7__StreamBody__ * SOAP_FMAC4 soap_get_ns7__StreamBody__(struct soap*, ns7__StreamBody__ *, const char*, const char*);
    SOAP_FMAC3 ns7__StreamBody__ * SOAP_FMAC4 soap_in_ns7__StreamBody__(struct soap*, const char*, ns7__StreamBody__ *, const char*);
    SOAP_FMAC5 ns7__StreamBody__ * SOAP_FMAC6 soap_new_ns7__StreamBody__(struct soap*, int);
    SOAP_FMAC5 void SOAP_FMAC6 soap_delete_ns7__StreamBody__(struct soap*, ns7__StreamBody__*);
    SOAP_FMAC3 ns7__StreamBody__ * SOAP_FMAC4 soap_instantiate_ns7__StreamBody__(struct soap*, int, const char*, const char*, size_t*);
    SOAP_FMAC3 void SOAP_FMAC4 soap_copy_ns7__StreamBody__(struct soap*, int, int, void*, size_t, const void*, size_t);

    These also have definition associated with them.

    I agree there might be a deserializing issue. However, I’m not sure what part of the gSoap API code needs to be changed. Is there a work around?

  22. Alternatively, do you know how I can see the SOAP return message. This will confirm whether anything is being returned in the message body?

  23. I see that the call to the method is not successful. It returns -1 error

    «myProxy.DownloadDeal(input,output)»

    Does that give us any help?

  24. According to what you said previously, there is a buffer that contains the data, but gSOAP simly failed to de-serialize the structure. It is not about changing gSOAP api methods, it is about implementing your own de-serialization function as described in the link I gave before.

  25. I think the last message I sent got skipped. I was wanting to know how can I see the SOAP response message so as to verify that the client is receiving the stream in the Body. Is there a method in gSoap API which allows me to do this?

  26. Should’nt there be a way I can atleast see the serialized data to make sure the service is doing its job?

  27. Actually, you have plenty of options to ensure service returns data.
    At first, chances are soap->buf mentioned by you is the buffer containing raw data. At second, you can get Wireshark to see what is being sent over the network (it is generally a good idea to install network sniffer once you are in network programming).

  28. gSoap doesn’t have any method for this purpose?

  29. gSoap doesn’t have any method for this purpose?

    Not sure. Take a look at its documentation, it is quite an easy to deal with.

  30. Thanks a ton. Will u be around in case I need more help and advice. Is it possible to reach u any faster through an email?

  31. No porblem at all. BTW, you have just given me an idea for the next port about gSOAP/WCF.
    With all time zones issues this blog is the most reliable way to get me :)

  32. Hi Vital,
    Is there a way I can send my log file to you? I want to discuss regarding the issue I was having with deserialization of WCF data.

    Please let me know.

    Thanks,
    Vishal

  33. Hi Vital,
    I turned the debug on and was able to see my SOAP response message. However, the body tag for the FileStream contained this:

    ***************************************************************
    below this line it looks like the binary stream data. Shouldn’t this have been enclosed in the body tag???
    ***************************************************************

    —uuid:6e5371b3-9fca-4914-be46-dba2957546c9+id=1
    Content-ID:
    Content-Transfer-Encoding: binary
    Content-Type: application/octet-stream

     ÿÿÿÿ  System.Collections.ArrayList _items_size_version         
     OMkmv.SFW.WebService.Util, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null 7Mkmv.SFW.WebService.Util.GZipCompress+SerializeFileInfo fileName
    fileBuffer  ACE05RM2.WB     ACE05RM2.WC
       ACE05RM2.WS  ø+  ƒ¸í }D scenario  *! A’j¾ýÚ4¿ß¿wJsÊý
    «»˜‚«¾ïÛ¾îû@½÷íÛ§iÛm»»Bç:©\js’²
    Ñ52 åRc2®‘T²Zl‹»ÇFj`؁YR2±x+ï¾Ïs¶ÙÛvÙaM$H$ŒKÐøf!­>ð­à¼Qᘼw‚ñ! à¼Wð¼/º
    áI É ñ>HÿÕµ²ÈÜbôtƒÁ`¯wÛÿY’×`!ˆB·[Sà#5lz
    áʧXÄ1©UhÌX!-O–PT`ÕùN‹@¸ è©{ŽŽ|ceÔ3­P‘P=>H©j; @¬•äF ò´½

  34. It looks like Im getting the serialized filestream as an attachment instead of getting it as part of the SOAP body. I don’t know how I can get that stream data.

    I tried calling my service from SoapUI test utility and it returned the filstream as an attachment in the tag:

    Can you help me understand this Vital?

    Thanks,
    Vishal

  35. Hi Vital,
    I’m still not able to figure out where this deserialization code should be called from within gSoap API. I can receive the file stream and can see the size of the file stream in the binary object on C++ client side, however, I still notice that the __ptr field is empty.

    I would really appreciate any help from you since I’ve been stuck on this issue for some while now.

    Thanks,
    Vishal

  36. Hi,

    According to what I see WCF serialized file stream data as binary and apparently used compression. I am in doubts gSoap can decode it by itself.
    Ar you sure you did not try to used base64 encoding on WCF side?

  37. Hi Vital,
    The WCF service is using BinaryFormatter to serialize the memory stream on WCF side.

    I am able to read the stream characters when I debug the c++ client. Also, __size field is getting set but __ptr field is still empty.

    I can incorporate the deserialization function, however, for that I first need to receive the serialized data which I can’t find in a variable.

    I really need to get this resolved since I feel I’m too close to the solution but really need help now and can’t find any other support from gSoap.

    Please help.

    Thanks,
    Vishal

  38. BTW, did you try to make gSoap to generate binary deserializer for you like shown here?

  39. I tried the following options for generating proxy files:

    wsdl2h -o myService.h http://localhost:2714/DealFileService.svc?wsdl

    soapcpp2 -1 -C -i -I ..\..\import -t -x myService.h

    Do I need to include -s option? also, Do I need to include typedef.dat in the .bat folder?

  40. Hi Vital,
    I still don’t have any clue on this issue. Please can you provide some more ideas.

    Thanks,
    Vishal

  41. G’day,

    I’ll try to write a simple test for it once I have a moment.

  42. Hi.
    I’m looking at setting up something similar on a GNU/Linux client in order to test that it works for our companies clients. Some may be using other clients than windows.

    Do you have any experience on this platform?
    I’m reasonably familiar with GNU/Linux as a user.
    Any help or direction in this would be helpfull.

    • Should not be a problem at all. You’ll need a gsoap (not sure about the name though) library. I bet it is already available in most Linux repositories. For instance, it is already there in Debian (here) And gcc, of course. If you have no experience writing and compiling programs Linux, you should probably start from some of make/gcc tutorials.

      I originally did it on Linux and for Linux.

  43. Sounds good vital.
    I’m using debian.
    I havn’t done any development on Linux. Only Windows so far.
    Thanks for the advice!

  44. Hi,

    I am using gSOAP 2.7.9l for generation of client side code i.e proxy ( via 2 WSDL file ) to connect to 2 different webservice in VC++ 2005 framework. soapStub and soapClient file is created. Now stdsoap2.cpp and stdsoap2.h file is common for both the stub files.

    I got the linking error :
    error LNK2001: unresolved external symbol «public: virtual void __thiscall ns1__submitMessage::soap_default(struct soap *)» (?soap_default@ns1__submitMessage@@UAEXPAUsoap@@@Z)

    Can any one advise on the same error.
    Thanks,
    Vijay

  45. Thank you very much! This info and your answers on questions in comments was very usefull to me!

  46. Hi Vital,
    I am trying to use the gsoap and following is my test client code —
    1 #include «soapUSCOREspcService_USCOREspcRequestBSProxy.h»
    2 #include «USCOREspcService_USCOREspcRequestBS.nsmap»
    3
    4 int main()
    5 {
    6 std::string sr = «2-1750638711″;
    7 USCOREspcService_USCOREspcRequestBS s;
    8 _ns1__Yahoo_USCOREspc__USCOREspcService_USCOREspcRequestBS_USCOREQueryTicket_USCOREInput *input =
    9 new _ns1__Yahoo_USCOREspc__USCOREspcService_USCOREspcRequestBS_USCOREQueryTicket_USCOREInput;
    10 _ns1__Yahoo_USCOREspc__USCOREspcService_USCOREspcRequestBS_USCOREQueryTicket_USCOREOutput *output =
    11 new _ns1__Yahoo_USCOREspc__USCOREspcService_USCOREspcRequestBS_USCOREQueryTicket_USCOREOutput;
    12 input->NamedSearchSpec = «»;
    13 input->LOVLanguageMode = «LIC»;
    14 input->ViewMode = «All»;
    15 ns2__queryType SRNumber;
    16 ns2__ServiceRequestQuery ServiceRequest;
    17 ns2__Yahoo_USCOREServiceRequest_USCOREIOQuery ns2__Yahoo_USCOREServiceRequest_USCOREIO;
    18
    19 SRNumber.__item = sr;
    20 ServiceRequest.SRNumber = &SRNumber;
    21 ns2__Yahoo_USCOREServiceRequest_USCOREIO.ServiceRequest = &ServiceRequest;
    22 input->ns2__Yahoo_USCOREServiceRequest_USCOREIO = &ns2__Yahoo_USCOREServiceRequest_USCOREIO;
    23
    24
    25 //input->ns2__Yahoo_USCOREServiceRequest_USCOREIO->ServiceRequest->SRNumber->__item = sr;
    26
    27 int err = s.__ns1__QueryTicket(input, output);
    28 if (SOAP_OK == err)
    29 {
    30 std::cout<<"Service returned\n";
    31 }
    32 else
    33 {
    34 std::cout<<"Error\n";
    35 }
    36 delete input;
    37 delete output;
    38 return 0;
    39 }

    Now, ……

  47. Hi !
    Thank you for your very interesting article.

    I made ​​a small demo project but found little problem.

    I’m very need it, hope you can help me.

    (WCF project — c #)

    public string strGetCustomerByID (int customerID)
    ————————————————— ———————————
    CallWCFDemo demo project (c + +)

    similar to you.

    and error for me:

    error LNK1120: 14 unresolved externals E: \ CURRENT_WORK \ workspace \ MY PROJECT \ DLL \ CallWCFDemo \ Debug \ CallWCFDemo.exe CallWCFDemo
    ——
    error LNK2001: unresolved external symbol «public: virtual int __ thiscall _ns1__strGetCustomerByID :: soap_out (struct soap *, char const *, int, char const *) const» (? soap_out @ _ns1__strGetCustomerByID @ @ UBEHPAUsoap @ @ PBDH1 @ Z) E: \ CURRENT_WORK \ workspace \ MY PROJECT \ DLL \ CallWCFDemo \ CallWCFDemo \ CallWCFDemo.obj CallWCFDemo

    thanks !

  48. hello vital,

    very good tutorial, but when I tried to develop a wcf client c + + I have a little problem. When I compile my project (console application) I have no error, but I just can not manage to access my service (hosted locally «http://localhost/mexservice/implRoutingService.svc»).

    I followed exactly your tutorial.
    1 — wsdl2h.exe-o myservice.h http://localhost/mexservice/implRoutingService.svc?wsdl -> ok
    2 — soapcpp2.exe -i -I [path to import] myservice.h -C -> ok

    But no results when I run my application

    I don’t understand

    best regards,

    • Hi Marius,

      The first thing I always do when facing a problem with network app is starting Wireshark and watching network traffic.
      It won’t work with local traffic, you’ll need to host your service on another machine or virtual box.

Оставить комментарий


Примечание - Вы можете использовать эти HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Трэкбэки и Пингбэки:

3 посетителей онлайн
1 гостей, 2 bots, 0 зарегистрированных
Максимум сегодня:: 17 в 01:13 am UTC
В этом месяце: 82 в 04-16-2014 04:26 am UTC
В этом году: 89 в 02-06-2014 11:41 pm UTC
За все время: 89 в 02-06-2014 11:41 pm UTC