Thread Rating:
  • 449 Vote(s) - 2.86 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Win32API を利用するには?
04-28-2014, 12:43 PM, (This post was last modified: 04-28-2014, 01:49 PM by umemura.)
#5
RE: Win32API を利用するには?
下記のサイトのDLL宣言文のフォーマットを対象にした、
簡易なDLLインタフェースの自動生成用ロジックを組んでみました。

■MSDN
http://msdn.microsoft.com/en-us/library/...s.85).aspx

DLLで定義される型が、Curl ではどんな型になるのかがわからないので、
もし知っている方がいらっしゃったら教えてください。

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
}


Messages In This Thread
Win32API を利用するには? - by umemura - 04-23-2014, 04:06 PM
RE: Win32API を利用するには? - by hokada - 04-24-2014, 02:10 PM
RE: Win32API を利用するには? - by kay - 12-12-2016, 10:32 AM
RE: Win32API を利用するには? - by umemura - 04-28-2014, 12:43 PM
Forum Jump:


Users browsing this thread:
1 Guest(s)

MyBB SQL Error

MyBB has experienced an internal SQL error and cannot continue.

SQL Error:
1017 - Can't find file: 'mybb_threadviews' (errno: 2)
Query:
INSERT INTO mybb_threadviews (tid) VALUES('1077')