Archive for 4月, 2012

  1. Hello, Win32 API(Lua) World!

    Posted on 4月 30th, 2012 by cx20

    Win32 API(Lua)

    Win32 API は、Windows の機能にアクセスする為の API(Application Programming Interface)である。
    以下は Lua にて alien ライブラリを用いた呼出し例である。

    ソースコード

    require "alien"
     
    MessageBox = alien.User32.MessageBoxA
    MessageBox:types{ ret = 'long', abi = 'stdcall', 'long', 'string', 'string', 'long' }
    MessageBox( 0, "Hello, Win32 API(Lua) World!", "Hello, World!", 0 )

    Win32 データ型に対応する Lua の型(alien ライブラリ)としては以下のようなものがある。

    Win32 データ型 C/C++ データ型 Lua
    VOID void void
    INT int int
    UINT unsigned int uint
    DOUBLE double double
    CHAR char char
    LPCSTR const char * string
    LPVOID void * pointer
    PINT int * ref int
    PUINT unsigned int * ref uint
    DOUBLE * double * ref double
    PCHAR char * ref char
    PROC function pointer callback
    SHORT short short
    WORD unsigned short ushort
    BYTE signed char byte
    LONG long long
    DWORD unsigned long ulong
    FLOAT float float

    実行方法

    C:¥> lua hello.lua

    実行結果

    ---------------------------
    Hello, World!
    ---------------------------
    Hello, Win32 API(Lua) World!
    ---------------------------
    OK   
    ---------------------------
  2. Hello, Win32 API(Python) World!

    Posted on 4月 29th, 2012 by cx20

    Win32 API(Python)

    Win32 API は、Windows の機能にアクセスする為の API(Application Programming Interface)である。
    以下は Python にて ctypes ライブラリを使用した呼出し例である。

    ソースコード

    import ctypes
     
    user32 = ctypes.windll.user32
    user32.MessageBoxA( 0, "Hello, Win32 API(Python) World!", "Hello, World!", 0 )

    実行方法

    C:¥> python hello.py

    実行結果

    ---------------------------
    Hello, World!
    ---------------------------
    Hello, Win32 API(Python) World!
    ---------------------------
    OK   
    ---------------------------
  3. Hello, Win32 API(PHP) World!

    Posted on 4月 29th, 2012 by cx20

    Win32 API(PHP)

    Win32 API は、Windows の機能にアクセスする為の API(Application Programming Interface)である。
    以下は PHP にて COM ライブラリである DynamicWrapper を経由した Win32 API の呼出し例である。

    なお、PHP 5.4.5 / 5.3.15 より、COM サポートは既定では組み込まれていない為、使用するには、以下の設定を追加する必要がある。

    PHP 設定

    [COM_DOT_NET]
    extension = php_com_dotnet.dll

    ソースコード

    <?php
    $win32 = new COM("DynamicWrapper");
    $win32->Register( "user32.dll", "MessageBoxA", "i=hhsu", "f=s", "r=l" );
    $win32->MessageBoxA( 0, "Hello, Win32 API(PHP) World!", "Hello, World!", 0 );
    ?>

    なお、上記の “i=hhsu” は各引数の型を、”f=s” は呼び出し規約を、”r=l” は戻り値の型を表している。以下は主要なタイプ一覧である。詳細は「An Automation Object for Dynamic DLL Calls | Dr Dobb’s」を参照のこと。

    タイプ 説明
    a オートメーションオブジェクト(IDispatch*)
    c 符号なし文字型(unsigned char)
    d 倍精度浮動小数点数(double)
    f 単精度浮動小数点数(float)
    k COM オブジェクト(IUnknown*)
    h ハンドル(handle)
    l 整数型(long)
    p ポインタ(pointer)
    s 文字列(string)
    t 整数型(short)
    u 符号なし整数型(unsigned int)
    w ワイド文字列(wide string)

    実行方法

    C:¥> php -f hello.php

    実行結果

    ---------------------------
    Hello, World!
    ---------------------------
    Hello, Win32 API(PHP) World!
    ---------------------------
    OK   
    ---------------------------
  4. Hello, Win32 API(Ruby) World!

    Posted on 4月 28th, 2012 by cx20

    Win32 API(Ruby)

    Win32 API は、Windows の機能にアクセスする為の API(Application Programming Interface)である。
    以下は Ruby の Win32API ライブラリならびに Ruby/DL2(Ruby 1.9 より標準添付)よる呼出し例である。

    ソースコード(Win32API)

    require 'Win32API'
     
    msgbox = Win32API.new('user32', 'MessageBox', ['i', 'p', 'p', 'i'], 'i')
    msgbox.call( 0, "Hello, Win32 API(Ruby) World!", "Hello, World!", 0 )

    なお、上記の [‘i’, ‘p’, ‘p’, ‘i’], ‘i’ は、各引数と戻り値の型を表している。主なタイプとしては以下の種類がある。詳細は「Ruby 1.9.3 リファレンスマニュアル > ライブラリ一覧 > Win32APIライブラリ > Win32APIクラス」を参照のこと。

    タイプ 説明
    “p” ポインタ型(pointer)
    “l” 数値型(long)
    “i” 整数型(integer)
    “v” void 型

    ソースコード(Ruby/DL2)

    require 'dl/import'
    require 'dl/types'
     
    module User32
      extend DL::Importer
      dlload 'user32'
     
      include DL::Win32Types
      extern 'int MessageBoxA(HWND, LPCSTR, LPCSTR, UINT)'
    end
     
    User32.MessageBoxA( 0, "Hello, Windows API(Ruby) World!", "Hello, World!", 0 )

    Ruby/DL2 では、C言語のプロトタイプ宣言を記述することにより、外部ライブラリの利用が可能となっている。

    実行方法

    C:¥> ruby hello.rb

    実行結果

    ---------------------------
    Hello, World!
    ---------------------------
    Hello, Win32 API(Ruby) World!
    ---------------------------
    OK   
    ---------------------------
  5. Hello, Win32 API(Perl) World!

    Posted on 4月 27th, 2012 by cx20

    Win32 API(Perl)

    Win32 API は、Windows の機能にアクセスする為の API(Application Programming Interface)である。
    以下は Perl にて Win32::API モジュールを用いた呼出し例である。

    ソースコード

    use strict;
    use Win32::API;
     
    my $msgbox= Win32::API->new("user32", "MessageBoxA", "NPPN", "N");
       $msgbox->Call( 0, "Hello, Win32 API(Perl) World!", "Hello, World!", 0 );

    なお、上記の “NPPN”, “N” は各引数と戻り値の型を表している。以下は主要なタイプ一覧である。詳細は「Win32::API – search.cpan.org」を参照のこと。

    タイプ 説明
    I 整数型(int)
    N 数値型(long)
    F 単精度浮動小数点数(float)
    D 倍精度浮動小数点数(double)
    C 文字型(char)
    P ポインタ型(文字列、構造体等へのポインタ)
    S 構造体オブジェクト(Win32::API::Struct)
    K コールバックオブジェクト(Win32::API::Callback)

    コンパイル方法

    C:¥> perl hello.pl

    実行結果

    ---------------------------
    Hello, World!
    ---------------------------
    Hello, Win32 API(Perl) World!
    ---------------------------
    OK   
    ---------------------------
  6. Hello, Win32 API(MSIL) World!

    Posted on 4月 26th, 2012 by cx20

    Win32 API(MSIL)

    Win32 API は、Windows の機能にアクセスする為の API(Application Programming Interface)である。
    以下は MSIL による呼出し例である。

    ソースコード

    //  Microsoft (R) .NET Framework IL Disassembler.  Version 4.0.30319.1
    //  Copyright (c) Microsoft Corporation. All rights reserved.
     
    // Metadata version: v2.0.50727
    .module extern user32.dll
    .assembly extern mscorlib
    {
      .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )                         // .zV.4..
      .ver 2:0:0:0
    }
    .assembly Hello
    {
      .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) 
      .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78   // ....T..WrapNonEx
                                                                                                                 63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 )       // ceptionThrows.
      .hash algorithm 0x00008004
      .ver 0:0:0:0
    }
    .module Hello.exe
    // MVID: {412A0088-7664-4361-B59D-98DD5760B045}
    .imagebase 0x00400000
    .file alignment 0x00000200
    .stackreserve 0x00100000
    .subsystem 0x0003       // WINDOWS_CUI
    .corflags 0x00000001    //  ILONLY
    // Image base: 0x00360000
     
    // =============== CLASS MEMBERS DECLARATION ===================
    .class private auto ansi beforefieldinit Hello
           extends [mscorlib]System.Object
    {
      .method private hidebysig static pinvokeimpl("user32.dll" winapi) 
              uint32  MessageBox(uint32 hWnd,
                                 string lpText,
                                 string lpTitle,
                                 uint32 uType) cil managed preservesig
      {
      }
      .method private hidebysig static void  Main(string[] args) cil managed
      {
        .entrypoint
        // コード サイズ       20 (0x14)
        .maxstack  8
        IL_0000:  nop
        IL_0001:  ldc.i4.0
        IL_0002:  ldstr      "Hello, Windows API(MSIL) World!"
        IL_0007:  ldstr      "Hello, World!"
        IL_000c:  ldc.i4.0
        IL_000d:  call       uint32 Hello::MessageBox(uint32,
                                                      string,
                                                      string,
                                                      uint32)
        IL_0012:  pop
        IL_0013:  ret
      } // end of method Hello::Main
     
      .method public hidebysig specialname rtspecialname 
              instance void  .ctor() cil managed
      {
        // コード サイズ       7 (0x7)
        .maxstack  8
        IL_0000:  ldarg.0
        IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
        IL_0006:  ret
      } // end of method Hello::.ctor
     
    } // end of class Hello

    上記のコードは、以下の C# のプログラムを ildasm.exe で逆アセンブルしたものである。

    ソースコード

    using System.Runtime.InteropServices;
     
    class Hello
    {
         [DllImport("user32.dll")]
         private extern static uint MessageBox(uint hWnd, string lpText, string lpTitle, uint uType);
         static void Main(string[] args)
        {
            MessageBox( 0, "Hello, Win32 API(MSIL) World!", "Hello, World!", 0 );
        }
    }

    コンパイル方法

    C:¥> ilasm Hello.il

    実行結果

    ---------------------------
    Hello, World!
    ---------------------------
    Hello, Win32 API(MSIL) World!
    ---------------------------
    OK   
    ---------------------------
  7. Hello, Win32 API(F#) World!

    Posted on 4月 25th, 2012 by cx20

    Win32 API(F#)

    Win32 API は、Windows の機能にアクセスする為の API(Application Programming Interface)である。
    以下は F# にて DllImport 属性を用いた呼出し例である。

    ソースコード

    open System
    open System.Runtime.InteropServices
     
    [<DllImport("user32.dll")>]
    extern int MessageBox( UInt32 hWnd, String lpText, String lpCaption, UInt32 uType)
     
    let x = MessageBox( 0u, "Hello, Win32 API(F#) World!", "Hello, World!", 0u )

    コンパイル方法

    C:¥> fsc Hello.fs

    実行結果

    ---------------------------
    Hello, World!
    ---------------------------
    Hello, Win32 API(F#) World!
    ---------------------------
    OK   
    ---------------------------
  8. Hello, Win32 API(VB.NET) World!

    Posted on 4月 24th, 2012 by cx20

    Win32 API(VB.NET)

    Win32 API は、Windows の機能にアクセスする為の API(Application Programming Interface)である。
    以下は VB.NET にて Declare ステートメントを用いた呼出し例である。

    ソースコード

    Imports System
    Imports System.Runtime.InteropServices
     
    Module Hello
        Declare Auto Function MessageBox Lib "user32.dll" Alias "MessageBox" ( _
            ByVal hWnd As IntPtr, _
            ByVal lpText As String, _
            ByVal lpCaption As String, _
            ByVal nType As UInteger _
        ) As Integer
     
        Sub Main()
            MessageBox( New IntPtr(0), "Hello, Win32 API(VB.NET) World!", "Hello, World!", 0 )
        End Sub
    End Module

    「文字セット」に「Auto」を指定した場合は「エイリアス名」「プラットフォーム」に応じて、呼び出される API 関数名が自動判別される。
    「文字セット」に「Ansi」もしくは「Unicode」を指定した場合は「エイリアス名」が API 関数名として使用される為、”A” / “W” のどちらのバージョンであるか明示的に指定する必要がある。(指定を行わない場合、関数名が見つからずエラーとなる)

    文字セット指定 エイリアス名 プラットフォーム 文字変換 判別 API関数名
    Auto MessageBox Windows 9x系 ANSI “A” MessageBoxA
    Auto MessageBox Windows NT系 Unicode “W” MessageBoxW
    Ansi または 省略 MessageBox ANSI Not Found
    Ansi または 省略 MessageBoxA ANSI MessageBoxA
    Unicode MessageBox Unicode Not Found
    Unicode MessageBoxW Unicode MessageBoxW

    また、Win32 データ型と VB.NET データ型の対応は主に以下のようになっている。「(2.0)」は、.NET Framework 2.0 で追加された型を示す。文字関連の型に関しては文字セット指定が必要なことに注意。

    Win32 データ型 C/C++ データ型 .NET データ型 VB.NET データ型
    HANDLE void * IntPtr
    BYTE unsigned char Byte Byte
    SHORT short Int16 Short
    WORD unsigned short UInt16 UShort (2.0)
    INT int Int32 Integer
    UINT unsigned int UInt32 UInteger (2.0)
    LONG long Int32 Integer
    BOOL int Int32 Integer
    DWORD unsigned long UInt32 UInteger (2.0)
    ULONG unsigned long UInt32 UInteger (2.0)
    CHAR char Char (Ansi) Char (Ansi)
    WCHAR wchar_t Char (Unicode) Char (Unicode)
    LPSTR char * StringBuilder (Ansi)
    LPCSTR const char * String (Ansi) String (Ansi)
    LPWSTR wchar_t * StringBuilder (Unicode)
    LPCWSTR const wchar_t * String (Unicode) String (Unicode)
    FLOAT float Single Single
    DOUBLE double Double Double

    コンパイル方法

    C:¥> vbc Hello.vb

    実行結果

    ---------------------------
    Hello, World!
    ---------------------------
    Hello, Win32 API(VB.NET) World!
    ---------------------------
    OK   
    ---------------------------
  9. Hello, Win32 API(C#) World!

    Posted on 4月 23rd, 2012 by cx20

    Win32 API(C#)

    Win32 API は、Windows の機能にアクセスする為の API(Application Programming Interface)である。
    以下は C# にて DllImport 属性を用いた呼出し例である。

    ソースコード

    using System;
    using System.Runtime.InteropServices;
     
    class Hello
    {
         [DllImport("user32.dll", CharSet=CharSet.Auto)]
         private extern static uint MessageBox(IntPtr hWnd, string lpText, string lpCaption, uint uType);
         static void Main(string[] args)
        {
            MessageBox( new IntPtr(0), "Hello, Win32 API(C#) World!", "Hello, World!", 0 );
        }
    }

    「文字セット」に「Auto」を指定した場合は「関数定義」「プラットフォーム」に応じて、呼び出される API 関数名が自動判別される。
    「文字セット」に「Ansi」もしくは「Unicode」を指定した場合それぞれ、末尾が “A” / “W” の API 関数名として自動判別される。

    文字セット指定 関数定義 プラットフォーム 文字変換 判別 API関数名
    Auto MessageBox Windows 9x系 ANSI “A” MessageBoxA
    Auto MessageBox Windows NT系 Unicode “W” MessageBoxW
    Ansi または 省略 MessageBox ANSI “A” MessageBoxA
    Ansi または 省略 MessageBoxA ANSI MessageBoxA
    Unicode MessageBox Unicode “W” MessageBoxW
    Unicode MessageBoxW Unicode MessageBoxW

    また、Win32 データ型と C# データ型の対応は主に以下のようになっている。文字関連の型に関しては文字セット指定が必要なことに注意。

    Win32 データ型 C/C++ データ型 .NET データ型 C# データ型
    HANDLE void * IntPtr
    BYTE unsigned char Byte byte
    SHORT short Int16 short
    WORD unsigned short UInt16 ushort
    INT int Int32 int
    UINT unsigned int UInt32 uint
    LONG long Int32 int
    BOOL int Int32 int
    DWORD unsigned long UInt32 uint
    ULONG unsigned long UInt32 uint
    CHAR char Char (Ansi) char (Ansi)
    WCHAR wchar_t Char (Unicode) char (Unicode)
    LPSTR char * StringBuilder (Ansi)
    LPCSTR const char * String (Ansi) string (Ansi)
    LPWSTR wchar_t * StringBuilder (Unicode)
    LPCWSTR const wchar_t * String (Unicode) string (Unicode)
    FLOAT float Single float
    DOUBLE double Double double

    コンパイル方法

    C:¥> csc Hello.cs

    実行結果

    ---------------------------
    Hello, World!
    ---------------------------
    Hello, Win32 API(C#) World!
    ---------------------------
    OK   
    ---------------------------
  10. Hello, Win32 API(PowerShell) World!

    Posted on 4月 22nd, 2012 by cx20

    Win32 API(PowerShell)

    Win32 API は、Windows の機能にアクセスする為の API(Application Programming Interface)である。
    以下は PowerShell での P/Invoke による呼出し例である。

    ソースコード

    function Main
    {
       MessageBox 0 "Hello, Win32 API(PowerShell)!" "Hello, World!" 0
    }
     
    ## Invoke a Win32 P/Invoke call. 
    ## http://www.leeholmes.com/blog/2006/07/21/get-the-owner-of-a-process-in-powershell-%e2%80%93-pinvoke-and-refout-parameters/
    function Invoke-Win32([string] $dllName, [Type] $returnType, [string] $methodName,  
       [Type[]] $parameterTypes, [Object[]] $parameters) 
    { 
       ## Begin to build the dynamic assembly 
       $domain = [AppDomain]::CurrentDomain 
       $name = New-Object Reflection.AssemblyName 'PInvokeAssembly' 
       $assembly = $domain.DefineDynamicAssembly($name, 'Run') 
       $module = $assembly.DefineDynamicModule('PInvokeModule') 
       $type = $module.DefineType('PInvokeType', "Public,BeforeFieldInit") 
     
       ## Define the actual P/Invoke method
       $method = $type.DefineMethod($methodName, 'Public,HideBySig,Static,PinvokeImpl',  
          $returnType, $parameterTypes) 
     
       ## Apply the P/Invoke constructor 
       $ctor = [Runtime.InteropServices.DllImportAttribute].GetConstructor([string]) 
       $attr = New-Object Reflection.Emit.CustomAttributeBuilder $ctor, $dllName 
       $method.SetCustomAttribute($attr) 
     
       ## Create the temporary type, and invoke the method. 
       $realType = $type.CreateType() 
       $realType.InvokeMember($methodName, 'Public,Static,InvokeMethod', $null, $null,  
          $parameters) 
    } 
     
    function MessageBox([Int32] $hWnd, [String] $lpText, [String] $lpCaption, [Int32] $uType) 
    { 
       $parameterTypes = [Int32], [String], [String], [Int32]
       $parameters = $hWnd, $lpText, $lpCaption, $uType
     
       Invoke-Win32 "user32.dll" ([Int32]) "MessageBoxA" $parameterTypes $parameters
    } 
     
    . Main

    実行方法

    C:¥> PowerShell -file hello.ps1

    実行結果

    ---------------------------
    Hello, World!
    ---------------------------
    Hello, Win32 API(PowerShell) World!
    ---------------------------
    OK   
    ---------------------------