FIFOを使ってGNUPLOTとデータを送受信する (Perl)

みんなが作った便利な関数やサンプルを共有するコミュニティです。
[url]http://www.activebasic.com/forum/viewforum.php?f=2]ActiveBasicの「実践コードモジュール」[/url]的な感じでやりましょう。
フォーラム(掲示板)ルール
・投稿するコードはできるだけ一つ、もしくは一つの関数を補助する複数の関数の形式にするか、
それだけをコンパイルして動くソースコード一式の形にしてください。
記事には説明だけを書き、コードは添付ファイルにしてもかまいません。
・使い方などの説明も書いてください。
環境に依存するコードの場合は、対象の環境も書いてください。
・使用条件(ライセンスなど)も書いていただけるとありがたいです。
・C言語、もしくはC++推奨ですが、他の言語でもかまいません。
・コードは正しくcodeタグで囲みましょう。
・一つのスレッドで一つのサンプルが基本です。
関連するサンプルの場合はまとめてもかまいません。
・投稿したサンプルを修正する場合には、スレッドの返信の形で投稿してください。
(新しいスレッドにしないでください。記事の編集でもかまいません)
返信
アバター
みけCAT
記事: 6036
登録日時: 7年前
住所: 千葉県
連絡を取る:

FIFOを使ってGNUPLOTとデータを送受信する (Perl)

#1

投稿記事 by みけCAT » 3年前

FIFO(名前付きパイプ)を用いて、(通常の)一時ファイルを用いずにGNUPLOTにプロットするデータを渡し、描画結果を取得します。
Windowsでは動かないかもしれません。
Raspberry Pi 2 Model B上のRaspbian GNU/Linux 7 (/etc/debian_version = 7.8) で動作確認しました。

CGI形式にしてみました。
セキュリティはあまり考えていません。
動作する状態でインターネットへ公開する際は自己責任です。

コード:

#!/usr/bin/perl

use strict;
use POSIX;

my $raw_data = '';
if ($ENV{'REQUEST_METHOD'} eq 'POST') {
	while (<STDIN>) { $raw_data .= $_; }
} else {
	$raw_data = $ENV{'QUERY_STRING'};
}
my @split_data = split(/&/, $raw_data);
my %query_data = {};
for (my $i = 0; $i < @split_data; $i++) {
	my ($key, $value) = split(/=/, $split_data[$i], 2);
	$value =~ s/\+/ /g;
	$value =~ s/%([0-9a-fA-F]{2})/pack('C', hex($1))/eg;
	$query_data{$key} = $value;
}

if ($query_data{'data'} ne '') {
	my $data_fifo = "/tmp/data_";
	my $img_fifo = "/tmp/img_";
	srand;
	for (my $i = 0; $i < 32; $i++) {
		$data_fifo .= chr(ord('a') + int(rand() * 26));
		$img_fifo .= chr(ord('a') + int(rand() * 26));
	}

	my $script = <<EOS;
set terminal pngcairo
set output "$img_fifo"
unset key
plot "$data_fifo"
exit
EOS

	mkfifo($data_fifo, 0600) or die "mkfifo error\n";
	unless (mkfifo($img_fifo, 0600)) {
		unlink($data_fifo);
		die "mkfifo error\n";
	}

	my $pid1 = fork();
	if ($pid1 == -1) {
		unlink($data_fifo);
		unlink($img_fifo);
		die "fork error\n";
	}
	if ($pid1 == 0) {
		open(DATA, "> $data_fifo") or die "data open error\n";
		my $send_data = $query_data{'data'};
		$send_data =~ s/,/ /g;
		print DATA $send_data;
		close(DATA);
		exit;
	}

	my $pid2 = fork();
	if ($pid2 == -1) {
		unlink($data_fifo);
		unlink($img_fifo);
		die "fork error 2\n";
	}
	if ($pid2 == 0) {
		open(GP, "| gnuplot > /dev/null 2>&1") or die "gnuplot open error\n";
		print GP $script;
		close(GP);
		exit;
	}

	unless (open(IMG, "< $img_fifo")) {
		unlink($data_fifo);
		unlink($img_fifo);
		die "img open error\n";
	}
	binmode(IMG);
	my $image_data = '';
	while (<IMG>) { $image_data .= $_; }
	close(IMG);
	
	waitpid($pid1, 0);
	waitpid($pid2, 0);

	unlink($data_fifo);
	unlink($img_fifo);

	print "Content-type: image/png\n\n";
	binmode(STDOUT);
	print $image_data;
} else {
	print <<EOS;
Content-type: text/html;charset=UTF-8

<html lang="ja">
<head>
<meta charset="UTF-8">
<title>GNUPLOTテスト</title>
</head>
<body>
<h2>GNUPLOTテスト</h2>
<p>データは、横軸の値と縦軸の値をこの順番で1行に1組ずつ半角空白、タブ、もしくはコンマ区切りで入力してください。</p>
<form method="POST" action="./" target="_blank">
<p><textarea name="data" cols="30" rows="20" placeholder="データを入力"></textarea></p>
<p><input type="submit" value="描画"></p>
</form>
<hr>
<p><a href="../">戻る</a></p>
</body>
</html>
EOS
}
添付はCGI版と非CGI版です。

仕様、改造、再配布など自由にどうぞ。
添付ファイル
gnuplot_test.zip
ソースコード
(2.22 KiB) ダウンロード数: 98 回
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

返信

“サンプルを共有するコミュニティ” へ戻る