- 2008年2月22日 23:46
- 仕事のこと
去年の暮れから C に興味を持ち出した。まぁ、正確には Apche モジュールなんだけど。
残念ながらパンダ本は未だに手に入ってないわけだけど、気休めに買った gcc と K&R の本をそこそこ読んだので実際に C を書いてみようかなぁと。
何よりもまず、.emacs ですよね。
;; cc-mode
(require 'cc-mode)
;; Kernighan & Ritchie style
(setq c-default-style "k&r")
(add-hook 'c-mode-common-hook
'(lambda ()
(progn
(c-toggle-hungry-state 1)
(define-key c-mode-base-map "\C-m" 'newline-and-indent)
(setq c-basic-offset 4 indent-tabs-mode nil))))
hello_world.c
#include <stdio.h>
int main(int argc, char *argv[]) {
printf("Hello World!\n");
return 0;
}
gcc hello_world.c -o hello_world でコンパイル。実行。
[travail@mina]~/c% gcc hello_world.c -o hello_world [travail@mina]~/c% ./hello_world Hello World!
LL な Perl でしかまともなプログラムを書いたことのない僕にしては、この「コンパイル」という作業にちょっと感動します。
で、Hello World も済ませたし、次に何書こうか考えたものの特に何もないのでとりあえず DB に接続してみようかなぁと。
リモートホストの DB(saycheese) につないで、とあるテーブル(thumbnail)から10件 SELECT して、とあるカラムのデータ(small サイズのサムネイル)をファイル(ファイル名は id)に書き込んで終了。
何となく getopt_long を使いたかったので、mysql のユーザ、パスワード、ホストをオプションで取る。
というプログラム。のつもり。
#include <stdlib.h> /* for exit(), free() */
#include <stdio.h> /* for printf(), sprintf(), fwrite() */
#include <string.h> /* for strdup() */
#include <getopt.h> /* for getopt_long() */
#include <mysql/mysql.h>
#define DB "saycheese"
#define PORT 3306
#define SOCKET "/var/lib/mysql/mysql.sock"
#define OPT 0
char *host;
char *user;
char *password;
/* prototypes */
void options_parse(int argc, char *argv[]);
int main(int argc, char *argv[]) {
options_parse(argc, argv);
int count = 0;
MYSQL *mysql;
MYSQL_RES *res;
MYSQL_ROW row;
mysql = mysql_init(NULL);
if (!mysql_real_connect(mysql, host, user, password, DB, PORT, SOCKET, OPT)) {
printf("ERROR %d: %s)\n", mysql_errno(mysql), mysql_error(mysql));
exit(-1);
}
char *sql =
"SELECT id, created_on, modified_on, url, extension, small FROM thumbnail LIMIT 10";
mysql_query(mysql, sql);
res = mysql_store_result(mysql);
for (count = mysql_num_rows(res); count > 0; count--) {
/* for fwrite() secend argument 'length' */
row = mysql_fetch_row(res);
unsigned int length = ((unsigned long *)mysql_fetch_lengths(res))[5];
/* open file and write it down */
FILE *fp;
char filename[256];
sprintf(filename, "%s.%s", row[0], row[4]);
if ((fp = fopen(filename, "w+")) == NULL) {
printf("Can't open %s\n", filename);
} else {
fwrite(row[5], length, 1, fp);
fclose(fp);
}
}
mysql_close(mysql);
mysql_free_result(res);
/* for strdup(host|user|password) in options_parse() */
if (host) free(host);
if (user) free(user);
if (password) free(password);
return 0;
}
void options_parse(int argc, char *argv[]) {
static struct option longopts[] = {
{"host", required_argument, NULL, 'h'},
{"user", required_argument, NULL, 'u'},
{"password", required_argument, NULL, 'p'},
{0, 0, 0, 0}
};
int opt;
while (1) {
opt = getopt_long(argc, argv, "h:u:p:", longopts, NULL);
if (opt == -1) break;
switch (opt) {
case 'h':
host = strdup(optarg);
break;
case 'u':
user = strdup(optarg);
break;
case 'p':
password = strdup(optarg);
break;
}
}
}
コンパイル、実行。
[travail@mina]~/c% gcc saycheese.c -o saycheese /tmp/ccsfFlXE.o: In function `main': saycheese.c:(.text+0x35): undefined reference to `mysql_init' saycheese.c:(.text+0x80): undefined reference to `mysql_real_connect' saycheese.c:(.text+0x8f): undefined reference to `mysql_error' saycheese.c:(.text+0x9c): undefined reference to `mysql_errno' saycheese.c:(.text+0xd5): undefined reference to `mysql_query' saycheese.c:(.text+0xe0): undefined reference to `mysql_store_result' saycheese.c:(.text+0xee): undefined reference to `mysql_num_rows' saycheese.c:(.text+0x101): undefined reference to `mysql_fetch_row' saycheese.c:(.text+0x10f): undefined reference to `mysql_fetch_lengths' saycheese.c:(.text+0x1c3): undefined reference to `mysql_close' saycheese.c:(.text+0x1ce): undefined reference to `mysql_free_result' collect2: ld はステータス 1 で終了しました
「終了しました」とか言われてもよくわからないので「"undefined reference to" mysql_init」でグーグルさんに訊ねてみる。
4.1 向けのリファレンスだけど、「リンク時に libmysqlclient.so へのパスを教えてあげてね」とのこと。
どうもこれっぽいので、改めてコンパイル、実行。
[travail@mina]~/c% gcc saycheese.c -o saycheese -L/usr/lib/mysql -lmysqlclient [travail@mina]~/c% ./saycheese -u travail -p ******* -h 192.168.1.1 [travail@mina]~/c% ls 10.jpg 13.jpg 16.jpg 9.jpg libmemcached* saycheese.c 11.jpg 14.jpg 6.jpg hello_world* libmemcached.c 12.jpg 15.jpg 8.jpg hello_world.c saycheese* [travail@mina]~/c% ./saycheese -u travail -p ******* ERROR 1049: Unknown database 'saycheese') [travail@mina]~/c% ./saycheese -u travail ERROR 1045: Access denied for user 'travail'@'localhost' (using password: NO)) [travail@mina]~/c% ./saycheese ERROR 1045: Access denied for user 'travail'@'localhost' (using password: NO))
できたっぽい。
ちゃんと mysql のエラーも取れてるみたい。
ちょっと気になるのは -u でユーザを指定しなくても travail で DB につなぎに行っているところ。
mysql_real_connect の引数で user が NULL はまたは "" であった場合は現在のユーザを想定するって。
ちなみに、host が NULL もしくは、"" だったら localhost にするって。
詳しくは Web で。
Perl で言う青本みたいなリファレンスってないんですかね?
「あぁ、こんな関数(マクロ)があるのか」なんて思って使ってみようとしてもヘッダを include してないからエラーが出たり。
それをいちいちグーグルさんに訊ねるのも煩わしいので。
今だけですかね?そのうち覚えますかね?
あと、ソースで「ここ変」とか「その書き方冗長」とかありますかね?
- Newer: 2月22日の音楽のこと
- Older: ノートブック
Comments:2
- shot 2008年2月25日 15:21
wxWidgetsいいよ!wxWidgetsサイコー!
- さわ 2008年2月25日 23:14
> shot さん
何?GUI?
Trackbacks:0
- TrackBack URL for this entry
- http://hibinokoto.jp/mt/mt-tb.cgi/252
- Listed below are links to weblogs that reference
- C はじめました - hello_world.c from 日々のこと