c言語からredisにアクセスする方法を調べてみると,hiredisというツールを使ってアクセスすることができると記載があったので,試してみることにした。
redisサーバの準備
redisサーバの構築方法は省略します
redisサーバを準備して,中身が空であることを確認します
hiredisの準備
注意,本手順で実行する場合はredisの値がgetができませんのでご注意ください。
git clone https://github.com/redis/hiredis.git
cd hiredis/
make
make install
redisへアクセスするサンプルコードをコンパイルする
サンプルコードを用意する
#include <stdio.h>
#include <hiredis/hiredis.h>
#include <stdlib.h>
extern int main(int argc, char **argv) {
redisContext *con;
redisReply *rep;
int i;
/* 接続 */
con = redisConnect("127.0.0.1", 6379);
if (!con) {
fprintf(stderr, "redisConnect error\n");
return -1;
}
if (con->err) {
fprintf(stderr, "%s\n", con->errstr);
redisFree(con);
return -1;
}
/* テスト用データの設定 */
for (i = 1; i <= 3; i++) {
(redisReply *)redisCommand(con, "SET KEY-%d VALUE-%d", i,i);
}
/* データ表示 */
for (i = 1; i <= 3; i++) {
rep = (redisReply *)redisCommand(con, "GET KEY-%d", i);
if (!rep) {
fprintf(stderr, "redisReply error\n");
redisFree(con);
return -1;
}
if (rep->type != REDIS_REPLY_ERROR) {
printf("KEY-%d = %s\n", i, rep->str);
}
freeReplyObject(rep);
}
/* 終了 */
redisFree(con);
return 0;
}
コンパイルする
gcc -o redis redistest.c -lhiredis
"error while loading shared libraries: libhiredis.so.1.1.1-dev: cannot open shared object file: No such file or directory"というエラーが発生した。
libhiredis.so.1.1.1-devが見つからず,解決できなかったと思い,以下のコマンドで追加
sudo apt-get install libhiredis-dev
再度以下のコマンドでコンパイルするとコンパイルができました。
gcc -o redis redistest.c -lhiredis
試しに実行してみるとnullが返ってきました。
redisの方でコマンドで確認してみると値は入っていることがわかる。
何故かhiredisの方から値が取得できていない。
調査
コンパイルされているバイナリに何がリンクされているのかを確認する
lddコマンドを使って中身を見てみます。
"error while loading shared libraries: libhiredis.so.1.1.1-dev: cannot open shared object file: No such file or directory"というエラーが発生した時のバイナリ
リンク先が"not fount"になっていました。これなら当然動かないなと納得しました。
値が取得できないときのバイナリ
リンクを見てみると"libhiredis.so.0.14"がリンクされていました
指定されているフォルダを見に行くとlibhiredis.soがlibhiredis.so.0.14にシンボリックリンクが張られていました。
gccのコンパイルオプションで-lhiredisを指定して実行すると,該当のファイルを検索して一致した場合にリンクが行われるようになります。以下のコマンドを実行してから別のlibhiredisが参照されていました
sudo apt-get install libhiredis-dev
おそらくhiredisが上記のlibhiredis-devのinstallで入れ替わったのだと思います。
hiredisのgithubを確認してみると,0.14より1.1.1の方が新しいことがわかったので,
"libhiredis.so.1.1.1-dev"を直接参照して試してみることにする。
libhiredis.so.1.1.1-devを以下のコマンドで検索した
find / -name libhiredis.so.1.1.1-dev
その結果,/usr/local/libに配置されていることがわかった。
直接パスを指定して,libhiredis.soをリンクしてみることにする。
gcc -o redis redistest.c -lhiredis -L/usr/local/lib
結果は以下のようになった。
再度実行すると値が取得することが可能になった。
結果のまとめ
libhiredis.so.0.14がリンクされている場合,setすることは可能だがgetするとnullが取得されてしまった。
libhiredis.so.0.14がリンクされているところをlibhiredis.so.1.1.1-devにすることで値が取得することが可能になった。
libhiredis.so.0.14がリンクされているときにgetすると値がnullになるかは現在のところ不明だが,回避方法としてここにまとめておきます。
追記
apt-get install libhiredis-devが問題だと思い,removeしてみた
sudo apt-get remove libhiredis-dev
再度 gcc で-lhiredisを実行すると"not found"ではなくpathが通ってリンクされていた。
libhiredis-devしたことでpathが通ったものと考えられる。
Cでバイナリを作成する際にはリンク先が正しいことを確認していかないといけないと改めて認識された件でした。