Code:
||DLLソースの種別
{define-enum public DLLType
struct, ||構造体
method, ||メソッド
interface ||インタフェースクラス
}
||DLL の型と、Curl の型の変換マップ
{def package type-map =
{{HashTable-of String, String}
||int
"DWORD", "int",
"COLORREF", "int",
||String
"LPCCTSTR", "#String",
"HWND", "CPointer",
"LPCCHOOKPROC", |"{StdcallCallback-to #WindowsHook}"|,
||++
||++ "", "",
||++ "", "",
||++ "", "",
||++ "", "",
"*", ""
}
}
||パラメータの形式
{define-enum public ParamType
out = "_Out_"
,out-option = "_Out_opt_"
,in-out = "_Inout_"
,in = "_In_"
,in-option = "_In_opt_"
}
||DLLの型に対応するCurlの型を返却する
||FIXME
||LPCT ごとに対応すべき?
||L:???
||P:ポインタ
||C :コンスタント
||T :???
{define-proc public {get-type-name
type-name:String
}:String
def ret-type-name =
{if {type-map.key-exists? type-name} then
type-map[type-name]
else
type-name
}
{return ret-type-name}
}
||(rep = CString-type [, max-size = size]) 等対応なし
{define-proc public {get-splited-ary str:String}:StringArray
||空白で区切られた文字を格納
def tmp = {str.split}
def ary = {StringArray}
{for s in tmp do
{if not s.empty? then
{ary.append s}
}
}
{return ary}
}
||特定の文字を削除する
{define-proc public {remove-strings str:String, remove-strings:StringArray}:String
let ret-str:String = str
{for s in remove-strings do
set ret-str = {ret-str.replace-clone s, ""}
}
{return ret-str}
}
||型と変数の名称を取得
{define-proc public {get-type-and-var
tgt-type-name:String,
tgt-var-name :String
}:(type-name:String, var-name:String)
let type-name:String = tgt-type-name
let var-name:String = {remove-strings tgt-var-name, {StringArray ";", ","}}
let pointer?:bool = false
||ポインタを表しているかどうかチェック
|| 型、もしくは変数にアスタリスクがついているかどうか
{if {var-name.find '*'} > -1 or
{type-name.find '*'} > -1
then
set type-name = {type-name.replace-clone "*", ""}
set var-name = {var-name.replace-clone "*", ""}
set pointer? = true
}
||型マップから変換
set type-name = {get-type-name tgt-type-name}
||ポインタ型の場合
{if pointer? then
set type-name = "\{CArray-of " & type-name & "\}"
}
{return type-name , var-name}
}
||構造体の変換
{define-proc public {gerate-curl-from-dll-struct
dll-source:String
}:String
||Curlのソース定義
let curl-source:String = |"{define-C-struct public "|
def clup-dll-source = {dll-source.trim-clone}
def dll-source-lines = {clup-dll-source.split split-chars = '\n'}
{for ln key idx:int in dll-source-lines do
||空白で区切られた文字を格納
def splt-source = {get-splited-ary ln}
{if idx == 0 then
||1行目は構造体の宣言
||①typedef ②struct ③型名 を想定
set curl-source = curl-source & splt-source[2]
else
||最初に「}」が来たら定義の終わりとして処理を終了
{if {splt-source[0].trim-clone}[0] == '\}' then
{break}
}
||①型名 ②変数名 を想定
|| ただし、①が「struct」の場合は、②型名 ③変数名になる(?)
||FIXME 未対応
||固定長、サイズ指定
||ポインタ(*)、アドレス(&)
||参考 http://bituse.info/c/10
let (tmp-type-name:String , tmp-var-name:String) =
{if splt-source[0] == "struct" then
(splt-source[1], splt-source[2])
else
(splt-source[0], splt-source[1])
}
def (type-name:String, var-name:String) =
{get-type-and-var tmp-type-name, tmp-var-name}
set curl-source = curl-source & " field public " & var-name & ":" & type-name
}
set curl-source = curl-source & "\n"
}
set curl-source = curl-source & "\}"
{return curl-source}
}
||メソッドの変換
{define-proc public {gerate-curl-from-dll-method
dll-source:String
}:String
||Curlのソース定義
let curl-source:String = |"{dll-method public "|
def clup-dll-source = {dll-source.trim-clone}
def dll-source-lines = {clup-dll-source.split split-chars = '\n'}
let return-var-name:String = ""
{for ln key idx:int in dll-source-lines do
||空白で区切られた文字を格納
def splt-source = {get-splited-ary ln}
{if idx == 0 then
||1行目はメソッドの宣言
||①戻り値型 ②メソッド名
||ただし、2番目の項目が「WINAPI」の場合、メソッド名は3番目
set return-var-name ={get-type-name splt-source[0]}
let method-name:String =
{if splt-source[1] == "WINAPI" then
splt-source[2]
else
splt-source[1]
}
set method-name = {method-name.replace-clone "(", ""}
set curl-source = curl-source &
{format |"{%s ("%s") "|, method-name, method-name}
else
||最初に「)」が来たら定義の終わりとして処理を終了
{if {splt-source[0].trim-clone}[0] == '\)' then
{break}
}
||①パラメータの形式 ②型 ③パラメータ変数名
def param-type = splt-source[0]
def (type-name:String, var-name:String) =
{get-type-and-var splt-source[1], splt-source[2]}
set curl-source = curl-source &
" " & var-name & ":" & type-name
{switch param-type
case ParamType.in.value ,
ParamType.in-out.value,
ParamType.out.value
do
case ParamType.in-option.value ,
ParamType.out-option.value
do
||オプションの場合は、初期値を指定
set curl-source = curl-source & " = null"
}
set curl-source = curl-source & ","
}
set curl-source = curl-source & "\n"
}
||引数の最後のカンマを削除
{if curl-source[curl-source.size - 2] == ',' then
def tmp-strb = {StringBuf curl-source}
{tmp-strb.remove curl-source.size - 2}
set curl-source = {tmp-strb.to-String}
}
set curl-source = curl-source & " \}:" & return-var-name & "\n\}"
{return curl-source}
}
||インターフェースの変換
{define-proc public {gerate-curl-from-dll-interface
dll-source:String
}:String
{return "インターフェース ┐(´Д`)┌ サッパリ ワカリマセン"}
}
||DLLの定義から、Curlのソースへ変換する
{define-proc public {gerate-curl-from-dll
dll-type:DLLType,
dll-source:String
}:String
let curl-source:String =
{switch dll-type
case DLLType.struct do
{gerate-curl-from-dll-struct dll-source}
case DLLType.method do
{gerate-curl-from-dll-method dll-source}
case DLLType.interface do
{gerate-curl-from-dll-interface dll-source}
else
""
}
{return curl-source}
}
||DLLソースの種別選択用ラジオボタン
{def rdb-strct = {RadioButton label = "構造体", radio-value = DLLType.struct}}
{def rdb-method = {RadioButton label = "メソッド", radio-value = DLLType.method}}
{def rdb-interface = {RadioButton label = "インタフェース", radio-value = DLLType.interface}}
{def rdfr =
{RadioFrame
{HBox
spacing = 10pt,
rdb-strct,
rdb-method,
rdb-interface
}
}
}
{def ta-dll-source =
{TextArea
width = 7in, height = 3in
}
}
{def ta-curl-source =
{TextArea
width = 7in, height = 3in
}
}
{def cb =
{CommandButton
label = "変換",
{on Action do
||DLLソースをCurlソースに変換
{if-non-null rdfr.value then
def curl-source =
{gerate-curl-from-dll
rdfr.value asa DLLType,
ta-dll-source.value
}
set ta-curl-source.value = curl-source
}
}
}
}
{VBox
{HBox spacing = 10pt, rdfr,cb },
ta-dll-source, ta-curl-source
}