Translation code

This is the forum for miscellaneous technical/programming questions.

Moderator: 2ffat

Translation code

Postby ingalime » Wed Apr 12, 2017 3:25 am

Please help me translate it in C++ Builder Berlin:
Code: Select all
procedure TFormMain.RegisterDevice;
begin
  TTask.Run(
    procedure
    var
      aHTTP: THTTPClient;
    begin
      aHTTP := THTTPClient.Create;
      try
        aHTTP.Get('http://rzaripov.kz/pushTest/api.php?method=saveToken&deviceID=' + FDeviceID + '&deviceToken=' +
          FDeviceToken + '&platform='{$IFDEF ANDROID} + 'ANDROID' {$ELSEIF defined(IOS)} + 'IOS' {$ENDIF});
      finally
        FreeAndNil(aHTTP);
      end;
    end);
end;

Thanks.
ingalime
Active Poster
Active Poster
 
Posts: 12
Joined: Wed Apr 12, 2017 3:22 am

Re: Translation code

Postby Lena » Thu Apr 13, 2017 4:06 am

I guess over something like that
Code: Select all
#include <memory>
#include <System.Threading.hpp>
 
 class TCppTask : public TCppInterfacedObject<TProc> {
 public:
    TCppTask()
    {}
    void __fastcall Invoke()
        {
         std::unique_ptr<THTTPClient> aHTTP(THTTPClient::Create());
         aHTTP->Get(L"http://***");
        }
 };
 
void __fastcall  TForm1::RegisterDevice()
{
 TTask::Run(_di_TProc(new TCppTask()));
}
Lena
BCBJ Master
BCBJ Master
 
Posts: 519
Joined: Sun Feb 06, 2011 1:28 pm

Re: Translation code

Postby ingalime » Thu Apr 13, 2017 7:07 am

Thank you.
Code: Select all
String sPlatform =
#ifdef ANDROID
  "ANDROID"
#elseif defined(IOS)
  "IOS"
#else
  ""
#endif
  ;


class TCppTask : public TCppInterfacedObject<TProc>
{
 String FDeviceID, FDeviceToken;
 public:
    TCppTask(String AnID, String AToken) : FDeviceID(AnID), FDeviceToken(AToken)
    {
    }
    void __fastcall Invoke()
    {
      String link =
      String().sprintf(L"http://rzaripov.kz/pushTest/api.php?method=saveToken&deviceID=%s&deviceToken=%s&platform=%s",
                   FDeviceID.c_str(), FDeviceToken.c_str(), sPlatform.c_str());
      std::unique_ptr<THTTPClient> aHTTP(THTTPClient::Create());
      aHTTP->Get(link);
    }
};

// ---------------------------------------------------------------------------
void __fastcall  TForm1::RegisterDevice()
{
   TTask::Run(_di_TProc(new TCppTask(FDeviceID, FDeviceToken)));
}


Why sprintf does not initialize %s on android platform?
I see data in FDeviceID.c_str() and FDeviceToken.c_str() but in link ="".
How initialize sPlatform? Always ="".
ingalime
Active Poster
Active Poster
 
Posts: 12
Joined: Wed Apr 12, 2017 3:22 am

Re: Translation code

Postby HsiaLin » Fri Apr 14, 2017 4:53 am

Try it like this?

Code: Select all
String link;
      link.sprintf(L"http://rzaripov.kz/pushTest/api.php?method=saveToken&deviceID=%s&deviceToken=%s&platform=%s",
                   FDeviceID.c_str(), FDeviceToken.c_str(), sPlatform.c_str());
      std::unique_ptr<THTTPClient> aHTTP(THTTPClient::Create());
HsiaLin
BCBJ Master
BCBJ Master
 
Posts: 281
Joined: Sun Jul 08, 2007 6:29 pm

Re: Translation code

Postby ingalime » Fri Apr 14, 2017 6:23 am

Hi.
Try it like this?

No.

I found a solution on another forum:
Code: Select all
#if defined(_PLAT_IOS)
    String sPlatform = L"IOS";
#elif defined(__ANDROID__)
    String sPlatform = L"ANDROID";
#else
    String sPlatform = L"";
#endif


class TCppTask : public TCppInterfacedObject<TProc>
{
 String FDeviceID, FDeviceToken;
 public:
    TCppTask(String AnID, String AToken) : FDeviceID(AnID), FDeviceToken(AToken)
    {
    }
    void __fastcall Invoke()
    {
      String link =
      String().sprintf(L"http://rzaripov.kz/pushTest/api.php?method=saveToken&deviceID=%s&deviceToken=%s&platform=%s",
                   UTF8String(FDeviceID).c_str(), UTF8String(FDeviceToken).c_str(), UTF8String(sPlatform).c_str());

      std::unique_ptr<THTTPClient> aHTTP(THTTPClient::Create());
      aHTTP->Get(link);
    }
};

// ---------------------------------------------------------------------------
void __fastcall  TForm1::RegisterDevice()
{
  TTask::Run(_di_TProc(new TCppTask(FDeviceID, FDeviceToken)));
}
ingalime
Active Poster
Active Poster
 
Posts: 12
Joined: Wed Apr 12, 2017 3:22 am

Re: Translation code

Postby rlebeau » Fri Apr 14, 2017 4:13 pm

Lena wrote:I guess over something like that


If you are using a Clang-based compiler, you can use a C++11 lambda instead of deriving a class from TCppInterfacedObject (see How to Handle Delphi Anonymous Methods in C++: Using a Lambda Expression):

Code: Select all
#include <memory>
#include <System.Threading.hpp>
 
void __fastcall  TForm1::RegisterDevice()
{
    TTask::Run([](){
        std::unique_ptr<THTTPClient> aHTTP(THTTPClient::Create());
        aHTTP->Get(L"http://***");
    });
}
Last edited by rlebeau on Fri Apr 14, 2017 4:24 pm, edited 1 time in total.
Remy Lebeau (TeamB)
Lebeau Software
User avatar
rlebeau
BCBJ Author
BCBJ Author
 
Posts: 1446
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA

Re: Translation code

Postby rlebeau » Fri Apr 14, 2017 4:22 pm

ingalime wrote:
Code: Select all
String sPlatform =
#ifdef ANDROID
  "ANDROID"
#elseif defined(IOS)
  "IOS"
#else
  ""
#endif
  ;



"ANDROID" and "IOS" are Delphi compiler conditionals. Detecting the various platforms in C++ is a bit different. See:

Predefined Macros

Writing C++ Code for BCCAARM

Writing C++ Code for BCCIOSARM

Writing C++ Code for BCCIOSARM64

For example:

Code: Select all
String sPlatform =
#ifdef __ANDROID__
  _D("ANDROID")
#elseif defined(__APPLE__) && (defined(__arm__) || defined(__arm64__))
  _D("IOS")
#else
  _D("")
#endif
  ;


However, note that UnicodeString::sprintf() is broken on Android to begin with:

RSP-13285: UnicodeString::XXXprintf() methods do not accept UTF-16 data for "%s" specifier

So you would have to do something more like this instead when calling sprint():

Code: Select all
String link;
link.sprintf(
  _D("http://rzaripov.kz/pushTest/api.php?method=saveToken&deviceID=%s&deviceToken=%s&platform=%s"),
  #ifdef __ANDROID__
  UTF8String(FDeviceID).c_str(), UTF8String(FDeviceToken).c_str(), UTF8String(Platform).c_str()
  #else
  FDeviceID.c_str(), FDeviceToken.c_str(), sPlatform.c_str()
  #endif
);


Or, use Sysutils::Format() instead, which does not suffer from the sprintf() issue:

Code: Select all
String link = Format(
  _D("http://rzaripov.kz/pushTest/api.php?method=saveToken&deviceID=%s&deviceToken=%s&platform=%s"),
  ARRAYOFCONST(( FDeviceID, FDeviceToken, sPlatform ))
);
Remy Lebeau (TeamB)
Lebeau Software
User avatar
rlebeau
BCBJ Author
BCBJ Author
 
Posts: 1446
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA

Re: Translation code

Postby ingalime » Sat Apr 15, 2017 12:13 am

Thank you very mich!
Code: Select all
void __fastcall  TForm1::RegisterDevice()
{
   TTask::Run([]()
    {
     String link = Format(_D("http://rzaripov.kz/pushTest/api.php?method=saveToken&deviceID=%s&deviceToken=%s&platform=%s"),
                        ARRAYOFCONST(( FDeviceID, FDeviceToken, sPlatform )));//error
     std::unique_ptr<THTTPClient> aHTTP(THTTPClient::Create());
     aHTTP->Get(link);
    }
   );
}

[bccaarm Error] myfile.cpp(132): 'this' cannot be implicitly captured in this context
:(

2. Why are you using _D instead L?

3. What is the real difference?:
Code: Select all
String sPlatform =
#ifdef __ANDROID__
  _D("ANDROID")
#elseif defined(__APPLE__) && (defined(__arm__) || defined(__arm64__))
  _D("IOS")
#else
  _D("")
#endif
  ;


And
Code: Select all
#if defined(_PLAT_IOS)
   String sPlatform = L"IOS";
#elif defined(__ANDROID__)
   String sPlatform = L"ANDROID";
#else
   String sPlatform = L"";
#endif


Thank you!
ingalime
Active Poster
Active Poster
 
Posts: 12
Joined: Wed Apr 12, 2017 3:22 am

Re: Translation code

Postby rlebeau » Mon Apr 17, 2017 9:10 am

ingalime wrote:
Code: Select all
String link = Format(_D("http://rzaripov.kz/pushTest/api.php?method=saveToken&deviceID=%s&deviceToken=%s&platform=%s"),
    ARRAYOFCONST(( FDeviceID, FDeviceToken, sPlatform )));//error

[bccaarm Error] myfile.cpp(132): 'this' cannot be implicitly captured in this context
:(


Add 'this' to the capture list of the lambda:

Code: Select all
void __fastcall  TForm1::RegisterDevice()
{
    TTask::Run([this]()
        {
            ...
        }
    );
}


Otherwise, capture the individual variables directly:

Code: Select all
void __fastcall  TForm1::RegisterDevice()
{
    TTask::Run([FDeviceID, FDeviceToken, sPlatform]()
        {
            ...
        }
    );
}


ingalime wrote:2. Why are you using _D instead L?


Because the code is using System::String. Similar to how the _T() and TEXT() macros map a literal to the data type used by the C runtime's _TCHAR and Win32 API's TCHAR data types, respectively, the _D() macro maps a literal to the data type used by the System::String and System::Char data types. Prior to CB2009, that what Ansi 'char'. In CB2009 onwards, that is now UTF-16 'wchar_t' (Windows) and 'char16_t' (other platforms). Who knows what it will be in the future.

ingalime wrote:3. What is the real difference?


On Windows, there is currently no difference, since L"" and _D("") both map to the same 'wchar_t' data type. On other platforms, though, there is a difference, since 'wchar_t' is 32bit instead of 16bit on some platforms. That is why 'char16_t' is used instead on those platforms, to ensure 16bit since System::String is currently UTF-16 on all platforms. L"" does not produce a 16bit literal on those platforms, u"" does. Do _D() maps to either L"" or u"" as needed.
Remy Lebeau (TeamB)
Lebeau Software
User avatar
rlebeau
BCBJ Author
BCBJ Author
 
Posts: 1446
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA

Re: Translation code

Postby ingalime » Tue Apr 18, 2017 10:47 pm

Thank you!
ingalime
Active Poster
Active Poster
 
Posts: 12
Joined: Wed Apr 12, 2017 3:22 am


Return to Technical

Who is online

Users browsing this forum: Google [Bot], Yahoo [Bot] and 10 guests