consuming a web service called through a DLL

  • Thread starter Thread starter Roberto Perez via .NET 247
  • Start date Start date
R

Roberto Perez via .NET 247

Hello all and thank you in advance.

We have several old applications in Cobol, Centura, etc that needs to be converted to .NET
In order to save time our plan is to create web services and call them creating DLLs using C++ to be used by the old applications.

We have the simple "HELLO WORLD" web service and the DLL in C++ calling that service. Everything looks fine, our old applications are using that DLL but still is missing something because we are reading woofy characters and not the sentence that we want.

I'll appreciate any comment or suggestion to solve this matter.

Thank you all.
 
be more specific. we've done the same thing. a native DLL built with
ATL's SOAP support that consumes web services, and allows
web-services-impaired applications to use these. could those
applications expect Unicode strings but you actually provide ANSI?
 
Hello ismailp:

What I want is to know how to read the string from the Web Service. Rigth
now we are reading the first char only and not the enire string. I'm not an
expert on C++ or VC++, I'm trying to recall C++ and studying VS. One more
time; a simple web services returning "Hello World"; a standard DLL calling
the web service. The DLL returns the first character and not the string.

Thank you for your reply.
 
You receive a unicode string.

To get ASCII string, use W2A macro. Here is how to use it.

USES_CONVERSION; // you need this to use W2A macro
CMyWebService svc; // your service.
LPTSTR lpszOutput = W2A(svc.HelloWorld());

USES_CONVERSION macro is defined in atlconv.h, if it is not already
included (I don't think so - it should already be included).

after obtaining lpszOutput, you can copy it, duplicate it, or do
whatever you want (except returning that).

Ismail Pazarbasi
 
Thank you very much Ismail, I'll try it and let you know.

But, there is something catching my attention, when we have included the web
service in our C++ program we saw that the function "HelloWorld" needs a
paramater as "BSTR* HelloWorldResult" and returns a “HRESULT†value.
Inspecting the parameter we found the “H†letter and according with the
source code the “HRESULT†notifies the status of the function. This is the
way how we are calling the function.

BSTR* myOwnHello;
int myOwnSize = (int) sizeof( BSTR* );
HRESULT myOwnResult = InitializeSOAP( NULL );
myOwnHello = (BSTR*) malloc( myOwnSize );
myOwnResult = HelloWorld( myOwnHello );
If ( FAILED( myOwnResult) )
{
return “ERROR consuming the web serviceâ€;
}
return (const char*) myOwnHello;

Reading in other places we found that the function "VectorFromBstr(...)" is
the solution but does not works too. Any way, I'll try first your solution
and let you know.

Thank you again.
 
Hello Ismail:

Thank you for all your help. It is amazing how C++ works. I'm dazed and
surprised with the solution. Simple as asways.

Thank you very much again.
 
Hello Roberto,

I have seen some problems with that code. I guess, Visual Studio
generated proxy classes for your web service. These are generated with
ATL. So, in that case, your service name, say MyService, has a class
named CMyService. I did not understand how you called that HelloWorld
function. You need to do something like following:

#include "stdafx.h" // i think you have a precompiled header
// #include <atlbase.h> // uncomment, if you don't have these files in
your precompiled header
// #include <atlconv.h>
#include "Myservice.h"

int main()
{
USES_CONVERSION;
CoInitialize(NULL);
HRESULT hr;
CMyService svc;
CComBSTR bsHello; // if you use this, it will free the memory
allocated by the service
hr = svc.HelloWorld(&bsHello);
if (hr)
{
printf("We've a problem: %08x", hr);
return 1;
}
printf(W2A(bsHello));
CoUninitialize();
}

sizeof(BSTR*) is wrong. This returns 4. However, empty BSTR's size is
at least 6 bytes. BSTR starts with a DWORD that represents the size of
the string at the beginning, which is 4 bytes. 2 bytes for each
character in the string, two bytes for terminating null characters. On
the other hand, normally malloc is not used for BSTR allocation. You
can use SysAllocString, SysAllocStringByteLen or SysAllocStringLen
functions. These functions does a similar job with malloc (use
HeapAlloc, as far as I know - like malloc), however SysXXXX functions
can construct a well-formed BSTR. Also, there is no free - that leaks.

If you use CComBSTR for BSTR, you don't need to call SysFreeString -
its destructor automatically does it. If you use BSTR, the function
that receives BSTR* allocates some memory, and you need to explicitly
call SysFreeString or you leak that.

VectorFromBstr constructs a SAFEARRAY of chars. You need to retrieve
these chars from within the SAFEARRAY, that's too much of work. ATL's
conversion macros (A2W, W2A and their cousins) use MultiByteToWideChar
and WideCharToMultibyte Windows unicode character set functions. These
are directly dealing with your case.

Please also note that the computer that you will use this DLL should
have at least Internet Explorer 6.0. Because generated proxy classes
use SAX XML Reader object that comes with IE6 (with MSXML2 actually).

Ismail Pazarbasi
 
Hello Ismail:

I’ve changed my C++ function as you suggested and words much better but I
found another problem(?).

Doing a real test accessing the database, I discovered that the max string
length is 55 (starting in 1 or 54 stating in 0), do you know the answer? Let
me tell you that I'm not passing parameters yet, the web services goes to the
database and read a specific string-column which is returned.

If you wish, reply me directly at (e-mail address removed)

Thanks.

:
 
Back
Top