2009年4月30日木曜日

DLLからDEFファイルを作る

DLLファイルからDEFファイルを自動生成する必要があって、MinGWのpexportsを持っていなかったので、さくっと書いてみた。

dll_to_def.rb
#!ruby -Ku
# Generate the .def file from .dll using 'dumpbin.exe'
# 2009-04-30 23:43:20

class ExportsList
FUNCTION_LINE_PATTERN = /^\s+(\d+)\s+[0-9A-Fa-f]+\s+[0-9A-Fa-f]+\s+(.*)$/

def initialize(dllname)
@dllname = dllname
@max_name_length = 0
@exports = []
dumpbin(dllname) do |line|
next unless line =~ FUNCTION_LINE_PATTERN
@exports << [$1, $2]
@max_name_length = $2.length if @max_name_length < $2.length
end
end

def save_as_def
width = ((@max_name_length + 7) / 8) * 8
basename = File.basename(@dllname, '.dll')
File.open(basename + '.def', 'w') do |f|
f.puts(%Q|LIBRARY "#{basename}"|)
f.puts
f.puts('EXPORTS')
@exports.each do |i, name|
f.print("\t#{name}")
f.print("\t" * ((width + 7 - name.length) / 8))
f.puts("@#{i}")
end
end
end

private
def dumpbin(dllname)
raise "Command not found: dumpbin" unless cmd_exist?('dumpbin')
Kernel.open("|dumpbin /exports #{dllname}") do |f|
while line = f.gets
yield(line)
end
end
end

def cmd_exist?(cmd)
ENV['PATH'].split(';').each do |path|
(';' + ENV['PATHEXT']).split(';').each do |ext|
pathname = File.join(File.expand_path(path), cmd + ext)
return true if File.exist?(pathname)
end
end
nil
end
end

if $0 == __FILE__
ARGV.each do |dllname|
ExportsList.new(dllname).save_as_def
end
end

2009年4月28日火曜日

そろそろProcessingはじめてみる?


Quartz Composerにも興味津々だけど、その前にProcessingしてみる?

コマンドプロンプトでファイルを探す(リファクタリング)

コマンドプロンプトでファイルを探すをリファクタリング。
少しだけシンプルになったと思う。
locate.rb
#!ruby -Ku

module Locate
EXCLUDE_PATTERN = /^(\.|\.\.|\.svn)$/i

module_function
def locate(dirname, patterns)
each_entries(dirname) do |pathname, filename|
if File.directory?(pathname)
puts(pathname + '/') if match?(filename, patterns)
locate(pathname, patterns)
else
puts(pathname) if match?(filename, patterns)
end
end
end

def each_entries(dirname)
entries(dirname).each do |filename|
pathname = (dirname == '.' ? filename : File.join(dirname, filename))
yield(pathname, filename)
end
end

def entries(pathname)
Dir.entries(pathname).select do |filename|
filename !~ EXCLUDE_PATTERN
end
end

def match?(filename, patterns)
patterns.each do |pattern|
return true if filename =~ pattern
end
return false
end
end

if $0 == __FILE__
Locate.locate('.', ARGV.map{|pattern|Regexp.new(pattern, Regexp::IGNORECASE)})
end

2009年4月25日土曜日

SANYOのALBO


ホームネットワークビューワALBO
7インチの液晶をそなえた可愛いデジタルフォトフレーム+α
名前の通りデジタルフォトフレームの枠を超えた機能を持っている
Amazonでは31,320円で売っていた。
高い。
最近のデジタルフォトフレームはずいぶん安くなったので、比べてしまうと高い。
でもなぜか気になった。

2009年4月24日金曜日

DataスキームURI

DataスキームURIって
なんだかとっても
おもしろ~い。
<img src="data:image/png;base64,iVBORw0KGg...いっぱい省略..."/>
こんなんです。

2009年4月23日木曜日

即席 tail

Windowsなマシンでちょっと必要になったので書いてみた。

tail.rb
#!ruby -Ku

class Tail
def initialize(filename)
@filename = filename
end

def run
@interrupted = false
size = File.size(@filename)
size = print_head(size)
until @interrupted
size = print_diff(size)
sleep 0.5
end
end

def max(x, y)
x > y ? x : y
end

def print_head(size)
File.open(@filename, 'rb') do |f|
f.seek(max(size - 1024, 0))
print f.read
return f.tell
end
end

def print_diff(size)
latest = File.size(@filename)
return size if latest == size

if latest < size
puts
puts "truncated..."
puts
return print_head(latest)
end

File.open(@filename, 'rb') do |f|
f.seek(size)
print f.read
return f.tell
end
end

def interrupt
puts "^C"
@interrupted = true;
end
end

if $0 == __FILE__
tail = Tail.new(File.expand_path(ARGV[0]))
Signal.trap(:INT){ tail.interrupt }
tail.run
end

MS SQLServer の collation のメモ

必要になって調べてみたのでメモ。

■ 照合順序名の一覧

SELECT * FROM fn_helpcollations()

■ 照合順序の確認

○ Serverデフォルト値の確認

SELECT SERVERPROPERTY('collation')

○ データベース毎の確認

SELECT DATABASEPROPERTYEX('db_name', 'collation')

○ カラム毎の確認

sp_MSHelpcolumns table_name

■ 照合順序名の意味

Japanese_(BIN|(CI|CS)_(AI|AS)(_KS)?(_WS)?)

BIN (Binary)
→ 全て区別する

CI (Case Insensitive)
CS (Case Sensitive)
→ 大文字小文字の区別

AI (Accent Insensitive)
AS (Accent Sensitive)
→ アクセント、濁音、破裂音の区別

KI (Kana Insensitive)
KS (Kana Sensitive)
→ ひらがなとカタカナの区別

WI (Width Insensitive)
WS (Width Sensitive)
→ 文字幅の区別=全角・半角の区別

参考

RubyからGitをデータストアとして使う「Git Store」

RubyからGitをデータストアとして使う「Git Store」という記事をみつけた。
これは便利かも!

2009年4月22日水曜日

Webに3Dを by Google

GoogleのO3D。今後が楽しみです。

これまでもたくさん類似品はあったけど、GoogleがWebと3Dを本気で結びつけてくれそうな予感がするところに期待がふくらみます

OpenGLのポットが1000個、ぐりぐり回ってるのがブラウザで表示できてるのってちょっと面白かった。

ピンポンは途中でキーボードフォーカスが外れちゃったりとまだまだ初期段階っぽさ満載だけど。

可能性も満載な感じ。

WindowsでもC++のプログラムのデバッグを楽にしたいなぁ

C++のプログラムのデバッグを楽にする方法はとっても便利そう。

でもLinuxだったらgccで-gつけてコンパイルするのが基本だし。実行時のデメリットがほとんどないから。
スタックトレースできる機能はもともとあったよね。

WindowsでもC++でスタックトレースを表示してから落ちてほしいよなぁ。

最近そういう(すぐ落ちる)プログラムを毎日見てる。

2009年4月21日火曜日

AIRで非矩形ウィンドウ

OvalWindow.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication
xmlns:mx="http://www.adobe.com/2006/mxml"
showFlexChrome="false"
width="800" height="600"
paddingTop="0" paddingLeft="0" paddingRight="0" paddingBottom="0"
creationComplete="adjustSize()">
<mx:Script><![CDATA[]]>
private function adjustSize():void {
width = bg.width; height = bg.height;
}
</mx:Script>
<mx:Image id="bg" data="@Embed(source='./Oval.png')" mouseDown="nativeWindow.startMove()"/>
</mx:WindowedApplication>
OvalWindow-app.xml
<?xml version="1.0" encoding="utf-8"?>
<application xmlns="http://ns.adobe.com/air/application/1.5">
<id>com.blogspot.takumakei.OvalWindow</id>
<version>0.1</version>
<filename>OvalWindow</filename>
<initialWindow>
<systemChrome>none</systemChrome>
<transparent>true</transparent>
<maximizable>false</maximizable>
<resizable>false</resizable>
<content>OvalWindow.swf</content>
</initialWindow>
</application>
元のウィンドウサイズが画像のサイズより小さいと、AIRアプリを起動したときに一瞬スクロールバーが見える気がする。

2009年4月20日月曜日

Flexのコーディング規則

Flexのコーディング規則を見つけた。

これまで書いたコードが規則に則していないところもあった。

このページはかなり長い。具体例も示していて読みやすくは書いてあると思う。
それでもすべてをカバーできているわけでもないだろうな。

それにしても、こんなにたくさんひとつひとつ覚えるのは面倒だ。これまでの習慣と違うので、身体が覚えて自然に書けるようになるまでに時間もかかるだろう。

いろんな言語のソースを書いていていつも思うことだけど、自動的に整形する機能をコンパイラが持っていたらいいのに。
Warningで知らせてくれるとか、もっと過激にソースコードを修正してくれるとか。

歴史のある言語だと、宗教論争が燃え上がる可能性が高いから難しいだろうけれどね。

2009年4月19日日曜日

Adobe Flex 3 での Adobe AIR 1.5 アプリケーションの開発へのリンク

ブラウザのブックマークはマシン毎の同期がめんどうなのでできるだけ使わないようにしている。

ローカルがだめならオンライン。
Google bookmarksはメインのブラウザをchromeにしてからは使用頻度が減っている。
IEFirefoxGoogleツールバーを使っていたときはとても重宝していた。

最近はキーワードを頼りに検索エンジンに頼っている毎日。

そんななか、すぐに見失っちゃうリンク。

ついでにこっちもメモっておくかな・・

Adobe AIRアプリを配布する

Deploying Adobe AIR applications seamlessly with badge install

この記事はちゃんと読んで理解しておいたほうがよさそうだな。

NTEmacs 22BASE をインストール

自宅のマシンのEmacsは、公式サイトからダウンロードした22.3だったのだが、IMEパッチが適用されていないので不便だった。

普段使っている.emacsもロードできず、キーバインドになれていなくて用途が限られていた。

ようやく日本語インライン変換パッチ適用済みバージョンに差し替えたので、ついでに.emacsも書き換えてみた。
.emacs.el
;; [2009-04-19 01:25:04]

(setq inhibit-startup-message t)

(custom-set-variables
;; custom-set-variables was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
'(display-time-mode t)
'(current-language-environment "Japanese")
'(tool-bar-mode nil)
'(line-number-mode t)
'(column-number-mode t)
'(show-paren-mode t)
'(transient-mark-mode t))

(fixed-width-set-fontset "msgothic" 14)

(setq default-frame-alist
(append '((foreground-color . "black")
(background-color . "LemonChiffon")
(border-color . "black")
(mouse-color . "white")
(cursor-color . "black")
(top . 0)
(left . 1040)
(width . 96)
(height . 77)
(line-spacing . 0)
(cursor-type . box))
default-frame-alist))

(setq-default tab-width 4 indent-tabs-mode nil)

;;(add-hook 'c++-mode-hook
;; '(lambda()
;; (c-set-style "cc-mode")
;; (c-set-offset 'innamespace 0)))

(defconst my-c-style
'((c-tab-always-indent . t)
(c-comment-only-line-offset . 4)
(c-hanging-braces-alist . ((substatement-open after)
(brace-list-open)))
(c-hanging-colons-alist . ((member-init-intro before)
(inher-intro)
(case-label after)
(label after)
(access-label after)))
(c-cleanup-list . (scope-operator
empty-defun-braces
defun-close-semi))
(c-offsets-alist . ((arglist-close . c-lineup-arglist)
(substatement-open . 0)
(case-label . 4)
(block-open . 0)
(innamespace . 0)
(knr-argdecl-intro . -)))
(c-echo-syntactic-information-p . t))
"My C Programming Style")

;; offset customizations not in my-c-style
(setq c-offsets-alist '((member-init-intro . ++)))

;; Customizations for all modes in CC Mode.
(defun my-c-mode-common-hook ()
;; add my personal style and set it for the current buffer
(c-add-style "PERSONAL" my-c-style t)
;; other customizations
(setq tab-width 8
;; this will make sure spaces are used instead of tabs
indent-tabs-mode nil)
;; we like auto-newline and hungry-delete
(c-toggle-auto-hungry-state 1)
;; key bindings for all supported languages. We can put these in
;; c-mode-base-map because c-mode-map, c++-mode-map, objc-mode-map,
;; java-mode-map, idl-mode-map, and pike-mode-map inherit from it.
(define-key c-mode-base-map "\C-m" 'c-context-line-break))

(add-hook 'c-mode-common-hook 'my-c-mode-common-hook)

;;;; IME

(mw32-ime-initialize)
(setq default-input-method "MW32-IME")
(setq-default mw32-ime-mode-line-state-indicator "[--]")
(setq mw32-ime-mode-line-state-indicator-list '("[--]" "[あ]" "[--]"))
;; y/n, yes/no の問い合わせ時に IME をオフにする
(wrap-function-to-control-ime 'y-or-n-p nil nil)
(wrap-function-to-control-ime 'yes-or-no-p nil nil)

;;;; TAKUMAKEI

(defun kei-scroll-up ()
(interactive)
(scroll-up 1))

(defun kei-scroll-down ()
(interactive)
(scroll-down 1))

(defun kei-line-up ()
(interactive)
(let ((save-marker (point-marker)))
(kill-region (line-end-position) (point-marker))
(previous-line)
(yank)
(kill-region (line-end-position) (point-marker))
(goto-char (marker-position save-marker))
(yank '(nil))
(previous-line)))

(defun kei-line-down ()
(interactive)
(let ((save-marker (point-marker)))
(kill-region (line-end-position) (point-marker))
(next-line)
(yank)
(kill-region (line-end-position) (point-marker))
(goto-char (marker-position save-marker))
(yank '(nil))
(next-line)))

(load-library "time-stamp")
(defun kei-insert-date-string ()
(interactive)
(insert
(format "[%s %s]"
(time-stamp-yyyy-mm-dd)
(time-stamp-hh:mm:ss))))

(defun kei-load-memo (df)
(find-file
(expand-file-name
((lambda (today)
(format
"c:/Users/kei/Documents/memo/%s/%s(%s).txt"
(format-time-string "%Y" today)
(format-time-string "%Y-%m-%d" today)
(aref [ "日" "月" "火" "水" "木" "金" "土" ]
(string-to-number (format-time-string "%w" today)))))
((lambda (ts)
(let ((dt (decode-time ts)))
(encode-time 0 0 0
(+ (car (nthcdr 3 dt)) df)
(car (nthcdr 4 dt))
(car (nthcdr 5 dt)))))
(current-time))))))

(defun memo ()
(interactive)
(kei-load-memo 0))

(defun memox ()
(interactive)
(kei-load-memo (read-minibuffer "何日後?> " "")))

(defun kei-set-alpha1 ()
(interactive)
(set-alpha '(100 100)))

(defun kei-set-alpha2 ()
(interactive)
(set-alpha '(50 50)))

(defun kei-set-alpha3 ()
(interactive)
(set-alpha '(20 20)))

(global-set-key [(meta d)] 'kei-insert-date-string)
(global-set-key [(meta n)] 'kei-scroll-up)
(global-set-key [(meta p)] 'kei-scroll-down)
(global-set-key [(meta up)] 'kei-line-up)
(global-set-key [(meta down)] 'kei-line-down)
(global-set-key [(meta g)] 'goto-line)
(global-set-key [(meta o)] 'open-line)
(global-set-key [(ctrl h)] 'backward-delete-char-untabify)
(global-set-key [(ctrl o)] 'toggle-input-method)
(global-set-key [(ctrl \\)] 'kei-set-alpha1)
(global-set-key [(ctrl ,)] 'kei-set-alpha2)
(global-set-key [(ctrl .)] 'kei-set-alpha3)

2009年4月18日土曜日

Flexのswfの逆アセンブル

Flashのswfは逆アセンブルできるので、なんらかの理由でアルゴリズムが第三者に知られたくない場合に問題になる。と、どこかで聞いて知っていた。

AIRもswfなので、同じなのだろう。

確かめるために、自分で作ったAIRアプリを逆アセンブルしてみることにした。

まず、swfと逆アセンブルでぐぐったらFlareが引っかかったので試してみた。

結果は惨敗。クラス名と思われる名前は抽出されるが、肝心の中身は全く出力されていない。

同じswfなのに。

C++で作ったバイナリと、Cで作ったバイナリは、逆アセンブルすればそれぞれ特徴的なパターンを持っているのかもしれないと考えれば、Flashで作ったswfとFlexで作ったswfのパターンが異なっていてFlareで逆アセンブルできないことも不思議じゃない。

さて、ということは逆アセンブルできないのかというと、そうでもない。

Flex SDKにはswfdumpというツールがあったとか。(Flex SDK 3.3では見つけられない)
Flasmというものもある。(試してないけど)

それに、Nemo 440というAIRアプリを見つけた。

試してみたところ、バイトコードレベルだけれど、比較的読みやすいように思う。

FlashのVMのバイトコードを勉強する気にはまだなれないけれどね。

コマンドプロンプトでファイルを探す

ファイル名でファイルを検索することがよくある。
特にコマンドプロンプトを使っているときにそういう場面に遭遇する。
その都度Explorerを開いて作業するのは不便なのでRubyで作ってみた。
locate.rb
#!ruby -Ku

def handle_file(names, name)
basename = File.basename(name)
found = false
names.each do |target|
if basename =~ target
found = true
break
end
end
puts name if found
end

def handle_dir(names, name)
handle_file(names, name + '/')
handle_all(names, name + '/*')
end

def handle_all(names, name)
Dir[name].each do |candidate|
if File.directory?(candidate)
basename = File.basename(candidate)
handle_dir(names, candidate) unless basename == '.' || basename == '..'
else
handle_file(names, candidate)
end
end
end

def locate(names)
names = names.map{|n| Regexp.new(n)}
handle_all(names, '.*')
handle_all(names, '*')
end

if $0 == __FILE__
locate(ARGV)
end

2009年4月17日金曜日

Event propagation

Eventの伝搬の中の最後のフェーズなのね。
Bubbling。
読んでおこうっと。

Flex3でカスタムイベント


任意のActionScriptクラスで任意のイベントクラスをイベントとして送出するサンプル。

clone()をオーバーライドしないとイベントバブリングが発生した場合に問題になるそうだ。
これまで見て見ぬふりをしてきた「イベントバブリング」ってなんだろ?

それから、
[Event(name="alert", type="MyEvent")]
という属性(なのかな?)を書くと、Adobe Flex Builder 3 のコードエディタでaddEventListenerの引数の補完候補に表示されるようになる。これは便利。

カスタムイベントの作成(Flex2だけど日本語)とか

com.blogspot.takumakei.MyEventDispatcher.as
package com.blogspot.takumakei
{
import flash.events.EventDispatcher;
import flash.events.IEventDispatcher;

[Event(name="alert", type="MyEvent")]
[Event(name="notify", type="MyEvent")]
public class MyEventDispatcher extends EventDispatcher
{
public function MyEventDispatcher(target:IEventDispatcher=null)
{
super(target);
}

public function dispatchAlert(customProperty:String):void {
dispatchEvent(new MyEvent(MyEvent.ALERT, customProperty));
}

public function dispatchNotify(customProperty:String):void {
dispatchEvent(new MyEvent(MyEvent.NOTIFY, customProperty));
}
}
}
com.blogspot.takumakei.MyEvent.as
package com.blogspot.takumakei
{
import flash.events.Event;

public class MyEvent extends Event
{
public static const NOTIFY:String = 'notify';
public static const ALERT:String = 'alert';

public var customProperty:String = null;

public function MyEvent(type:String, customProperty:String, bubbles:Boolean=false, cancelable:Boolean=false)
{
super(type, bubbles, cancelable);
this.customProperty = customProperty;
}

override public function clone():Event {
return new MyEvent(type, customProperty);
}
}
}
StudyCustomEvent.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" initialize="init()">
<mx:Script>
<![CDATA[
import mx.controls.Alert;

import com.blogspot.takumakei.MyEvent;
import com.blogspot.takumakei.MyEventDispatcher;

private var myEventDispatcher:MyEventDispatcher = new MyEventDispatcher();

private function init():void {
myEventDispatcher.addEventListener(
MyEvent.NOTIFY,
function(event:MyEvent):void {
Alert.show(event.customProperty, 'MyEvent(notify) received');
});
myEventDispatcher.addEventListener(
MyEvent.ALERT,
function(event:MyEvent):void {
Alert.show(event.customProperty, "MyEvent(alert) received");
});
}

private function dispatchAlert():void {
myEventDispatcher.dispatchAlert('hello world');
}

private function dispatchNotify():void {
myEventDispatcher.dispatchNotify('hello world');
}
]]>
</mx:Script>
<mx:Button label="alert" click="dispatchAlert()"/>
<mx:Button label="notify" click="dispatchNotify()"/>
</mx:WindowedApplication>

2009年4月16日木曜日

知らないと損する便利なAIRアプリ60こ以上

60+ Useful Adobe AIR Applications You Should Know

知らないのもあったけど
便利そうなのもあったけど
知らなくてもいいものあったような・・・

Ruby 1.8.7-p160リリースされましたね

Ruby 1.8.7-p160は安定版であるruby 1.8.7の保守リリースです。」とのこと。

2009年4月15日水曜日

Flex 3 beta 3でRESTfulの記事みつけた


Flexのインストールからアプリの作成まで、図入りで丁寧に説明してくれている。
読みやすそう。

記事の内容だけでなく、ソースコードの表示に使っているdp.SyntaxHighlighterが気になった。

いいな~

boostproが登録制になってた

自分一人で使うなら、ソースコードからビルドして使っていれば十分なのだけど、チームで共同開発する場合には、「ソースコードからビルド・・・」なんて言おうものなら、「そんなもの使うなめんどくさい」と言われてしまう可能性が高い。

そんなときにwww.boostpro.comが便利だったのに・・・

いつのまにか、アカウント登録しないとダウンロードさせてもらえなくなってる。
「登録するのめんどくさい」って言われてしまうだろうなぁ。

しかも、ネットワークインストールになってる。
これだと、リンク先が突然なくなってしまわないかと不安で夜も眠れないよなぁ。

タイトルのなかの「中」が文字化けする!?


このPCの環境がおかしくなっているのだろうか?
Google Chrome 1.0.154.53 のアプリケーションのショートカット
chrome.exe --app=http://takumakei.blogspot.com/ --incognito
で表示した時だけ、タイトルのなかの「中」が文字化けする。
へんなの~

2009年4月14日火曜日

関数の呼び出し規約に縛られないラッパーDLLを作る

関数の呼び出し規約に縛られないラッパーDLLを作る

これは面白い!
なにかの時に役に立ちそう。

「特攻する別exeを作って生き残った方で呼び出す(笑)」ここは何度読んでも笑える。

要点は
  • インラインアセンブラで自前でスタック調整
  • コンパイルオプションなどによっては、最適化されてしまってまずい事になるのを予防する
という2点。

スタック調整
unsigned long reg_esp;
asm { mov reg_esp, esp }
// 関数呼び出し
asm { mov esp, reg_esp }

詳しいことは元ネタを参照。

「問題ある部分をDLLとして切り分ける」ことが、なぜ「最適化でまずいことになるのを予防する」につながるのかな?

「切り分けしたDLLが問題ないことがわかったらリビルドはしないで使い回すことができる」から?

MigemizeExplorer

エクスプローラを日本語でインクリメンタルサーチできるのだそうだ。
すごい!便利~!

...なのだろうけど...

こういう機能はデフォルトでついていて欲しかった。

Windowsをカスタマイズしまくってめちゃくちゃ使いやすくなってしまうと、他の環境に引っ越しする時に面倒なことになったり、たまたま使わなくちゃいけないWindowsとかを使う時に、あれ?あれ?って驚いてしまう。

Explorerは特に使用頻度が高いだけにたちが悪い。

それにフォルダ名の命名規則(と言うほど大げさなものではないが)がなんとなくできていて、検索対象にしそうなフォルダ名の先頭には日本語を使わないように馴らされているので、インストールはしないかもな。

もう少し若い頃に出会えていれば良かったね。

.DEFでNONAMEしたら関数名は見えないよ

早とちりした。「.DEFでNONAMEしても関数名見えちゃうじゃん」は嘘だった。
ビルドした場所に.PDBが存在していたから関数名も「親切に」教えてくれたのだった。

DLLをビルドする時に、「リンカ→デバッグ→デバッグ情報の生成」を「いいえ」にしたら、dumpbinの出力に元の関数名が表示されることはなかった。

良かった。恥ずかしい関数名でもばれることはないのだ。(どれだけ変な名前なんだ...!?)

ちなみに、dumpbinが.PDBを参照する機能は、.DLLをビルドした場所からコピーしても有効になる。
DLLをデバッグ情報の生成を"はい"にしてビルドすると、.PDBファイルのフルパス名がDLLの中に埋め込まれているからだ。

しかし、.PDBの参照はファイル名だけではないようで、
  1. DLLをビルドする
  2. DLLを別のフォルダにコピーする → A.DLL とする
  3. dumpbin/exports A.DLLすると関数名が見える
  4. DLLをリビルドする(※ソースコードや設定変更など一切なし)
  5. dumpbin/exports A.DLLすると関数名はもはや見えない
という結果になった。

A.DLLをコピーして.PDBを削除すると、.PDBを再度作成しても参照してはくれないのだ。
おれおれ詐欺にはひっかからないってことらしい。

でも、A.DLLにはPDBファイルのフルパス名は埋め込まれているわけで、バイナリエディタかなにかを使えば、ビルドした時のフォルダ名が見えてしまうってことだ。

あ〜やっぱり恥ずかしいフォルダ名がばれちゃうってことじゃん。(どれだけ変な名前なんだ...!? 2回目)

.DEFでNONAMEしても関数名見えちゃうじゃん

え~知らなかった。
恥ずかしい関数名とかつけてなかったかなぁ・・・。
Windowsにもstripあるのかな?
※投稿直後に.DEFでNONAMEしたら関数名は見えないことがわかった
StudyDLL.cpp
int WINAPI Function_I_want_to_hide_its_name(int argc, char* argv)
{
return 0;
}
StudyDLL.def
StudyDLL.def

LIBRARY "StudyDLL"

EXPORTS
Function_I_want_to_hide_its_name @1 NONAME
dumpbin /exports StudyDLL.dll
Microsoft (R) COFF/PE Dumper Version 9.00.30729.01
Copyright (C) Microsoft Corporation. All rights reserved.


Dump of file StudyDLL.dll

File Type: DLL

Section contains the following exports for StudyDLL.dll

00000000 characteristics
49E4590C time date stamp Tue Apr 14 18:36:12 2009
0.00 version
1 ordinal base
1 number of functions
0 number of names

ordinal hint RVA name

1 00001000 [NONAME] ?Function_I_want_to_hide_its_name@@YGHHPAD@Z
(int __stdcall Function_I_want_to_hide_its_name(int,char *))

Summary

1000 .data
1000 .rdata
1000 .reloc
1000 .rsrc
1000 .text

2009年4月12日日曜日

WindowsでGitを使えるようになりたい

デファクトスタンダードと呼ばれる分散バージョン管理システムはまだないが、Gitは有名。
先日見つけたGit Extensionsに触発されて、Gitが(自分のなかで)盛り上がっている。
そんなさなかに見つけた「分散バージョン管理システムGitを活用しよう」というこの記事は勉強になりそうだ。

KubuntuをVirtualBoxで動かしてみた


VirtualBoxが2.2.0にバージョンアップしてた。
早速アップデートして、ついでにkubuntu 8.10をインストールしてみた。
24インチのiMacBootCampつかってWindows Vistaをいれて、VirtualBox 2.2.0 for Windows hosts動かしてkubuntuを動かしてる。
動かしてるだけで楽しい。

...ところでkubuntuのダウンロードのページの中央のiFrame(?)にubuntuが表示されるのだけど、これって意図したことなんだろうか。

2009年4月11日土曜日

WindowsでGitを使う

分散バージョン管理システムを使いたいと思っていたけれど、TortoiseSVNが便利すぎてなかなか手をつけられなかった。
もしかしたらGit Extensionsは答えになるかもしれない。

2009年4月10日金曜日

BloggerStyle.mxml不具合修正


前のバージョンでは「コードをコピー→clearをクリック→コードをペースト」ができなかった。
BloggerStyle.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"
width="164" height="164"
minWidth="164" minHeight="164"
showFlexChrome="true"
paddingBottom="2" paddingLeft="2" paddingRight="2" paddingTop="2"
showStatusBar="false"
title="BloggerStyle"
>
<mx:Script>
<![CDATA[
import mx.controls.CheckBox;
private static var TEMPLATE_TEXT_A:String
= '<pre class="mycodeT" onclick="toggleMyCode(this)">%name%</pre>'
+ '<pre class="mycodeB">%body%</pre>';
private static var TEMPLATE_TEXT_B:String
= '<pre class="mycodeT">%name%</pre>'
+ '<pre class="mycodeB">%body%</pre>';

private function escape(x:String):String {
x = x.replace(/&/g, '&amp;');
x = x.replace(/</g, '&lt;');
x = x.replace(/>/g, '&gt;');
x = x.replace(/"/g, '&quot;'); // "
return x;
}
private function format():String {
var name:String = escape(src_name.text);
var body:String = escape(src_body.text);
if(src_clickable.selected)
{
return TEMPLATE_TEXT_A.replace(/%name%/, name).replace(/%body%/, body);
}
return TEMPLATE_TEXT_B.replace(/%name%/, name).replace(/%body%/, body);
}
private function updateResult():void {
var text:String;
if(src_name.text != '' || src_body.text != ''){
text = format();
var cb:Clipboard = Clipboard.generalClipboard;
cb.setData(ClipboardFormats.TEXT_FORMAT, text);
}
else{
text = '';
}

if(dst != null){
dst.text = text;
}

}
private function clear():void {
src_name.text = '';
src_body.text = '';
}
]]>
</mx:Script>
<mx:TabNavigator width="100%" height="100%">
<mx:VBox label="I" width="100%" height="100%">
<mx:TextInput id="src_name" change="updateResult()"
width="100%" />
<mx:TextArea id="src_body" change="updateResult()"
width="100%" height="100%"
horizontalScrollPolicy="on" verticalScrollPolicy="on"/>
<mx:ControlBar
width="100%"
paddingBottom="2" paddingLeft="2" paddingRight="2" paddingTop="2">
<mx:CheckBox id="src_clickable" label="clickable?" click="updateResult()"/>
<mx:Spacer width="100%"/>
<mx:Button label="clear" click="clear()"/>
</mx:ControlBar>
</mx:VBox>
<mx:Canvas label="O" show="updateResult()"
width="100%" height="100%" >
<mx:TextArea id="dst"
editable="false"
width="100%" height="100%"
horizontalScrollPolicy="on" verticalScrollPolicy="on"/>
</mx:Canvas>
</mx:TabNavigator>
</mx:WindowedApplication>

今度はホント、App Engineに新しい言語 : Java™

探していたのはこっちでした。JRubyにも興味が出てきたな。
Seriously this time, the new language on App Engine: Java™

Google App Engine for Fortran

A Brand New Language on Google App Engine!
GAE for Javaを探してて見つけちゃった。
昔話だけど、面白かった。

path_mod.batに変更(PATH環境変数の要素の変更)

先日作ったPATH_SUB.BATには仕様バグがあったので書き直し。
PATHの要素から指定したパターンを探して、新たなディレクトリを追加するのは前と同じ。
ただし、
  • パターンにパッチした要素を置換する
  • マッチした要素は削除してPATHの先頭に追加する
  • マッチした要素は削除してPATHの末尾に追加する
という3種類の操作に対応してみた。
...でも、先頭に追加する機能しか使ってない...。無駄だったか...。
いつか役に立つ日が来るかもしれないよな...。

path_mod.bat
@echo off
set PATH_MOD_BAT=%TEMP%\path_mod_.bat
if "%1"=="replace" (
ruby -e "puts('PATH='+ENV['PATH'].split(';').map{|x|(x=~/%2/i)?'%3':x}.select{|y|y.size>0}.join(';'))" > %PATH_MOD_BAT%
) else if "%1"=="head" (
ruby -e "puts('PATH='+(['%3']+ENV['PATH'].split(';').select{|x|x !~/%2/i}).select{|y|y.size>0}.join(';'))" > %PATH_MOD_BAT%
) else if "%1"=="tail" (
ruby -e "puts('PATH='+(ENV['PATH'].split(';').select{|x|x !~/%2/i}+['%3']).select{|y|y.size>0}.join(';'))" > %PATH_MOD_BAT%
) else (
echo "Bad Usage: path_mod [replace|head|tail] pattern path"
goto cleanup
)
call %PATH_MOD_BAT%
del %PATH_MOD_BAT%
:cleanup
set PATH_MOD_BAT=
r186.bat
@call path_mod head ruby.*\\bin C:\\App\\ruby-186-26\\bin
r187.bat
@call path_mod head ruby.*\\bin C:\\App\\ruby-187-p72\\bin
r191.bat
@call path_mod head ruby.*\\bin C:\\App\\ruby-1.9.1-p0-i386-mswin32\\bin
jdk.bat
@set JAVA_HOME=C:\PROGRA~1\Java\jdk1.6.0_13
@call path_mod head \\jdk.*\\bin C:\\Progra~1\\Java\\jdk1.6.0_13\\bin
flex3
@call jdk
@call path_mod head \\flex.*\\bin C:\\App\\flex_sdk_3.3\\bin
jr114.bat
@call jdk
@call path_mod head jruby.*\\bin C:\\PROGRA~1\\NETBEA~1.1\\ruby2\\jruby-1.1.4\\bin

2009年4月9日木曜日

インストールしたgemのドキュメントを見る方法

実は知りませんでした。

前から「どうやって参照するんだろ?」と思ってました。

いまさらな感じ。
コマンド例
gem server --port 8808 --no-daemon

このコマンドでWebサーバが動くので、ブラウザでhttp://localhost:8808/にアクセスすれば良い。

しかもこのWebサーバでgemを配布することもできるらしい。

その場合は、
コマンド例
gem install GEMNAME --source http://gem_server_host:8808/

とするらしい。

詳しくは gem help server すること。

Rubyでzipファイル作る(圧縮)

rubyzipとziprubyを発見。
「ziprubyの方が評判がいい」とのことなのでziprubyを選択。
後で速度比較してみたいな。
インストール
gem install zipruby
コード例
require 'zipruby'

Zip::Archive.open('target.zip', Zip::CREATE) do |ar|
ar.add_file('source')
end

VirtualBox 2.2.0 released !

2009年4月8日に VirtualBox 2.2.0 がリリースされてた。

2009年4月7日火曜日

AIRが持つHTMLレンダリングエンジンを遊ぶ



記事を書いた頃のAIRのバージョンは古いみたいでAPIが変わっていた。

それをさらに更新してくれているFlex3でAIRブラウザという記事にたどり着き、

ようやくサンプルを手元で動かすことができました。


しかし、日本語が文字化けするのは何でだろう?

全てが文字化けするわけではないところが微妙~

FlexHTML.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="init()"
showStatusBar="false"
paddingBottom="2" paddingLeft="2" paddingRight="2" paddingTop="2">
<mx:Script>
<![CDATA[
private const DEFAULT_HOME:String = "http://www.google.com";

private const THUMBNAIL_WIDTH:uint = 800;
private const THUMBNAIL_HEIGHT:uint = 600;

private function init():void {
var initialBounds:Rectangle
= new Rectangle(
(Screen.mainScreen.bounds.width / 2 - 500),
(Screen.mainScreen.bounds.height / 2 - 400), 1000, 800);
this.nativeWindow.bounds = initialBounds;
htmlPage.addEventListener(Event.LOCATION_CHANGE, onLocationChange);
htmlPage.addEventListener(Event.COMPLETE, onHTMLComplete);
locationInput.text = DEFAULT_HOME;
changeLocation();
}
private function onLocationChange(event:Event):void {
locationInput.text = event.target.location;
}
private function changeLocation():void {
var url:String = locationInput.text;
htmlPage.location = url;
}

private var thumbnailCache:Object;

private function onHTMLComplete(event:Event):void {
thumbnailCache = {};
var links:Object = htmlPage.htmlLoader.window.document.links;
for(var i:uint = 0; i < links.length; ++i){
links[i].addEventListener("mouseover", thumbnailLoadFunc(links[i]));
links[i].addEventListener("mouseout", thumbnailHideFunc(links[i]));
links[i].addEventListener("click", thumbnailHideFunc(links[i]));
}
}
private function thumbnailHideFunc(link:Object):Function {
return function(mouseEvent:Object):void {
var thumbnail:Object = thumbnailCache[link.href];
if(!thumbnail){
return;
}
htmlPage.removeChild(thumbnail);
};
}
private function thumbnailLoadFunc(link:Object):Function {
return function(mouseEvent:Object):void {
var thumbnail:Object = thumbnailCache[link.href];
if(!thumbnail){
thumbnail = new Sprite();
var html:HTMLLoader = new HTMLLoader();
html.load(new URLRequest(link.href));
html.scaleX = .5;
html.scaleY = .5;
html.width = THUMBNAIL_WIDTH;
html.height = THUMBNAIL_HEIGHT;
thumbnail.addChild(html);
thumbnailCache[link.href] = thumbnail;
}
thumbnail.x = mouseEvent.x;
thumbnail.y = mouseEvent.y;
htmlPage.addChild(thumbnail);
};
}
]]>
</mx:Script>
<mx:VBox height="100%" width="100%">
<mx:HBox height="20" width="100%">
<mx:TextInput id="locationInput" width="100%"/>
<mx:Button label="Go"/>
</mx:HBox>
<mx:HTML id="htmlPage" width="100%" height="100%"/>
</mx:VBox>
</mx:WindowedApplication>

Swingのチュートリアル

JavaDriveの記事が良くまとめてあって読みやすそう。

Flex Builder 3 で AIR アプリを作った


toggleMyCode()を呼び出すコードを埋め込んだ。

休む暇もなくクリップボードにコピーするコードになってて美しくない。周期的に入力を検査して、変化があったらコピーする。それに加えて、アプリケーションがフォーカスを失う時にコピーすれば十分かな?
またいつか・・・。
BloggerStyle.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"
width="164" height="164"
minWidth="164" minHeight="164"
showFlexChrome="true"
paddingBottom="2" paddingLeft="2" paddingRight="2" paddingTop="2"
showStatusBar="false"
title="BloggerStyle"
>
<mx:Script>
<![CDATA[
import mx.controls.CheckBox;
private static var TEMPLATE_TEXT_A:String
= '<pre class="mycodeT" onclick="toggleMyCode(this)">%name%</pre>'
+ '<pre class="mycodeB">%body%</pre>';
private static var TEMPLATE_TEXT_B:String
= '<pre class="mycodeT">%name%</pre>'
+ '<pre class="mycodeB">%body%</pre>';

private function escape(x:String):String {
x = x.replace(/&/g, '&amp;');
x = x.replace(/</g, '&lt;');
x = x.replace(/>/g, '&gt;');
x = x.replace(/"/g, '&quot;'); // "
return x;
}
private function format():String {
var name:String = escape(src_name.text);
var body:String = escape(src_body.text);
if(src_clickable.selected)
{
return TEMPLATE_TEXT_A.replace(/%name%/, name).replace(/%body%/, body);
}
return TEMPLATE_TEXT_B.replace(/%name%/, name).replace(/%body%/, body);
}
private function updateResult():void {
var text:String = format();
if(dst != null){
dst.text = text;
}
var cb:Clipboard = Clipboard.generalClipboard;
cb.setData(ClipboardFormats.TEXT_FORMAT, text);
}
private function clear():void {
src_name.text = '';
src_body.text = '';
updateResult();
}
]]>
</mx:Script>
<mx:TabNavigator width="100%" height="100%">
<mx:VBox label="I" width="100%" height="100%">
<mx:TextInput id="src_name" change="updateResult()"
width="100%" />
<mx:TextArea id="src_body" change="updateResult()"
width="100%" height="100%"
horizontalScrollPolicy="on" verticalScrollPolicy="on"/>
<mx:ControlBar click="updateResult()"
width="100%"
paddingBottom="2" paddingLeft="2" paddingRight="2" paddingTop="2">
<mx:CheckBox id="src_clickable" label="clickable?"/>
<mx:Spacer width="100%"/>
<mx:Button label="clear" click="clear()"/>
</mx:ControlBar>
</mx:VBox>
<mx:Canvas label="O" show="updateResult()"
width="100%" height="100%" >
<mx:TextArea id="dst"
editable="false"
width="100%" height="100%"
horizontalScrollPolicy="on" verticalScrollPolicy="on"/>
</mx:Canvas>
</mx:TabNavigator>
</mx:WindowedApplication>

PATH_SUB.BAT ... PATH環境変数の要素の置換

複数のバージョンのjdkとかrubyとかを取っ換え引っ換え使ったりする。
Windowsのコマンドラインで。
そのためにPATH環境変数を書き換えるのだけど、こんなBATファイルを使ってる。
PATH_SUB.BAT
@ECHO OFF
SET UPDATE_PATH_BAT=%TEMP%\updatepath.bat
ruby -e "puts('PATH='+(ENV['PATH'].split(';').select{|x|x !~ /%1/i} + ['%2']).join(';'))" > %UPDATE_PATH_BAT%
CALL %UPDATE_PATH_BAT%
DEL %UPDATE_PATH_BAT%
SET UPDATE_PATH_BAT=
r186.bat
@CALL PATH_SUB \\ruby.*\\bin C:\\App\\ruby-186-26\\bin
r187.bat
@CALL PATH_SUB \\ruby.*\\bin C:\\App\\ruby-187-p72\\bin
r191.bat
@CALL PATH_SUB \\ruby.*\\bin C:\\App\\ruby-1.9.1-p0-i386-mswin32\\bin

※ 2009-04-10 正しく動かないBATの記述を削除
※ 2009-04-10 path_mod.bat

Swingの中でJavaFX

おもしろ~い
でも逆にJavaFXの中にSwingしたいな。JavaFXのGUIコンポーネントはまだ少ないからなぁ。

2009年4月6日月曜日

なんとなくJavaFX

ふんわり表示するプログラムをJavaFXで何となく書いてみた。特に意味なし。
main.fx
package studyfx;

import javafx.animation.Interpolator;
import javafx.animation.Timeline;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

var opacity = 0.0;

def image = Image {
url: "{__DIR__}images/3415358870_1cc377423d_m.jpg"
}

var stage:Stage = Stage {
title: "Application title"
style: StageStyle.TRANSPARENT
width: image.width
height: image.height
scene: Scene {
fill: Color.TRANSPARENT
content: ImageView {
opacity: bind opacity
preserveRatio: true
image: image
onMouseDragged: function(event:MouseEvent):Void {
stage.x += event.dragX;
stage.y += event.dragY;
}
}
}
}

Timeline {
keyFrames: [
at (0s) { opacity => 0.0 },
at (0.5s) { opacity => 1.0 tween Interpolator.EASEBOTH }
]
}.play();

2009年4月4日土曜日

見え隠れするコード領域

toggleMyCode.js
<script type="text/javascript">
function getNS(children, target, found, index){
if(children.length == index){return null;}
if(found){return children[index];}
if(target == children[index]){found=true;}
return getNS(children, target, found, index+1);
}
function toggleMyCode(me){
var item = getNS(me.parentElement.children, me, false, 0);
if(!item){ return; }
var style = item.style;
if('none' == style.display){
style.display = 'block';
}else{
style.display = 'none';
}
}
</script>

Windows Live Writerを試す

ブラウザでBloggerの記事を書くのはちょっと不便。

Blog Editorを探してみよう。

まず最初はWindows Live Writer。

ん♪

sample
#include <stdio.h>

int main(int argc, char* argv[]){
printf("hello world\n");
return 0;
}

これは便利かも!プログラムのコードなどを載せるために使っているカスタマイズしたスタイルシートを適用した状態でプレビューできる。これは便利かもしれない。

JavaFXはじめました

RubyのためにNetBeans IDEをインストールしてあったので、SilverLightより先にJavaFX。
本家のチュートリアルを斜め読みしつつ、プラグインをインストールして環境構築完了。

ついにベールを脱いだJavaFXも参考になるかな?チラ見した。

非矩形フレーム、あるいは透明フレームをいただいてみた。JavaFX SDKのバージョンが違うから?そのままではビルドできなかったので。

JavaFXのAPIドキュメント。なんだか読みにくいよ。

ノーティファイアイコン(タスクトレイアイコンとかシステムトレイアイコンとも言う)を使いたいと思ったらこの記事も参考になるかも。

Main.fx
/*
* Main.fx
*
* Created on 2009/04/04, 17:16:02
*/

package javafxeyes;

import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.PointerInfo;
import java.lang.Math;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.Scene;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Ellipse;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

var rightX:Number;
var rightY:Number;
var leftX:Number;
var leftY:Number;
var strokeWidth: Number = 10;
var eyeRadius = bind strokeWidth;
var width = 150;
var height = 100;

var stage:Stage = Stage {
title: "JavaFXeyes"
width: bind width
height: bind height
style: StageStyle.TRANSPARENT
scene: Scene {
fill: null
content: [
Ellipse {
centerX: bind width / 4
centerY: bind height / 2
radiusX: bind width / 4 - strokeWidth / 2
radiusY: bind height / 2 - strokeWidth / 2
stroke: Color.BLACK
strokeWidth: bind strokeWidth
fill: null // Color.WHITE
onMouseDragged: moveStage
},
Circle {
centerX: bind leftX
centerY: bind leftY
radius: bind eyeRadius
fill: Color.BLACK
onMouseDragged: moveStage
},
Ellipse {
centerX: bind width / 4 * 3
centerY: bind height / 2
radiusX: bind width / 4 - strokeWidth / 2
radiusY: bind height / 2 - strokeWidth / 2
stroke: Color.BLACK
strokeWidth: bind strokeWidth
fill: null // Color.WHITE
onMouseDragged: moveStage
},
Circle {
centerX: bind rightX
centerY: bind rightY
radius: bind eyeRadius
fill: Color.BLACK
onMouseDragged: moveStage
}
]
}
}

Timeline {
repeatCount: Timeline.INDEFINITE
keyFrames : [
KeyFrame {
time : 50ms
action: updateEyePosition
}
]
}.play();

function moveStage(event:MouseEvent):Void {
var x = event.dragX;
var y = event.dragY;
stage.x = stage.x + x;
stage.y = stage.y + y;
}

function calcEyePosition(x:Number, y:Number, cx:Number, cy:Number):Point {
var eyeX:Number = 0;
var eyeY:Number = 0;

var theta = Math.atan2(y - cy, x - cx);

var hr = width / 4 - strokeWidth - eyeRadius;
if(Math.abs(x - cx) > Math.abs(hr*Math.cos(theta))){
eyeX = cx + hr * Math.cos(theta);
} else {
eyeX = x;
}

var vr = height / 2 - strokeWidth - eyeRadius;
if(Math.abs(y - cy) > Math.abs(vr * Math.sin(theta))){
eyeY = height - cy - vr * Math.sin(theta);
} else {
eyeY = height - y;
}

return new Point(eyeX as Integer, eyeY as Integer);
}

function updateEyePosition():Void {
var point:PointerInfo = MouseInfo.getPointerInfo();
var x = point.getLocation().getX();
var y = point.getLocation().getY();
x = x - stage.x;
y = -y + stage.y + stage.height;
var p = calcEyePosition(x, y, width / 4, height / 2);
leftX = p.x;
leftY = p.y;
p = calcEyePosition(x, y, width / 4 * 3, height / 2);
rightX = p.x;
rightY = p.y;
}

jnlpでインストールする場合、マウスポインタの取得に(?本当かな?)セキュリティ制限が引っかかるので、securityで権限を与え、jarファイルに署名する必要があった。

JavaFXeyes.jnlp
<?xml version="1.0" encoding="UTF-8"?>
<jnlp spec="1.0+" codebase="file:///c:/Dev/" href="JavaFXeyes.jnlp">
<information>
<title>JavaFXeyes</title>
<vendor>Study JavaFX</vendor>
<icon href="icon.png"/>
<homepage href="http://takumakei.blogspot.com/"/>
<description>JavaFXeyes is the my first JavaFX program</description>
<offline-allowed/>
<shortcut>
<desktop/>
</shortcut>
</information>
<security>
<all-permissions/>
</security>

<resources>
<j2se version="1.5+"/>
<extension name="JavaFX Runtime" href="http://dl.javafx.com/1.1/javafx-rt.jnlp"/>
<jar href="JavaFXeyes.jar" main="true"/>
</resources>
<application-desc main-class="javafxeyes.Main">
</application-desc>
</jnlp>

自己署名証明書で署名する
C:\Dev>keytool -selfcert -alias myself -keystore myKeystore
C:\Dev>keytool -list -keystore myKeystore
C:\Dev>jarsigner -keystore myKeystore JavaFXeyes.jar myself

2009年4月1日水曜日

require 'dl'の続き

Ruby/DLをもっと使ってみた。

sample.rb
#!/usr/local/bin/ruby -Ku
# -*- encoding: utf-8 -*-

require 'dl/import'
require 'dl/struct'

module DSO
extend DL::Importable

typealias('BOOL', 'int')
typealias('WORD', 'unsigned short')
typealias('LPSYSTEMTIME', 'void*')
typealias('LPFILETIME', 'void*')

SYSTEMTIME = struct [
"WORD wYear",
"WORD wMonth",
"WORD wDayOfWeek",
"WORD wDay",
"WORD wHour",
"WORD wMinute",
"WORD wSecond",
"WORD wMilliseconds",
]

FILETIME = struct [
"DWORD dwLowDateTime",
"DWORD dwHighDateTime"
]

dlload 'Kernel32'
extern 'void GetSystemTime(LPSYSTEMTIME)'
extern 'void GetSystemTimeAsFileTime(LPFILETIME)'
extern 'void GetLocalTime(LPFILETIME)'
extern 'BOOL FileTimeToSystemTime(LPFILETIME, LPSYSTEMTIME)'
end

def print_system_time(st)
puts(
"#{st.wYear}/#{st.wMonth}/#{st.wDay}(#{st.wDayOfWeek}) " +
"#{st.wHour}:#{st.wMinute}:#{st.wSecond}.#{st.wMilliseconds}")
end

st = DSO::SYSTEMTIME.malloc
print_system_time(st)

ft = DSO::FILETIME.malloc
DSO.getSystemTimeAsFileTime(ft)
DSO.fileTimeToSystemTime(ft, st)
print_system_time(st)

DSO.getSystemTime(st)
print_system_time(st)
出力例
0/0/0(0) 0:0:0.0
2009/4/1(3) 11:8:44.406
2009/4/1(3) 11:8:44.406

require 'dl' してみた ... 便利だった

Win32APIをRuby/DLで呼び出してみた。
Ruby/Win32APIを使う(RubyのWin32APIとUNICODE)よりも簡単。

sample.rb
#!/usr/local/bin/ruby -Ku
# -*- encoding: utf-8 -*-

require 'dl/import'
require 'iconv'

module DSO
extend DL::Importable
dlload 'Kernel32', 'User32'
extern 'int GetTickCount()'
extern 'int MessageBoxA(int, char*, char*, int)'
extern 'int MessageBoxW(int, wchar_t*, wchar_t*, int)'
end

def s(x)
Iconv.iconv('shift_jis', 'utf-8', x + 0.chr)[0]
end

def u(x)
Iconv.iconv('utf-16le', 'utf-8', x + 0.chr)[0]
end

p DSO.getTickCount
p DSO.messageBoxA(0, s('あabc'), s('あabc'), 0)
p DSO.messageBoxW(0, u('あabc'), u('あabc'), 1)

ちなみに、ruby-1.9.1p0(に同梱されていたRuby/DL)では動かない。
  1. DL::ImportableがDL::Importerに
  2. 先頭が大文字の関数名でもそのままexternされるように
という仕様変更があったようだ。

sample_for_ruby-1_9_1.rb
#!/usr/local/bin/ruby -Ku
# -*- encoding: utf-8 -*-

require 'dl/import'
require 'iconv'

module DSO
extend DL::Importer
dlload 'Kernel32', 'User32'
extern 'int GetTickCount()'
extern 'int MessageBoxA(int, char*, char*, int)'
extern 'int MessageBoxW(int, wchar_t*, wchar_t*, int)'
end

def s(x)
Iconv.iconv('shift_jis', 'utf-8', x + 0.chr)[0]
end

def u(x)
Iconv.iconv('utf-16le', 'utf-8', x + 0.chr)[0]
end

p DSO.GetTickCount
p DSO.MessageBoxA(0, s('あabc'), s('あabc'), 0)
p DSO.MessageBoxW(0, u('あabc'), u('あabc'), 1)