libcurl

libcurl の使い方などについてメモします。

 

 

 

1. libcurl をインストールする

1-1. Linux (Ubuntu)

[概要]

標準 c++ 言語にはネットワーク関連処理を行うためのライブラリが脆弱ですので、本ページでは libcurl というオープンソースライブラリを紹介します。libcurlは複数のプラットフォームで同じようにビルド、稼動させることができるフリーで使いやすいクライアントサイド URL 転送ライブラリです。

 

[環境]

OS : Ubuntu, 22.04

 

■ curl のインストール

sudo apt install curl

 

■ libcurl のインストール

デフォルト版

sudo apt-get install libcurl-dev

OpenSSL 版

sudo apt-get install libcurl4-openssl-dev

GnuTLS 版

sudo apt-get install libcurl4-gnutls-dev

 

 

1-2. Windows

[概要]

標準 c++ 言語にはネットワーク関連処理を行うためのライブラリが脆弱ですので、本ページでは libcurl というオープンソースライブラリを紹介します。libcurlは複数のプラットフォームで同じようにビルド、稼動させることができるフリーで使いやすいクライアントサイド URL 転送ライブラリです。Microsoft Visual Studio からも利用可能です。

ここでは Microsoft が提供する vcpkg というクロスプラットフォームのパッケージマネージャーを使用して libcurl を導入する手順を紹介します。vcpkg を使用することで、c/c++ の外部ライブラリを利用したい場合に手動でソースコードからビルドすることなくインストールやリンクを簡単に行えるようになります。依存関係も vcpkg が解決してインストールしてくれます。vcpkg は Windows、Linux および MacOS に対応しているようです。

 

[環境]

コンパイラ : Visual Studio 2022 pro., Version 17.5.1
ライブラリ : curl:x64-windows, 7.88.1
OS : Windows11 home, 22H2

 

(1) vcpkg をインストール

git の clone コマンドを使用し、GitHub から vcpkg リポジトリをクローンします。任意の場所で実施してください。私は Documents フォルダ内に Github フォルダを作成してここで作業しました。

git clone https://github.com/Microsoft/vcpkg.git

[実行例]

C:\Users\foo\Documents\Github>git clone https://github.com/Microsoft/vcpkg.git
Cloning into 'vcpkg'...
remote: Enumerating objects: 181622, done.
remote: Total 181622 (delta 0), reused 0 (delta 0), pack-reused 181622
Receiving objects: 100% (181622/181622), 68.57 MiB | 3.37 MiB/s, done.
Resolving deltas: 100% (115829/115829), done.
Updating files: 100% (9787/9787), done.

C:\Users\foo\Documents\Github>

 

(2) vcpkg 実行ファイルを生成

クローンした中にある bootstrap-vcpkg.bat を実行して実行ファイルを生成します。

cd vcpkg
bootstrap-vcpkg.bat

[実行例]

C:\Users\foo\Documents\Github>cd vcpkg

C:\Users\foo\Documents\Github\vcpkg>bootstrap-vcpkg.bat
Downloading https://github.com/microsoft/vcpkg-tool/releases/download/2023-02-16/vcpkg.exe -> C:\Users\foo\Documents\Github\vcpkg\vcpkg.exe... done.
Validating signature... done.

Telemetry
---------
vcpkg collects usage data in order to help us improve your experience.
The data collected by Microsoft is anonymous.
You can opt-out of telemetry by re-running the bootstrap-vcpkg script with -disableMetrics,
passing --disable-metrics to vcpkg on the command line,
or by setting the VCPKG_DISABLE_METRICS environment variable.

Read more about vcpkg telemetry at docs/about/privacy.md

C:\Users\foo\Documents\Github\vcpkg>

 

(3) vcpkg install コマンドで curl をインストール

vcpkg install コマンドにより curl をインストールします。ここでは triplet として "x64-windows" を指定します。

triplet とは環境を表す文字列で、対応している triplet は vcpkg help triplet コマンドで確認できます。

vcpkg install curl:x64-windows

[実行例]

C:\Users\foo\Documents\Github\vcpkg>vcpkg install curl:x64-windows
Computing installation plan...
The following packages will be built and installed:
    curl[core,non-http,schannel,ssl,sspi]:x64-windows -> 7.88.1
  * zlib[core]:x64-windows -> 1.2.13
Additional packages (*) will be modified to complete this operation.
Detecting compiler hash for triplet x64-windows...
Restored 0 package(s) from C:\Users\foo\AppData\Local\vcpkg\archives in 161 us. Use --debug to see more details.
Installing 1/2 zlib:x64-windows...
Building zlib[core]:x64-windows...
-- Using cached madler-zlib-v1.2.13.tar.gz.

*** 途中省略 ***

-- Fixing pkgconfig file: C:/Users/foo/Documents/Github/vcpkg/packages/curl_x64-windows/debug/lib/pkgconfig/libcurl.pc
-- Installing: C:/Users/foo/Documents/Github/vcpkg/packages/curl_x64-windows/share/curl/vcpkg-cmake-wrapper.cmake
-- Installing: C:/Users/foo/Documents/Github/vcpkg/packages/curl_x64-windows/share/curl/copyright
-- Performing post-build validation
Stored binary cache: "C:\Users\foo\AppData\Local\vcpkg\archives\0b\0be4e066bb110c9e83d7ab0d78d61cee202eb0797b927e196b1af2e37d0a65d4.zip"
Elapsed time to handle curl:x64-windows: 1.262 min
Total install time: 1.423 min
curl provides CMake targets:

    # this is heuristically generated, and may not be correct
    find_package(CURL CONFIG REQUIRED)
    target_link_libraries(main PRIVATE CURL::libcurl)


C:\Users\foo\Documents\Github\vcpkg>

 

以上で libcurl のインストールを完了です。

 

(4) Visual Studio へ組み込む

vcpkg integrate install コマンドを実行することで、vcpkgでインストールしたライブラリを Visual Studio から利用できるようになります。インクルードディレクトリやライブラリディレクトリ、およびライブラリが自動で "Visual Studio" に追加されます。

Visual Studio 環境へ組み込まれることを好まない場合、こちらのコマンドを実行せずにご自身で個別にプロジェクトへ インクルードディレクトリやライブラリディレクトリ、およびライブラリの設定を行ってください。

vcpkg integrate install

[実行例]

C:\Users\foo\Documents\Github\vcpkg>vcpkg integrate install
Applied user-wide integration for this vcpkg root.
CMake projects should use: "-DCMAKE_TOOLCHAIN_FILE=C:/Users/foo/Documents/Github/vcpkg/scripts/buildsystems/vcpkg.cmake"

All MSBuild C++ projects can now #include any installed libraries. Linking will be handled automatically. Installing new libraries will make them instantly available.

C:\Users\foo\Documents\Github\vcpkg>

 

(5) インストールしたライブラリを確認

vcpkg list コマンドを実行することで、インストールしたライブラリ一覧を表示することができます。

vcpkg list

[実行例]

C:\Users\foo\Documents\Github\vcpkg>vcpkg list
curl:x64-windows                                  7.88.1              A library for transferring data with URLs
curl[non-http]:x64-windows                                            Enables protocols beyond HTTP/HTTPS/HTTP2
curl[schannel]:x64-windows                                            SSL support (Secure Channel)
curl[ssl]:x64-windows                                                 Default SSL backend
curl[sspi]:x64-windows                                                SSPI support
vcpkg-cmake-config:x64-windows                    2022-02-06#1
vcpkg-cmake:x64-windows                           2022-12-22
zlib:x64-windows                                  1.2.13              A compression library
zlib:x86-windows                                  1.2.13              A compression library

C:\Users\foo\Documents\Github\vcpkg>

 

 

2. i-PRO カメラと JPEG 接続して映像を表示してみる

[概要]

 c++(Visual Studio) と OpenCV, libcurl を使って、PC と i-PRO カメラを JPEG で接続して映像表示してみます。

 

[評価環境]

コンパイラ : Visual Studio 2022 pro., Version 17.5.1
ライブラリ : OpenCV, 4.6.0
  curl:x64-windows, 7.88.1
OS : Windows11 home, 22H2

 

※ "Community edition" でも動作する内容です。

 

 

[プログラム]

サンプルプログラムのソースコードを以下に示します。

 

動作確認は Windows 上の Visual Studio で行っていますが、プログラム内容から恐らく Linux および WSL 環境でも同じソースコードで動作するはずです。

opencv, libcurl 環境を必要とするのは Windows も Linux も同じです。

 

[プログラムソース "connect_with_jpeg_1.cpp"]

/*
======================================================================================
[Abstract]
    Try connecting to an i-PRO camera with JPEG.
    HTTPで接続してJPEGの連続表示で i-PRO カメラと接続してみる

[Details]
    Let's try first.
    まずはやってみる

[Library install]
    opencv:     See "https://i-pro-corp.github.io/Programing-Items/cpp_vs/install_opencv.html"
======================================================================================
*/

#include <iostream>
#include <vector>
#include <opencv2/opencv.hpp>
#include <opencv2/core/utility.hpp>
#include <curl/curl.h>


const std::string user_id       = "user-id";         // Change to match your camera setting
const std::string user_pw       = "password";        // Change to match your camera setting
const std::string host          = "192.168.0.10";    // Change to match your camera setting
const std::string resolution    = "1920";
const std::string winname       = "VIDEO";           // Window title
const std::string cameraURL     = "http://" + host + "/cgi-bin/camera?resolution=" + resolution;


/// <summary>
/// A curl callback function. Call this function when data is received.
/// </summary>
/// <param name="ptr">ptr points to the delivered data.</param>
/// <param name="size">size is always 1.</param>
/// <param name="nmemb">the size of the deliverd data is nmemb.</param>
/// <param name="userdata">Pointer to buffer specified by CURLOPT_WRITEDATA</param>
/// <returns>
/// Return the number of bytes actually taken care of.
/// If that amount differs from the amount passed to your callback function, it will signal an error condition to the library.
/// This will cause the transfer to get aborted and the libcurl function used will return CURLE_WRITE_ERROR.
/// </returns>
/// <detail>See "https://curl.se/libcurl/c/CURLOPT_WRITEFUNCTION.html" for details.</detail>
size_t onReceive(void* ptr, size_t size, size_t nmemb, void* userdata) {
    std::vector<char>* receiveBuffer = (std::vector<char>*)userdata;
    const size_t sizes = size * nmemb;

    receiveBuffer->insert(receiveBuffer->end(), (char*)ptr, (char*)ptr + sizes);

    return sizes;
}


/// <summary>
/// Receiving one JPEG image from the i-PRO camera.
/// </summary>
/// <param name="url">CGI command for 1 shot JPEG</param>
/// <param name="receiveBuffer">A variable to store the received JPEG image</param>
/// <retval>true: Success to get JPEG image.</retval>
/// <retval>false: Failed to get JPEG image.</retval>
bool get_jpeg_image(const std::string url, std::vector<char>& receiveBuffer) {
    CURL*       curl = NULL;
    CURLcode    res;

    // initialize curl.
    curl = curl_easy_init();
    if (!curl) {
        printf("curl_easy_init() failed...\n");
        return false;
    }

    // curl option for digest authentication
    curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
    std::string user_id_pw = user_id + ":" + user_pw;
    curl_easy_setopt(curl, CURLOPT_USERPWD, user_id_pw.c_str());

    // curl option
    curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &receiveBuffer);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, onReceive);

    // execute
    res = curl_easy_perform(curl);

    if (res != CURLE_OK) {
        printf("curl_easy_perform() failed...%s\n", curl_easy_strerror(res));
        return false;
    }
    curl_easy_cleanup(curl);
    return true;
}


/// <summary>
/// main function
/// </summary>
/// <returns>Always returns EXIT_SUCCESS(0).</returns>
int main() {
    cv::Mat recv_data;
    bool isDataReceived;
    char ret;
    std::vector<char> receiveBuffer;

    while (true) {

        // get image data by HTTP
        isDataReceived = get_jpeg_image(cameraURL, receiveBuffer);
        if (!isDataReceived) {
            std::cout << "get_jpeg_image() failed..." << std::endl;
            break;
        }

        // JPEG decode
        cv::Mat frame = cv::imdecode(receiveBuffer, cv::IMREAD_UNCHANGED);

        // Clear all received data.
        receiveBuffer.clear();

        // Please modify the value to fit your PC screen size.
        resize(frame, frame, cv::Size(), 0.5, 0.5);                     // Setting by magnification.

        // Display video.
        cv::imshow(winname, frame);

        ret = (char)cv::waitKey(1);     // necessary to display the video by cv::imshow().

        // Press the "q" key to finish.
        if (ret == 'q') {
            break;
        }
    }

    cv::destroyAllWindows();

    return EXIT_SUCCESS;
}

 

上記プログラムを動かした様子を動画で示します。

こんなに簡単なプログラムでとても快適な映像表示を実現することができました。

[動画] JPEG でカメラと接続して映像表示してみた様子

 

 

ライセンス

本ページの情報は、特記無い限り下記 MIT ライセンスで提供されます。

The MIT License (MIT)

Copyright © 2023 Kinoshita Hidetoshi

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

 


参考

 


 

変更履歴

2023-03-01 - 新規作成

 

Programming Items トップページ

プライバシーポリシー