Subscribe to RSS Feed ログイン

オーガニック・ウェルス

Thursday
2012年2月23日

Rustから自作共有ライブラリを呼び出す

Rustから呼び出せる共有ライブラリを作成する方法をまとめます。コンパイラにはgccを使用します。

<myfunc.h>

void sumTotal (int num);

<myfunc.c>

#include <stdio.h>
#include "myfunc.h"

void sumTotal (int num)
{
	int sum = 0, i;
	for (i = 1; i <= num; i++) {
		sum = sum + i;
	}
	printf("sum = %d\n", sum);
}

上記ファイルからライブラリファイルを生成します。


$ gcc -shared myfunc.c -o libmyfunc.so
$ sudo cp libmyfunc.so /usr/local/lib/rustc/i686-unknown-linux-gnu/lib/

ライブラリを用意したら次はRustのプログラムを作成します。

<main.rs>

use std;
#[link_name = "myfunc"]
native mod myfunc {
  fn sumTotal(arg :ctypes::c_int);
}
fn main(){
	myfunc::sumTotal(10);
	myfunc::sumTotal(20);
	myfunc::sumTotal(30);
}

いつもと同じようにコンパイルします。

$ rustc main.rs
$ ./main

実行結果

sum = 55
sum = 210
sum = 465

そこまで難しいことはしないので良かったです。

参考:

gccを用いたCの共有ライブラリの作り方 – 睡眠不足?!

11.1 Native modules

コメント(0)続きを読む

Rust Languageに手を出してみた

Rust a safe, concurrent, practical language

先日「Rust」という新しいプログラミング言語が公開されましたので早速使って見ました。Rustは実行する前にコンパイルをしネイティブの実行ファイルを生成します。

環境はUbuntu 11.10です。


$ sudo apt-get install g++ curl
$ wget http://dl.rust-lang.org/dist/rust-0.1.tar.gz
$ tar xvf rust-0.1.tar.gz
$ cd rust-0.1.tar.gz
$ ./configure
$ make
$ make install

以上で環境構築は終了です。以下のコードを実行してみます。

<hello.rs>

use std;
import std::io;

fn main() {
    for i in [1, 2, 3] {
        io::println(#fmt("hello %d\n", i));
    }
}

 

$ rustc hello.rs
$ ./hello

実行結果

hello 1

hello 2

hello 3

$ ldd hello

	linux-gate.so.1 =>  (0x00c0b000)
	libcore-14bd852465126fe7-0.1.so => /home/user/Programs/rust/./../../../../usr/local/lib/rustc/i686-unknown-linux-gnu/lib/libcore-14bd852465126fe7-0.1.so (0x004a9000)
	libstd-79ca5fac56b63fde-0.1.so => /home/user/Programs/rust/./../../../../usr/local/lib/rustc/i686-unknown-linux-gnu/lib/libstd-79ca5fac56b63fde-0.1.so (0x0098f000)
	librustrt.so => /home/user/Programs/rust/./../../../../usr/local/lib/rustc/i686-unknown-linux-gnu/lib/librustrt.so (0x00b6a000)
	libgcc_s.so.1 => /lib/i386-linux-gnu/libgcc_s.so.1 (0x007e7000)
	libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0x00182000)
	libm.so.6 => /lib/i386-linux-gnu/libm.so.6 (0x0051a000)
	librt.so.1 => /lib/i386-linux-gnu/librt.so.1 (0x0071d000)
	libdl.so.2 => /lib/i386-linux-gnu/libdl.so.2 (0x00110000)
	libpthread.so.0 => /lib/i386-linux-gnu/libpthread.so.0 (0x00f40000)
	libstdc++.so.6 => /usr/lib/i386-linux-gnu/libstdc++.so.6 (0x002fe000)
	/lib/ld-linux.so.2 (0x00d87000)

どうやら実行ファイルにRustのライブラリを読み込んでいるようです。この実行ファイルは約16KBとなっています。

objdump -S hello > hello.dump

hello:     file format elf32-i386
~
08048b10 <rust_start@plt>:
 8048b10:	ff 25 2c c0 04 08    	jmp    *0x804c02c
 8048b16:	68 58 00 00 00       	push   $0x58
 8048b1b:	e9 30 ff ff ff       	jmp    8048a50 <_init+0x38>
~
08048b50 <_start>:
 8048b50:	31 ed                	xor    %ebp,%ebp
 8048b52:	5e                   	pop    %esi
 8048b53:	89 e1                	mov    %esp,%ecx
 8048b55:	83 e4 f0             	and    $0xfffffff0,%esp
 8048b58:	50                   	push   %eax
 8048b59:	54                   	push   %esp
 8048b5a:	52                   	push   %edx
 8048b5b:	68 00 9d 04 08       	push   $0x8049d00
 8048b60:	68 90 9c 04 08       	push   $0x8049c90
 8048b65:	51                   	push   %ecx
 8048b66:	56                   	push   %esi
 8048b67:	68 a0 97 04 08       	push   $0x80497a0
 8048b6c:	e8 4f ff ff ff       	call   8048ac0 <__libc_start_main@plt>
 8048b71:	f4                   	hlt
 8048b72:	90                   	nop
 8048b73:	90                   	nop
~

elf形式の実行ファイルを生成しています。

今回は以上です。

続きを読む »

コメント(0)続きを読む

Ubuntuでアセンブラを使ってみる

Ubuntuでアセンブラを始めて見ようと思ったのですが、存在する情報がVistualStudioのインラインアセンブラを前提にしたものばかりでそれ以外のアセンブラ(今回はnasm)での情報がほとんど有りません。

なのでまずC言語でコンパイルした実効ファイルを逆アセンブルしてアセンブルソースを読み解く方法で進めます。

まず以下のC言語のソースから実行ファイルを作成します。

<asmbase.c>

#include <stdio.h>
int add(int a, int b) {
    return a + b;
}
int sub(int a, int b) {
    return a - b;
}
int mul(int a, int b) {
    return a * b;
}
int div(int a, int b) {
    return a / b;
}
float fadd(float a, float b) {
    return a + b;
}
float fsub(float a, float b) {
    return a - b;
}
float fmul(float a, float b) {
    return a * b;
}
float fdiv(float a, float b) {
    return a / b;
}
int main() {
    int i1 = 20, i2 = 4, i3;
    float f1 = 1.5,f2 = 0.3,f3;

    i3 = add(i1, i2);
    printf("add(%d, %d)=%d\n", i1, i2, i3);
    i3 = sub(i1, i2);
    printf("sub(%d, %d)=%d\n", i1, i2, i3);
    i3 = mul(i1, i2);
    printf("mul(%d, %d)=%d\n", i1, i2, i3);
    i3 = div(i1, i2);
    printf("div(%d, %d)=%d\n", i1, i2, i3);

    f3 = fadd(f1, f2);
    printf("fadd(%f, %f)=%f\n", f1, f2, f3);
    f3 = fsub(f1, f2);
    printf("fsub(%f, %f)=%f\n", f1, f2, f3);
    f3 = fmul(f1, f2);
    printf("fmul(%f, %f)=%f\n", f1, f2, f3);
    f3 = fdiv(f1, f2);
    printf("fdiv(%f, %f)=%f\n", f1, f2, f3);
}


$ gcc -o asmbase asmbase.c
$ ./asmbase
add(20, 4)=24
sub(20, 4)=16
mul(20, 4)=80
div(20, 4)=5
fadd(1.500000, 0.300000)=1.800000
fsub(1.500000, 0.300000)=1.200000
fmul(1.500000, 0.300000)=0.450000
fdiv(1.500000, 0.300000)=5.000000

まずasmbaseという実行可能ファイルを作成しました。このファイルを解析します。


$ objdump -S asmbase

(一部抜粋)

~
0804842e <fadd>:
 804842e:	55                   	push   %ebp
 804842f:	89 e5                	mov    %esp,%ebp
 8048431:	d9 45 08             	flds   0x8(%ebp)
 8048434:	d8 45 0c             	fadds  0xc(%ebp)
 8048437:	5d                   	pop    %ebp
 8048438:	c3                   	ret
~

fadd()という関数だけ抜き出してみました。この状態だとAT&T形式(だっけか?)なのでINTEL形式で表示させ直します。私はこの表記の違いでつまづきました。

$ objdump -M intel -S asmbase

~
0804842e <fadd>:
 804842e:	55                   	push   ebp
 804842f:	89 e5                	mov    ebp,esp
 8048431:	d9 45 08             	fld    DWORD PTR [ebp+0x8]
 8048434:	d8 45 0c             	fadd   DWORD PTR [ebp+0xc]
 8048437:	5d                   	pop    ebp
 8048438:	c3                   	ret
~

2つまったく違う表記になりました。特にmovは順番が違います。もちろん意味としては一緒です。内容については詳しく説明できるほど知識が無く、説明できないくて申し訳ないです。

次にこれをもとにCとアセンブラコードを書きます。

<main.c>

#include <stdio.h>

// extern 宣言でアセンブラ内の関数を読み込む
extern int _add(int a, int b);
extern int _sub(int a, int b);
extern int _mul(int a, int b);
extern int _div(int a, int b);
extern float _fadd(float a, float b);
extern float _fsub(float a, float b);
extern float _fmul(float a, float b);
extern float _fdiv(float a, float b);

int main () {
	int i1 = 20, i2 = 4, i3;
	float f1 = 1.5,f2 = 0.3,f3;

	i3 = _add(i1, i2);
	printf("add(%d, %d)=%d\n", i1, i2, i3);
	i3 = _sub(i1, i2);
	printf("sub(%d, %d)=%d\n", i1, i2, i3);
	i3 = _mul(i1, i2);
	printf("mul(%d, %d)=%d\n", i1, i2, i3);
	i3 = _div(i1, i2);
	printf("div(%d, %d)=%d\n", i1, i2, i3);

	f3 = _fadd(f1, f2);
	printf("fadd(%f, %f)=%f\n", f1, f2, f3);
	f3 = _fsub(f1, f2);
	printf("fsub(%f, %f)=%f\n", f1, f2, f3);
	f3 = _fmul(f1, f2);
	printf("fmul(%f, %f)=%f\n", f1, f2, f3);
	f3 = _fdiv(f1, f2);
	printf("fdiv(%f, %f)=%f\n", f1, f2, f3);
    return 0;
}

<sub.s>

    bits 32
	global _add
	global _sub
	global _mul
	global _div
	global _fadd
	global _fsub
	global _fmul
	global _fdiv

    ;; start program area
    section .text

    ;; global functions

_add: ; 二つの引数を足す
    MOV		EDX,[ESP+4]
    ADD		EDX, [ESP+8]
    MOV		EAX, EDX
    RET

_sub: ; 二つの引数をかける
    MOV		EDX,[ESP+4]
    sub		EDX, [ESP+8]
    MOV		EAX, EDX
    RET

_mul: ; 二つの引数をかける
    MOV		eax,[ESP+4]
    mov		ebx,[ESP+8]
    mul		ebx
    RET

_div: ; 二つの引数をかける
    MOV		eax,[ESP+4]
    mov		ebx,[ESP+8]
    div		ebx
    RET

_fadd: ; 2つの実数を足す
	push	ebp
	mov		ebp, esp
	fld		DWORD [ebp+8]
	fadd	DWORD [ebp+12]
	pop		ebp
    RET

_fsub: ; 2つの実数を引く
	push	ebp
	mov		ebp, esp
	fld		DWORD [ebp+8]
	fsub	DWORD [ebp+12]
	pop		ebp
    RET

_fmul: ; 2つの実数を掛ける
	push	ebp
	mov		ebp, esp
	fld		DWORD [ebp+8]
	fmul	DWORD [ebp+12]
	pop		ebp
    RET

_fdiv: ; 2つの実数を割る
	push	ebp
	mov		ebp, esp
	fld		DWORD [ebp+8]
	fdiv	DWORD [ebp+12]
	pop		ebp
    RET

上記2つのコードをビルドします。

$ gcc -o main.o -c main.c
$ nasm -f elf32 -o sub.o sub.s
$ gcc -o main main.o sub.o
$ ./main

実行結果

add(20, 4)=24
sub(20, 4)=16
mul(20, 4)=80
div(20, 4)=5
fadd(1.500000, 0.300000)=1.800000
fsub(1.500000, 0.300000)=1.200000
fmul(1.500000, 0.300000)=0.450000
fdiv(1.500000, 0.300000)=5.000000

とCのソースからアセンブラのソースが呼び出せました。

コメント(0)続きを読む

PHPの処理の確かめスクリプト

PHPの処理系で分からない部分があったので確かめる処理を書いてみました。特に”0x0A”と”10″を単純に文字比較すると等しいと判定されるので注意が必要です。

実行環境はWindows7 PHP5.3.5です。

PHPのソース(SHIFT-JIS)

<?php
echo '"0x0A" == "10"'." => ".var_export("0x0A" == "10", true).PHP_EOL;
echo '"0x0A" === "10"'." => ".var_export("0x0A" === "10", true).PHP_EOL;
echo '"0x0A" == 10'." => ".var_export("0x0A" == 10, true).PHP_EOL;
echo '"0x0A" === 10'." => ".var_export("0x0A" === 10, true).PHP_EOL;
echo '10 == "10"'." => ".var_export(10 == "10", true).PHP_EOL;
echo '10 === "10"'." => ".var_export(10 === "10", true).PHP_EOL;
echo '10 == "a"'." => ".var_export(10 == "a", true).PHP_EOL;
echo '10 === "a"'." => ".var_export(10 === "a", true).PHP_EOL;
echo '"00" == "0"'." => ".var_export("00" == "0", true).PHP_EOL;
echo '"-0" == "00000"'." => ".var_export("-0" == "00000", true).PHP_EOL;
echo '"00" === "0"'." => ".var_export("00" === "0", true).PHP_EOL;
echo '"-0" === "00000"'." => ".var_export("-0" === "00000", true).PHP_EOL;
echo 'false == 0'." => ".var_export(false == 0, true).PHP_EOL;
echo 'NULL == 0'." => ".var_export(NUll == 0, true).PHP_EOL;
echo 'false === 0'." => ".var_export(false === 0, true).PHP_EOL;
echo 'NULL === 0'." => ".var_export(NUll === 0, true).PHP_EOL;
echo 'NULL == false'." => ".var_export(NUll == false, true).PHP_EOL;
echo 'NULL === false'." => ".var_export(NUll === false, true).PHP_EOL;
echo '$bool = false'.PHP_EOL;($bool = false);
echo 'isset($bool)'." => ".var_export(isset($bool), true).PHP_EOL;
echo '$bool = NULL'.PHP_EOL;($bool = NULL);
echo 'isset($bool)'." => ".var_export(isset($bool), true).PHP_EOL;
echo '$bool = 0'.PHP_EOL;($bool = 0);
echo 'isset($bool)'." => ".var_export(isset($bool), true).PHP_EOL;

echo PHP_EOL;

echo 'is_int(10)'." => ".var_export(is_int(10), true).PHP_EOL;
echo 'is_int("10")'." => ".var_export(is_int("10"), true).PHP_EOL;
echo 'is_string("10")'." => ".var_export(is_string("10"), true).PHP_EOL;
echo 'is_int(true)'." => ".var_export(is_int(true), true).PHP_EOL;
echo 'is_int(false)'." => ".var_export(is_int(false), true).PHP_EOL;
echo 'is_int("true")'." => ".var_export(is_int("true"), true).PHP_EOL;
echo 'is_int("false")'." => ".var_export(is_int("false"), true).PHP_EOL;
echo 'is_string(true)'." => ".var_export(is_string(true), true).PHP_EOL;
echo 'is_string(false)'." => ".var_export(is_string(false), true).PHP_EOL;
echo 'is_string("true")'." => ".var_export(is_string("true"), true).PHP_EOL;
echo 'is_string("false")'." => ".var_export(is_string("false"), true).PHP_EOL;
echo 'is_bool(true)'." => ".var_export(is_bool(true), true).PHP_EOL;
echo 'is_bool(false)'." => ".var_export(is_bool(false), true).PHP_EOL;
echo 'is_bool("true")'." => ".var_export(is_bool("true"), true).PHP_EOL;
echo 'is_bool("false")'." => ".var_export(is_bool("false"), true).PHP_EOL;
echo 'is_bool(0)'." => ".var_export(is_bool(0), true).PHP_EOL;
echo 'is_bool(1)'." => ".var_export(is_bool(1), true).PHP_EOL;
echo PHP_EOL;

echo '@is_int(A)'." => ".var_export(@is_int(A), true).PHP_EOL;
echo '@is_string(A)'." => ".var_export(@is_string(A), true).PHP_EOL;
echo PHP_EOL;

$str = '
$var = NULL;
if($var) $res = true;
else $res = false;
return $res;';
echo $str." => ".var_export(eval($str), true).PHP_EOL;

$str = '
$var = 0;
if($var) $res = true;
else $res = false;
return $res;';
echo $str." => ".var_export(eval($str), true).PHP_EOL;

$str = '
$var = 1;
if($var) $res = true;
else $res = false;
return $res;';
echo $str." => ".var_export(eval($str), true).PHP_EOL;

$str = '
$var = -1;
if($var) $res = true;
else $res = false;
return $res;';
echo $str." => ".var_export(eval($str), true).PHP_EOL;

$str = '
$var = "";
if($var) $res = true;
else $res = false;
return $res;';
echo $str." => ".var_export(eval($str), true).PHP_EOL;

$str = '
$var = array();
if($var) $res = true;
else $res = false;
return $res;';
echo $str." => ".var_export(eval($str), true).PHP_EOL;

$str = '
$var = array(1);
if($var) $res = true;
else $res = false;
return $res;';
echo $str." => ".var_export(eval($str), true).PHP_EOL;

echo PHP_EOL;

echo 'strlen("あいう")'." => ".var_export(strlen("あいう"), true).PHP_EOL;
echo 'mb_strlen("あいう")'." => ".var_export(mb_strlen("あいう"), true).PHP_EOL;

echo PHP_EOL;
echo 'mb_language("Japanese");'.PHP_EOL;
mb_language("Japanese");

echo 'strlen("あいう")'." => ".var_export(strlen("あいう"), true).PHP_EOL;
echo 'mb_strlen("あいう")'." => ".var_export(mb_strlen("あいう"), true).PHP_EOL;

echo PHP_EOL;
echo 'mb_internal_encoding("SHIFT-JIS");'.PHP_EOL;
mb_internal_encoding("SHIFT-JIS");

echo 'strlen("あいう")'." => ".var_export(strlen("あいう"), true).PHP_EOL;
echo 'mb_strlen("あいう")'." => ".var_export(mb_strlen("あいう"), true).PHP_EOL;

echo PHP_EOL;

echo '$str = "abc"'.PHP_EOL;$str = "abc";
echo '$str{0}'." => ".var_export($str{0}, true).PHP_EOL;
echo '$str = "あいう"'.PHP_EOL;$str = "あいう";
echo '$str{0}'." => ".var_export($str{0}, true).PHP_EOL;

echo PHP_EOL;

$str = "abcd";
echo 'unpack("C*", "'.$str.'") => '.var_export(unpack("C*", $str), true).PHP_EOL;

echo PHP_EOL;
echo 'pack("C*", 97, 98, 99, 100) => '.var_export(pack("C*", 97, 98, 99, 100), true).PHP_EOL;

echo PHP_EOL;
echo 'pack("C*", 97, 98, 0, 99, 100) => '.var_export(pack("C*", 97, 98, 0, 99, 100), true).PHP_EOL;

echo PHP_EOL;
$str = pack("C*", 97, 98, 0, 99, 100);
echo '$str = pack("C*", 97, 98, 0, 99, 100)'.PHP_EOL;
echo 'is_string($str) => '.var_export(is_string($str), true).PHP_EOL;
echo 'strlen($str) => '.var_export(strlen($str), true).PHP_EOL;
echo 'mb_strlen($str) => '.var_export(mb_strlen($str), true).PHP_EOL;
echo 'strstr($str, "\0") => '.var_export(strstr($str, "\0"), true).PHP_EOL;
echo 'unpack("C*", $str) => '.var_export(unpack("C*", $str), true).PHP_EOL;

 

echo 'str_replace("\0", "-", $str) => '.var_export(str_replace("\0", "-", $str), true).PHP_EOL;

実行結果


"0x0A" == "10" => true
"0x0A" === "10" => false
"0x0A" == 10 => true
"0x0A" === 10 => false
10 == "10" => true
10 === "10" => false
10 == "a" => false
10 === "a" => false
"00" == "0" => true
"-0" == "00000" => true
"00" === "0" => false
"-0" === "00000" => false
false == 0 => true
NULL == 0 => true
false === 0 => false
NULL === 0 => false
NULL == false => true
NULL === false => false
$bool = false
isset($bool) => true
$bool = NULL
isset($bool) => false
$bool = 0
isset($bool) => true

is_int(10) => true
is_int("10") => false
is_string("10") => true
is_int(true) => false
is_int(false) => false
is_int("true") => false
is_int("false") => false
is_string(true) => false
is_string(false) => false
is_string("true") => true
is_string("false") => true
is_bool(true) => true
is_bool(false) => true
is_bool("true") => false
is_bool("false") => false
is_bool(0) => false
is_bool(1) => false

@is_int(A) => false
@is_string(A) => true

$var = NULL;
if($var) $res = true;
else $res = false;
return $res; => false

$var = 0;
if($var) $res = true;
else $res = false;
return $res; => false

$var = 1;
if($var) $res = true;
else $res = false;
return $res; => true

$var = -1;
if($var) $res = true;
else $res = false;
return $res; => true

$var = "";
if($var) $res = true;
else $res = false;
return $res; => false

$var = array();
if($var) $res = true;
else $res = false;
return $res; => false

$var = array(1);
if($var) $res = true;
else $res = false;
return $res; => true

strlen("あいう") => 6
mb_strlen("あいう") => 6

mb_language("Japanese");
strlen("あいう") => 6
mb_strlen("あいう") => 6

mb_internal_encoding("SHIFT-JIS");
strlen("あいう") => 6
mb_strlen("あいう") => 3

$str = "abc"
$str{0} => 'a'
$str = "あいう"
$str{0} => '・

unpack("C*", "abcd") => array (
1 => 97,
2 => 98,
3 => 99,
4 => 100,
)

pack("C*", 97, 98, 99, 100) => 'abcd'

pack("C*", 97, 98, 0, 99, 100) => 'ab' . "\0" . 'cd'

 

$str = pack("C*", 97, 98, 0, 99, 100)
is_string($str) => true
strlen($str) => 5
mb_strlen($str) => 5
strstr($str, "\0") => '' . "\0" . 'cd'
unpack("C*", $str) => array (
1 => 97,
2 => 98,
3 => 0,
4 => 99,
5 => 100,
)
str_replace("\0", "-", $str) => 'ab-cd'

コメント(0)続きを読む

canvasタグの座標変換

下記のようなグラフを出力するのに座標変換を使って描画してみました。

function paint(){

    ctx.strokeStyle = “#333333″;

    ctx.lineWidth = 1;

    // X

    ctx.beginPath();

    ctx.moveTo(0, h / 2);

    ctx.lineTo(w, h / 2);

    ctx.stroke();

    // Y

    ctx.beginPath();

    ctx.moveTo(w / 2, 0);

    ctx.lineTo(w / 2, h);

    ctx.stroke();

    // CANVASの中心を(0,0)に指定

    ctx.setTransform(1, 0, 0, 1, w / 2, h / 2);

    ctx.textAlign = “right”;

    // 文字の傾き角度

    var deg = -80;

    var seata = deg * Math.PI / 180;

    ctx.rotate(seata);

    for(var i = -10;i <= 10;i += 1) {

        var y = 10;

        var x = i * 35;

        var d = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));

        var tan = Math.atan2(y, x);

        var x2 = d * Math.cos(tan - seata);

        var y2 = d * Math.sin(tan - seata);

        ctx.fillText(i.toFixed(1), x2, y2);

    }

    ctx.rotate(-seata);

    // Y座標を反転し、CANVASの中心を(0,0)に指定

    ctx.setTransform(1, 0, 0, -1, w / 2, h / 2);

    // グラフ描画

    ctx.beginPath();

    ctx.strokeStyle = “#ff6633″;

    for(var i = -10;i < 10;i += 0.01) {

        var y = i * i * 2.5;

        var x = i * 35;

        ctx.lineTo(x, y);

    }

    ctx.stroke();

}

グラフを出力するならば-Xから+Xの間の値を取れると楽なのでsetTransformの第5,6引数にて座標をずらします。そしてcanvasはもともと下方向に+Yが向いているので第4引数に-1を渡すことによって上方向を+Yにしています。setTransformを使用することによってグラフの座標処理を簡単にします。

またX軸の目盛りは文字を80度傾けています。傾けるといってもrotateでは描画すべてを傾けて描画するため、傾いたあとの補正する値を計算します。

サンプル

コメント(0)続きを読む

半導体の売り上げシェアをグラフにしてみた

Wikipediaにあります半導体メーカの売り上げを年毎にプロットしたグラフを作ってみました。

半導体メーカー売上高ランキング

まず1987年から1996年までのトップ10の売上高をグラフにしました。

1987年は上位をNEC、東芝、日立と日本企業が占めていました。1992年にIntelに首位を奪われてからは一度も奪還できていないばかりかさらに差をつけられてしまいます。

次は1994年から2002年の売り上げですが、完全にIntelに独走を許しており2位以下の企業は売り上げを伸ばすことができていませんでした。Intelの地位が確固たるものとなりました。

最後は2000年から2010年の売り上げです。Intelは変わらず首位をキープしていますが、背後にはサムスン電子の足跡が忍び寄ります。3位以下の企業は混戦状態で順位の変動が激しい状態です。

今までIntelはPCの売り上げによって支えられてきました。これからはスマートフォンの時代になりスマートフォン用のCPUを販売していないIntelにとっては不利なように見えますが、私にはそれは一要因でしかなく、どのようなソフトウェアがどのデバイスをサポートするかで変わると思っています。

今後も気になる分野です。

参考:

日本「半導体」の凋落とともに歩んだ技術者人生 世界シェア50%を誇った日本の半導体はどこへ

コメント(0)続きを読む

RubyでHTMLを解釈するライブラリ[Hpricot]を使う

環境CentOS

まずバージョンの確認

#cat /etc/redhat-release
CentOS release 5.5 (Final)
# ruby -v

ruby 1.8.7 (2011-06-30 patchlevel 352) [x86_64-linux] ←Rubyが1.8.7でなければアップデートする

#gem -v

1.3.7 ←rubygemsが1.3.7では無ければアップデートする

# yum remove ruby-libs
# wget ftp://ftp.ruby-lang.org/pub/ruby/1.8/ruby-1.8.7-p352.tar.gz
# tar xvf ruby-1.8.7-p352.tar.gz
# cd ruby-1.8.7-p352
# ./configure –prefix=/usr
# make
# make install
# wget http://rubyforge.org/frs/download.php/75308/rubygems-update-1.8.10.gem
# gem install rubygems-update-1.8.10.gem –local
# git clone git://github.com/thbar/hpricot.git
# cd hpricot
# ruby setup.rb

インストールが完了したのでこちらのサイトのようにHpricotを使えます。

ついでに、

Rubyをソースからインストールすると、Rails起動時にOpensslが無いと言われるのでOpenSSLをインストールします。

OpenSSLはRubyのソースフォルダにあります。

# cd ruby-1.8.7-p352/ext/openssl/
# ruby extconf.rb
# make
# make install

あと、SQLite3もインストール

# yum install sqlite-devel
# gem install sqlite3-ruby -v 1.2.5

コメント(0)続きを読む

PHP文字列型の不思議

<?php

    $str = ”abcあいう”;

    echo ”strlen=”.strlen($str).”\r\n”;

    echo ”mb_strlen=”.mb_strlen($str).”\r\n”;

    for($i=0;$i < strlen($str);$i++) {

        printf(“%d=%d(%s)\r\n”, $i, (int)$str[$i], $str[$i]);

    }

?>

上記のPHPを実行するとこうなりました。

strlen=12
mb_strlen=6
0=0(a)
1=0(b)
2=0(c)
3=0(・
4=0(・
5=0(・
6=0(・
7=0(・
8=0(・
9=0(・
10=0(・
11=0(・

文字の配列の配列がPHPでは文字型に成っているのか、中身は取り出せずじまいでした。

たんなる自分の実験ですが

コメント(0)続きを読む

CentOS5.5にPHP5.3.8をソースからインストール

# wget http://jp2.php.net/get/php-5.3.8.tar.bz2/from/this/mirror

# tar xvf php-5.3.8.tar.bz2

# cd php-5.3.8

# yum install -y libxml2
# yum install -y libxml2-devel
# yum install -y libpng-devel
# yum install -y libmcrypt
# yum install -y libmcrypt-devel
# yum install -y libtool-ltdl
# yum install -y libtool-ltdl-devel
# yum install -y httpd-devel

# ./configure --enable-mbstring \
 --enable-mbregex \
 --enable-zend-multibyte \
 --with-zlib-dir=/usr/lib \
 --with-apxs2=/usr/sbin/apxs \
 --with-zlib \
 --enable-zip \
 --enable-ftp \
 --enable-pcntl \
 --enable-soap \
 --with-mcrypt \
 --with-gd \
 --enable-pdo \
 --with-pear

# cp php.ini-development /usr/local/php/lib/php.ini

/etc/profileのパスに以下を追加
PATH=$PATH:/usr/local/php/bin/

# source /etc/profile

コメント(0)続きを読む

PHPのPack・UnPackで文字と数値の変換

<?php
$str = "字";
$byte_array = unpack("C*", $str);
echo "'$str'";
echo "\n↓\n";
var_dump($byte_array);

echo "packed => '".pack("C*", 229, 173, 151)."'\n";
?>

実行結果

'字'
↓
array(3) {
 [1]=>
 int(229)
 [2]=>
 int(173)
 [3]=>
 int(151)
}
packed => '字'

リファレンスを見てみたのですが、packに数値の配列を渡す方法が見つからないので、バイト数によって分岐し異なる引数のpackを呼び出す必要が有りそうです。

コメント(0)続きを読む