Search code examples
androidc++delphiwsdlc++builder

C++ Builder WSDL client for Android


I'm having a confusing problem. I'm trying to make a Web cleint that uses WSDL. I'm using C++ RAD Studio 10 Seattle, but the same problem occured in RAD Studio XE8(older version).

1.I create a Multi-Device Application, add one Edit component and one Button.

2.I create a WSDL Importer by changing the location of the WSDL file to : "http://www.w3schools.com/webservices/tempconvert.asmx?WSDL" and leave all other setting to default.

3.On ButtonClick event of the button I write two lines of code :

 _di_TempConvertSoap Converter = GetTempConvertSoap(true,    
 "http://www.w3schools.com/webservices/tempconvert.asmx?WSDL");

 Edit1->Text = Converter->CelsiusToFahrenheit("32");

So after these three steps I have one unit, which is the main Unit with the Form and with the button event. And one file "tempconvert.cpp" that the WSDL Importer has generated. It quite actually just translates the WSDL code to a C++ one and defines the method to communicate with the server. In my case I have two methods : FahrenheitToCelsius() and CelsiusToFahrenheit(), in the example I use CelsiusToFahrenheit().

I compile it to 32-bit Windows platform, run it and when I click the button, the result "89.6" appears in the text of the Edit component. So this is working as expected.

But when I change the target platform to "Android" and use my mobile phone "Samsung GT-I8262" with Android 4.1.2 and run the project, it just stops and exits. I debugged the problem and it stops at the first command in "tempconvert.cpp" in RegTypes() method.

// ************************************************************************ 
//
// This routine registers the interfaces and types exposed by the WebService.
// ************************************************************************ //
static void RegTypes()
{
  /* TempConvertSoap */
  InvRegistry()->RegisterInterface(__delphirtti(TempConvertSoap), L"http://www.w3schools.com/webservices/", L"utf-8");
  InvRegistry()->RegisterDefaultSOAPAction(__delphirtti(TempConvertSoap), L"http://www.w3schools.com/webservices/%operationName%");
  InvRegistry()->RegisterInvokeOptions(__delphirtti(TempConvertSoap), ioDocument);
  /* TempConvertSoap.FahrenheitToCelsius */
  InvRegistry()->RegisterMethodInfo(__delphirtti(TempConvertSoap), "FahrenheitToCelsius", "",
                                    "[ReturnName='FahrenheitToCelsiusResult']", IS_OPTN);
  /* TempConvertSoap.CelsiusToFahrenheit */
  InvRegistry()->RegisterMethodInfo(__delphirtti(TempConvertSoap), "CelsiusToFahrenheit", "",
                                    "[ReturnName='CelsiusToFahrenheitResult']", IS_OPTN);
  /* TempConvertHttpPost */
  InvRegistry()->RegisterInterface(__delphirtti(TempConvertHttpPost), L"http://www.w3schools.com/webservices/", L"utf-8");
  InvRegistry()->RegisterDefaultSOAPAction(__delphirtti(TempConvertHttpPost), L"");
}
#pragma startup RegTypes 32

Does someone have any idea why this might be happening? I tried on two other Samsung phones and it didn't work. The error that shuts the program down is "Segmentation fault(11)", and more precisely it stops at the following line of code in "System.pas" file :

u_strFromUTF8(PUChar(Dest), MaxDestChars, DestLen, MarshaledAString(Source), SourceBytes, ErrorConv);

Here is some info that I've found about the function:

  1. u_strFromUTF8 - function that converts a UTF-8 string to UTF-16.
  2. UCHAR is a Byte(in Delphi), so PUCHAR is a pointer to Byte.

I cannot se what could possibly go wrong with this function which apparently only converts a string.

So my question is why does the project work on Windows 32 bit version, but on Android it throws Segmentation fault(11)?

I hope I could find a solution for this problem. I will keep looking.

Thank you,

Zdravko Donev :)

UPDATE:

I disassembled the line:

InvRegistry()->RegisterInterface(__delphirtti(TempConvertSoap), L"http://www.w3schools.com/webservices/", L"utf-16");

to get :

  TInvokableClassRegistry *Class = InvRegistry();
  TTypeInfo *Info = __delphirtti(TempConvertSoap);
  UnicodeString Namespace = "http://www.w3schools.com/webservices/";
  UnicodeString WSDLEncoding = "utf-8";

  Class->RegisterInterface(Info, Namespace, WSDLEncoding);

And I saw that the problem occurs when calling InvRegistry() function, but I still haven't found the problem as I cannot reach the source code of the function.


Solution

  • I found a solution.

    I deleted the line

    #pragma startup RegTypes 32
    

    and called the method RegTypes() on my own when I create the form and it worked.