libcurl の使い方などについてメモします。
標準 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
標準 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>
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 ライセンスで提供されます。
| 2023-03-01 | - | 新規作成 |