GLUTでウィンドウを開く

OpenGLはSilicon Graphics社が開発したOSに依存しない三次元のグラフィックスライブラリ
AUXライブラリを改良したものがGLUT
※LinuxやMacintoshではMesaの上にAUXライブラリやGLUTが移植されている

freeglut

### GLUTインストール
$ sudo apt-get install freeglut3 freeglut3-dev

#include <GL/glut.h>

void display(void){

}

int main(int argc, char *argv[]){
	glutInit(&argc, argv);  // GLUTおよびOpenGL環境を初期化。引数がある時はこの後処理
	glutCreateWindow(argv[0]); // windowを開く、以降描画は開いたウィンドウに対して行われる
	glutDisplayFunc(display); // ウィンドウ内に描画するポインタ
	glutMainLoop(); // 無限ループ、イベントの待ち受け
	return 0;
}

mac vagrantでGLUTのGUIの立ち上げ方法

VagrantでGULTのGUIが立ち上がらない

#include <GL/glut.h>

void display(void){

}

int main(int argc, char *argv[]){
	glutInit(&argc, argv);
	glutCreateWindow(argv[0]);
	glutDisplayFunc(display);
	glutMainLoop();
	return 0;
}

$ ./app
freeglut (./app): failed to open display ”

1.一旦ログアウトしてvagrantを止めます。

$ exit
$ vagrant halt

2. Vagrantfileにssh.forward_x11を追記します。

Vagrantfile

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/bionic64"
  config.vm.network "private_network", ip: "192.168.33.10"
  config.ssh.forward_x11 = true // 追加
end

https://www.vagrantup.com/docs/vagrantfile/ssh_settings.html
config.ssh.forward_x11 (boolean) – If true, X11 forwarding over SSH connections is enabled. Defaults to false.

X Window Systemとは、UNIX系OSで標準的に用いられるウィンドウシステム。

XQuartzをダウンロード
-> MacユーティリティでXQuartzを起動し、terminalから再度実行

$ ./app
libGL error: No matching fbConfigs or visuals found
libGL error: failed to load driver: swrast
X Error of failed request: GLXBadContext
Major opcode of failed request: 149 (GLX)
Minor opcode of failed request: 6 (X_GLXIsDirect)
Serial number of failed request: 43
Current serial number in output stream: 42
X Error of failed request: BadValue (integer parameter out of range for operation)
Major opcode of failed request: 149 (GLX)
Minor opcode of failed request: 24 (X_GLXCreateNewContext)
Value in failed request: 0x0
Serial number of failed request: 42
Current serial number in output stream: 43

$ sudo ldconfig -p | grep -i gl.so
libwayland-egl.so.1 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libwayland-egl.so.1
libwayland-egl.so (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libwayland-egl.so
libOpenGL.so.0 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libOpenGL.so.0
libOpenGL.so (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libOpenGL.so
libGL.so.1 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libGL.so.1
libGL.so (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libGL.so
libEGL.so.1 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libEGL.so.1
libEGL.so (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libEGL.so

あれ、何故だーーーーーーーーーー
色々検索していたところ、同じ解決方法を発見
https://unix.stackexchange.com/questions/429760/opengl-rendering-with-x11-forwarding

Try the following: 1) ensure you are running up-to-date Xquartz. 2) in a terminal, defaults write org.macosforge.xquartz.X11 enable_iglx -bool true 3) restart xquartz. This worked for me to get a simple java app running. I tried "glxgears" and it starts, but the gears don't turn. I presume they're supposed to

mac側のterminalでX11をenableにする。
$ defaults write org.macosforge.xquartz.X11 enable_iglx -bool true

再度XQuartzでsshログイン
$ ./app

立ち上がったーーーーーーーーーーーー

C言語でジャンケンゲームを作る

1.ジャンケンゲームはランダム関数でrand() % 3 + 1; としてグーチョキパーを出す。
2.srand((unsigned int)time(NULL));でランダム関数を初期化する

#include <stdio.h>
#include <stdlib.h> // rand()に必要

int main(void){
	int n, r;
	printf("ジャンケン....\n");
	printf("1.グー、2.チョキ、3.パー [数字を入力してください]\n");
	scanf("%d", &n);
	switch(n){
		case 1:
			printf("グー\n");
			break;
		case 2:
			printf("チョキ\n");
			break;
		case 3:
			printf("パー\n");
			break;
		default:
			printf("1〜3の何れかを入力してください。\n");
			return 1;
	}	

	srand((unsigned int)time(NULL));
	r = rand() % 3 + 1;

	switch(r){
		case 1:
			printf("相手はグー\n\n");
			break;
		case 2:
			printf("相手はチョキ\n\n");
			break;
		case 3:
			printf("相手はパー\n\n");
			break;
	}
	switch(n){
		case 1:
			switch(r){
				case 1:
					printf("あいこです。\n");
					break;
				case 2:
					printf("あなたの勝ちです。\n");
					break;
				case 3:
					printf("あなたの負けです。\n");
					break;
			}
			break;
		case 2:
			switch(r) {
				case 1:
					printf("あなたの負けです。\n");
					break;
				case 2:
					printf("あいこです。\n");
					break;
				case 3:
					printf("あなたの勝ちです。\n");
					break;
			}
			break;				
		case 3:
			switch(r) {
				case 1:
					printf("あなたの勝ちです。\n");
					break;
				case 2:
					printf("あなたの負けです。\n");
					break;
				case 3:
					printf("あいこです。\n");
					break;
			}
			break;
	}

	return 0;
}

$ ./app
ジャンケン….
1.グー、2.チョキ、3.パー [数字を入力してください]
1
グー
相手はチョキ

あなたの勝ちです。
$ ./app
ジャンケン….
1.グー、2.チョキ、3.パー [数字を入力してください]
3
パー
相手はパー

あいこです。

一応できたけど、勝ち負けの判定をswitch文の入れ子にすると冗長になるな。。
他の方がどうやって書いているか見てみると、、、
あ、swtichではなく、以下の条件式で収まるじゃん。。。
if (r == n) : あいこ
elseif (r – n == 1 || r – n == -2) : あなたの勝ち
else : 負け

C言語 + Ubuntu18.04でGUIを作りたい

C言語でもGUIを自由に作れれば、C言語のロジックをコーディングすれば、ほぼC言語でもアプリケーションを作れるようになるのでは? という事で、C言語のGUIについて考えたい。

GUIライブラリはOSによって異なる
– WindowsはWindows API や、GUIライブラリ
– LinuxはLinux GUI アプリ
– Android, iOSはCを使うアプリから

### UbuntuのGUI
– GUIツールキットにGTK+2.0を使用する
– GIMP, Gnome, Mozilla FirfoxなどはGTK+を使用して作られた

GTK+とは?
クロスプラットフォームのウィジェット・ツールキット(GUIツールキット)
gtk.org

### GTK+, Gladeのインストール
$ sudo apt-get install libgtk2.0-dev glade
$ pkg-config –cflags gtk+-2.0  // gtkを使うのに必要なものを表示
-pthread -I/usr/include/gtk-2.0 -I/usr/lib/x86_64-linux-gnu/gtk-2.0/include -I/usr/include/gio-unix-2.0/ -I/usr/include/cairo -I/usr/include/pango-1.0 -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/pixman-1 -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/libpng16 -I/usr/include/pango-1.0 -I/usr/include/harfbuzz -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/freetype2 -I/usr/include/libpng16

$ gcc -o gtk window.c
window.c:1:10: fatal error: gtk/gtk.h: No such file or directory
#include
^~~~~~~~~~~
compilation terminated.

うーむ、なんか上手くいかんな。

$ gcc -o gtk window.c `pkg-config –cflags –libs gtk+-2.0`
$ ./gtk
(gtk:17204): Gtk-WARNING **: 02:38:25.145: cannot open display:

何故だ。
というか、GTKで開発ってしないのか?

C言語でMySQLにinsertする書き方

sql_strの箇所をselectからinsert文に変えるだけです。update, deleteも一緒です。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mysql/mysql.h>

int main(){
	MYSQL *conn = NULL;
	MYSQL_RES *resp = NULL;
     // MYSQL_ROW row;
	char sql_str[255];
	char *sql_serv = "localhost";
	char *user = "root";
	char *passwd = "hogehoge";
	char *db_name = "test";

	memset( &sql_str[0], 0x00, sizeof(sql_str));

	conn = mysql_init(NULL);
	if(!mysql_real_connect(conn, sql_serv, user, passwd, db_name, 0, NULL, 0)){ 
		 exit(-1);
	}

	snprintf(&sql_str[0], sizeof(sql_str)-1, "insert into test (id,name) values (4, 'ddd')"); 
	if(mysql_query(conn, &sql_str[0])){ 
		mysql_close(conn);
		exit(-1);
	}

	mysql_free_result(resp);
	mysql_close(conn);

	return 0;
}

### コンパイル&実行
$ gcc -Wall -o dev hello.c -lmysqlclient -L/usr/lib/x86_64-linux-gnu/
$ ./dev

### 動作確認
mysql> select * from test;
+——+——+
| id | name |
+——+——+
| 1 | aaa |
| 2 | bbb |
| 3 | ccc |
| 4 | ddd |
+——+——+
4 rows in set (0.00 sec)

なるほど、DBとの接続はわかった。次はGUIか。

C言語でMySQLのレコードからSelectする方法

### ソースコード

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mysql/mysql.h>

int main(){
	MYSQL *conn = NULL;
	MYSQL_RES *resp = NULL;
	MYSQL_ROW row;
	char sql_str[255];
	char *sql_serv = "localhost";
	char *user = "root";
	char *passwd = "hogehoge";
	char *db_name = "test";

	memset( &sql_str[0], 0x00, sizeof(sql_str)); // memsetはメモリに指定バイト数分の値をセット, 0x00はヌル文字

	conn = mysql_init(NULL);
	if(!mysql_real_connect(conn, sql_serv, user, passwd, db_name, 0, NULL, 0)){ // サーバ接続開始 mysql_real_connect(mysql, host, user,passwd,db, port,  unix_socket, client_flag)
		 exit(-1);
	}

	// クエリ実行
	snprintf(&sql_str[0], sizeof(sql_str)-1, "select * from test");  // snprintfは指定文字数分だけ文字配列に書き込む
	if(mysql_query(conn, &sql_str[0])){  // sql_str によって指示される SQL ステートメントを実行
		mysql_close(conn);
		exit(-1);
	}

	// レスポンス
	resp = mysql_use_result(conn);  // 結果セットの取得を開始
	while((row = mysql_fetch_row(resp)) != NULL){   // 結果を添字配列として取得する
		printf("%d: %s\n", atoi(row[0]), row[1]);
	}

	mysql_free_result(resp);  // 結果保持用メモリを開放
	mysql_close(conn); // MySQL 接続を閉じる

	return 0;
}

### ライブラリのlibmysqlclient.soの配置場所を確認
$ find / -name “libmysqlclient.so”
/usr/lib/x86_64-linux-gnu/libmysqlclient.so

### コンパイル、実行
// -Wは警告メッセージ抑制, -Lはオブジェクトライブラリ
$ gcc -Wall -o dev hello.c -lmysqlclient -L/usr/lib/x86_64-linux-gnu/
$ ./dev
1: aaa
2: bbb
3: ccc

おいおい、マジかよ。。。
感動した。

C言語でmysqlを使う前準備

### MySQLにデータ挿入
$ mysql -u root -p
> use test;
> create table test(id int,name varchar(256));
> insert into test(id,name) values(1,”aaa”);
> insert into test(id,name) values(2,”bbb”);
> insert into test(id,name) values(3,”ccc”);
> select * from test;

### ubuntu18.04にmysql/mysql.hが入っているか確認
hello.c

#include <stdio.h>
#include <mysql/mysql.h>


int main(){

	return 0;
}

$ gcc -o dev hello.c
hello.c:2:10: fatal error: mysql/mysql.h: No such file or directory
#include
^~~~~~~~~~~~~~~
compilation terminated.
-> 入っていない

### libmysqlclient-devをインストール
$ sudo apt-get -y install libmysqlclient-dev
$ gcc -o dev hello.c
-> 無事コンパイル

trustyのlibmysqlclient-dev.installのgithub見たが、includeしてるって事か?

usr/include/mysql/*.h
usr/include/mysql/mysql/*.h
usr/include/mysql/mysql/*.h.pp
usr/include/mysql/mysql/psi/*.h
usr/lib/*/libmysqlclient.a
usr/lib/*/libmysqlclient.so
usr/lib/*/libmysqlservices.a
usr/bin/mysql_config
usr/bin/mysql_config_editor
usr/share/man/man1/mysql_config.1
usr/share/man/man1/mysql_config_editor.1
# legal
usr/share/doc/libmysqlclient-dev/COPYING
usr/share/doc/libmysqlclient-dev/README

.aファイルはStaticライブラリの事らしい。
あまり見ないな。

Ubuntu18.04 mysql5.7でAccess denied for user ‘root’@’localhost’

ubuntu18.04でtasksel install lamp-serverでmysqlを入れ、パスワードの設定をしたが、アクセスできない時

$ sudo mysql -u root
mysql> update user set authentication_string=password(“password”) where User=’root’;
$ mysql -u root -p
Enter password:
ERROR 1698 (28000): Access denied for user ‘root’@’localhost’

むむむむ?

MySQL 5.7では認証にauth_socket plugin(MySQL :: Security in MySQL :: 6.1.11 Socket Peer-Credential Pluggable Authentication) というものを使っていて、これを使っているとパスワードではアクセスできず、MySQLのユーザー名と、システムのユーザー名が一致しているときのみアクセスできる

mysql> SELECT User, Host, plugin FROM mysql.user;
+——————+———–+———————–+
| User | Host | plugin |
+——————+———–+———————–+
| root | localhost | auth_socket |
| mysql.session | localhost | mysql_native_password |
| mysql.sys | localhost | mysql_native_password |
| debian-sys-maint | localhost | mysql_native_password |
+——————+———–+———————–+
4 rows in set (0.00 sec)

mysql> UPDATE user SET plugin=’mysql_native_password’ WHERE User=’root’;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0

mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)

$ mysql -u root -p

C言語でfreeコマンドを書きたい

メモリを調べるにはfree, top, ps, vmstat, /proc/meminfoなどがある

$ free
total used free shared buff/cache available
Mem: 1008620 312640 186604 2200 509376 542844
Swap: 0 0 0

– 単位はバイト
– メモリ8Gのマシンなら、8G

■freeコマンドの項目
total: 全メモリ
free: 全く利用されていないメモリ
buff/cache: キャッシュとして利用されているけど、解放できる可能性のあるメモリ
used: = total – free – buff/cache

■swapとは
メモリ-の一部をディスク(HDDなど)に退避させて計算を続ける事ができる。この様にしてメモリ-の容量を実際よりも大きく見せるメカニズムを仮想メモリという。そのためにディスクにメモリを退避させるための領域をswapという

メモリ消費量を見積もるには /proc/pid/status の VmHWM

#include <stdio.h>


int main(){

	char command[128];

	sprintf(command, "grep VmHWM /proc/%d/status", getpid()); // getpid():プロセスのIDを知る
	system(command);

	return 0;
}

$ ./dev
VmHWM: 720 kB

■物理メモリ使用量の調べ方
$ ps
PID TTY TIME CMD
459 pts/0 00:00:00 bash
687 pts/0 00:00:00 bash
2490 pts/0 00:00:00 bash
4458 pts/0 00:00:00 ps
18043 pts/0 00:00:00 dev
18140 pts/0 00:00:00 dev
18499 pts/0 00:00:00 dev
18505 pts/0 00:00:00 dev
32396 pts/0 00:00:00 bash
32437 pts/0 00:00:00 bash
32556 pts/0 00:00:00 bash
32600 pts/0 00:00:00 bash

$ cat /proc/18043/status
Name: dev
Umask: 0002
State: T (stopped)
Tgid: 18043
Ngid: 0
Pid: 18043
PPid: 2490
TracerPid: 0
Uid: 1000 1000 1000 1000
Gid: 1000 1000 1000 1000
FDSize: 256
Groups: 1000
NStgid: 18043
NSpid: 18043
NSpgid: 18043
NSsid: 2490
VmPeak: 4508 kB
VmSize: 4508 kB
VmLck: 0 kB
VmPin: 0 kB
VmHWM: 704 kB
VmRSS: 700 kB
RssAnon: 60 kB
RssFile: 640 kB
RssShmem: 0 kB
VmData: 176 kB
VmStk: 132 kB
VmExe: 4 kB
VmLib: 2112 kB
VmPTE: 56 kB
VmSwap: 0 kB
HugetlbPages: 0 kB
CoreDumping: 0
Threads: 1
SigQ: 0/3838
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000000000000
SigCgt: 0000000000000000
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: 0000003fffffffff
CapAmb: 0000000000000000
NoNewPrivs: 0
Seccomp: 0
Speculation_Store_Bypass: vulnerable
Cpus_allowed: 3
Cpus_allowed_list: 0-1
Mems_allowed: 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000001
Mems_allowed_list: 0
voluntary_ctxt_switches: 3
nonvoluntary_ctxt_switches: 2

less, more, cat, tailの違い

cat
L 標準出力

more
L ファイル末尾まで行くと終了

less
L ファイル内容を閲覧、 qで終了

tail
L ファイル末尾だけ表示

実際にコマンドを打って確認しましょう。
$ cat hello.c
$ more hello.c
$ less hello.c

lessだと次の操作に移るのに[q]を打たないといけないので、catの方を多用していますが、行が長いファイルをじっくり確認したい場合はlessの方が使いやすい、と言ってる方もいます。