読者です 読者をやめる 読者になる 読者になる

Haruyuki Mohri

毛利春幸のブログです。

C++BuilderでDelphiのジェネリクスCollections TDictionary__2 などを使う場合

C++BuilderDelphiジェネリクスCollections TDictionary__2などを使う場合

How to Handle Delphi Generics in C++ - RAD Studio
上記URLにもありますが TList__1<TObject* >*こんなのを作るとilink32, ilink64エラーになります
f:id:mojeld:20170125172031g:plain

[ilink32 Error] Error: Unresolved external 'System::Generics::Collections::TList__1<System::Net::Httpclientcomponent::TNetHTTPClient *>::' referenced from C:\***\WIN32\DEBUG\UNIT1.OBJ
[ilink32 Error] Error: Unresolved external '__fastcall System::Generics::Collections::TList__1<System::Net::Httpclientcomponent::TNetHTTPClient *>::TList__1<System::Net::Httpclientcomponent::TNetHTTPClient *>()' referenced from C:\*\*\*\WIN32\DEBUG\UNIT1.OBJ
[ilink32 Error] Error: Unable to perform link

64ビット
[ilink64 Error] Error: Unresolved external 'vtable for System::Generics::Collections::TDictionary__2<int, System::UnicodeString>' referenced from C:\*\*\*\WIN64\DEBUG\UNIT1.O

Delphiジェネリクス型なので Delphi側で内部的に「TList__1<TObject* >*」を作る必要があります
C++プロジェクトにDelphiユニットを追加します。

unit Unit2;

interface
uses
  System.SysUtils, System.Types,  System.Generics.Collections, FMX.StdCtrls,
  System.Net.HttpClient, System.Net.HttpClientComponent;
type
  TDummyNetHttp = TList<TNetHTTPClient>;

Delphiのtype宣言のところだけにダミーを作ります。

 TList__1<TNetHTTPClient* >* net_list = new TList__1<TNetHTTPClient* >();

これでビルドが成功します。

 TList__1<TNetHTTPClient* >* net_list = new TList__1<TNetHTTPClient* >();
    for (auto i = 0; i < 10; i++) {
        net_list->Add(new TNetHTTPClient(nullptr));
    }

    _di_IHTTPResponse res = net_list->Items[0]->Get("http://localhost:8080/version");
    Memo1->Lines->Append(res->ContentAsString(TEncoding::UTF8));

www.youtube.com

How to use TADOQuery* with C++Builder Console

f:id:mojeld:20170118100008g:plain

TADOQueryを使うためのヘッダー

#include <Data.DB.hpp>
#include <Data.Win.ADODB.hpp>

インスタンスを作成

int _tmain(int argc, _TCHAR* argv[])
{
    TADOQuery* a=new TADOQuery(nullptr);
}

実行してもリンクエラーになります

[ilink64 エラー] Error: Unresolved external 'vtable for Data::Win::Adodb::TADOQuery' referenced from C:\EMBARCADERO\ADO_ZIP_INSERT\CONSOLE_ADO_INS\WIN64\DEBUG\ADO_INS_THREAD.O
[ilink64 エラー] Error: Unresolved external 'Data::Win::Adodb::TADOQuery::TADOQuery(System::Classes::TComponent*)' referenced from C:\EMBARCADERO\ADO_ZIP_INSERT\CONSOLE_ADO_INS\WIN64\DEBUG\ADO_INS_THREAD.O

下記(adortl.lib)を追加する必要があります。

#if defined(_WIN64)
    //64Bit
   #pragma comment(lib,"adortl.a")
#else
    //32Bit
   #pragma link  "adortl.lib"
#endif

community.embarcadero.com

bcc32c(clang) std::round()でエラー 回避するには

bcc32c(clang) std::round()でエラー

bcc32cではstd:: round()下記コードでエラーが出ます(bcc64は問題なし)
10.1 Berlin Update 2でもまだ同じく直ってません
several unresolved functions declared in <math.h>

unsigned int float2int(float in)
{
    unsigned int i {static_cast<unsigned int>(std::round(in))};
    return i;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
    Edit1->Text = float2int(1.1);
}

bcc32cでこの問題を回避する場合

unsigned int float2int(float in)
{
#if __WIN32__
    unsigned int i{static_cast<unsigned int>(System::Math::RoundTo(in, 0))};
#else
    unsigned int i {static_cast<unsigned int>(std::round(in))};
#endif
    return i;
}

f:id:mojeld:20161118174840j:plain

C++Builder 定義済みマクロ - RAD Studio

関連

EMS開発サーバー(RAD Server)環境 + nginxリバースプロキシ - Qiita
C++Builder IDEからC言語コンソールアプリプロジェクトを作る方法 - Qiita

Visual C++ 2015 cpprestsdkを使ってREST受信

Visual C++ 2015 cpprestsdkを使ってREST受信する

マイクロソフトさんがgithubで公開しているREST SDKです
github.com/Microsoft/cpprestsdk

NuGetからcpprestsdkが取れます

f:id:mojeld:20161027172348j:plain
How to use the C Rest SDK NuGet package · Microsoft/cpprestsdk Wiki · GitHub

方法: HTTP サーバーに接続する (C++ REST SDK)
JSONを操作するライブラリも付いてます
方法: JSON データを操作する (C++ REST SDK)
f:id:mojeld:20161027171809j:plain

試したソース

フリープラン- 駅すぱあとWebサービス - システム連携サービス - サービス・製品紹介 - 駅すぱあとワールド
上記のフリープランデータの一部をREST取得試してみました。

#include "stdafx.h"
#include <cpprest/http_client.h>
#include <locale.h>

#include "eki_key.h"

int main()
{
    using namespace web::http;
    std::locale::global(std::locale("Japanese_Japan.932"));
    setlocale(LC_ALL, std::locale().c_str());
    client::http_client c1{ EKI_URL  L"/v1/json/station/light" };

    //web::http::uri_builder
    uri_builder url1{ uri_builder() 
        .append_query(L"key", EKI_KEY)
        .append_query(L"code", L"29090")
    };

    std::wstring s1 = url1.to_string();
    std::wcout << s1 << std::endl;

    //pplx::task<web::http::http_response> 
    auto t1{ c1.request(web::http::methods::GET, s1) };

    t1.then([](http_response res) {
        std::wstring s1{ res.extract_string().get().c_str() };
        wprintf(s1.c_str() );
    }).wait();

    
    return 0;
}

結果

f:id:mojeld:20161027172710j:plain
JSONの文字列が取得できました。

std::wstring to byte[]

VC++2015の場合

f:id:mojeld:20161012124745j:plain

#include "stdafx.h"
#include <string>
#include <iostream>
#include <memory>
#include <sstream>
#include <locale>

using Byte = char;
using PByte = std::shared_ptr<Byte>;
PByte WstrToChar(std::wstring& s1)
{
    unsigned int iLength = s1.length() * 2 + 1;
    PByte result_{new Byte[iLength]};
    memcpy(result_.get(), s1.c_str(), iLength);  //wstring to byte[]
    return result_;
}

int main()
{
    std::locale::global(std::locale("japanese"));
    std::wstring ls = L"あいうえお日本語";
    std::wstringstream as1;
    std::string s_out;
    PByte c1 = WstrToChar(ls);
    char* c2 = c1.get();
    for (int i = 0; i < ls.length() * 2; i++)
    {
        int iin = static_cast<int>(*c2);
        if (iin < 0) { iin = iin - 0xffffff00; }//これはなぜ?
        as1 << std::hex << std::showbase << iin << std::endl;
        c2++;
    }
    std::wcout << as1.str();
    std::cin >> s_out;
    return 0;
}

C++Builder 10.1Berlin の場合

using PSByte = std::shared_ptr<Byte>;
PSByte WstrToChar(std::wstring& s1)
{
    unsigned int iLength = s1.length() * 2 + 1;
    PSByte result_{new Byte[iLength]};
    memcpy(result_.get(), s1.c_str(), iLength);  //wstring to byte[]
    return result_;
}

void __fastcall TForm1::FormCreate(TObject *Sender)
{
    std::locale::global(std::locale("japanese"));
    std::wstring ls = L"あいうえお日本語";
    std::wstringstream as1;
    std::string s_out;
    PSByte c1 = WstrToChar(ls);
    Byte* c2 = c1.get();
    for (int i = 0; i < ls.length() * 2; i++)
    {
        as1 << std::hex << std::showbase << static_cast<unsigned int>(*c2) << std::endl;
        c2++;
    }
    Memo1->Lines->Text = as1.str().c_str();

}