2011-12-13

lua and 64bit integer

lua 的整數運算很不幸的,只有到 32bit 的範圍(-2,147,483,648 ~ 2,147,483,647),但透過 lnum 之 patch 之後,可支援到 64bit(-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807)底下是 patch 之過程的記錄:

1. 到 這裡 取得 Lua 5.1.4 原始碼。
2. 到 這裡 取得 lua514-lnum-20090417.patch.tgz。
3. 執行 patch 指令 
    a. linux or mac :  
        i. 解壓解 lua 5.1.4 及 lua514-lnum-20090417.patch.tgz
        ii. 把 lua514-lnum-20090417.patch  擺在 lua 5.1.4 之 src 目錄下
        ii. 進到 lua src 檔目錄下
        iii. 執行 patch < lua514-lnum-20090417.patch
    b. windows :
        i. 到 這裡 下載 patch 執行檔
        ii. 解壓解 lua 5.1.4 及 lua514-lnum-20090417.patch.tgz
        ii. 把 lua514-lnum-20090417.patch 和 patch.exe  擺在 lua 5.1.4 之 src 目錄下
        ii. 進到 lua src 檔目錄下
        iii. 假如使用的是 win7, vista 作業系統,須把 patch.exe 改成其它名稱(例如 cc.exe)
        iv. 執行 patch < lua514-lnum.patch(或者 cc < lua514-lnum.patch)
        v. 假如顯示 Assertion failed: hunk, file ../patch-2.5.9-src/patch.c, line 354…訊息: 
            1. 執行 write lua514-lnum-20090417.path
            2. 將會跳出 wordpad 視窗,此時直接按存檔並離開
            3. 重新執行 iv 指令
4. 開啟 luaconf.h,找到下列關鍵字:

/*
@@ LNUM_DOUBLE | LNUM_FLOAT | LNUM_LDOUBLE: Generic Lua number mode
@@ LNUM_INT32 | LNUM_INT64: Integer type (optional)
@@ LNUM_COMPLEX: Define for using 'a+bi' numbers
@*
@* You can combine LNUM_xxx but only one of each group. I.e. 'LNUM_FLOAT
@* LNUM_INT32 LNUM_COMPLEX' gives float range complex numbers, with
@* 32-bit scalar integer range optimized.
*/
/*#define LNUM_DOUBLE*/

5. 在關鍵字下一行加入 #define LNUM_INT64
6. 開始編譯(可參考 這篇

redirect git stdout message

假如現在執行一個 git 指令 “git clone git://github.com/joyent/node” 其顯示的訊息(包含檔案下載的進度)為:


最後完成時顯示為:


若要在 C# 執行上述 git 指令,通常使用 System.Diagnostics.Process 來呼叫執行,其程式碼如下:
static void Main(string[] args)
{

    Process myProcess = new Process();
    ProcessStartInfo info = new ProcessStartInfo("git.exe", "clone git://github.com/joyent/node");
    info.CreateNoWindow = true;
    info.UseShellExecute = false;
    info.RedirectStandardOutput = true;
    info.WorkingDirectory = "";
    myProcess.StartInfo = info;
    myProcess.OutputDataReceived += new DataReceivedEventHandler(myProcess_OutputDataReceived);

    myProcess.Start();
    myProcess.BeginOutputReadLine();

    myProcess.WaitForExit();
    myProcess.Close();

}
static void myProcess_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
    if (!String.IsNullOrEmpty(e.Data))
    {
        Console.WriteLine("captured line> "+e.Data);
    }           
}
執行結果為:
由上圖發現執行過程中,只有顯示一行訊息,猜測是因為 git 在執行時期會呼叫其它的 process,而這些 process 所顯示的訊息未被 redirect 到 C#,下圖是 process explorer 在 git 執行時期所擷取的畫面,發現 git 的確產生 child process 來處理其它工作:

因此若要擷取 child process 顯示的訊息,改用下列指令:
cmd.exe /C “git.exe clone git://github.com/joyent/node –progress 2>&1”
程式碼修改為:
ProcessStartInfo info = new ProcessStartInfo("cmd.exe", "/C " + "" + "git.exe clone git://github.com/joyent/node --progress 2>&1" + "");
執行結果為:

終於把所有的訊息都 redirect 到 C# 了。

2011-11-24

git 使用筆記

刪除所有 .git 資料夾
    find . -type f | grep -i .git | xargs rm
取得程式:
    git clone git://URL
取得最新的程式:
    git pull
目前狀態:
    git status
如果確定 repo 有更新,但使用 git pull 確沒有效果(顯示 Your system reports no Git commands at all.)時使用:
    git fetch origin master:tmp
    git merge tmp

程式修改完之後:
    git add . 
    git commit –a –m '註解'

    git commit -i <file> -m '註解'
刪除沒有被加入到 git 的檔案:
    git clean –d -f
回復上次 commit 前的狀態(包含實際檔案):
    git reset –-hard HEAD^
回復到與 repo 上 origin/master 相同的狀態(包含實際檔案):
    git reset –-hard origin/master
個別檔案回復到 modified 之前的狀態(包含實際檔案):
    git checkout <filename>
個別檔案回復到某次 commit 時的狀態(包含實際檔案):
    git checkout <commit id> <filename>
回復上次 commit 前的狀態(不包含實際檔案):
    git reset –-soft HEAD^
更改 branch 名稱:
    git branch -m <old_name> <new_name>
修改的程式回寫至 repo:
    git push

--------------------
列出 stash 清單
    git stash list
將 working copy 暫存
    git stash
取出最後一次執行暫存的 stash
    git stash pop

--------------------
產生備份
    git bundle create <filename> --all
還原至某目錄
    git clone <filename> <foldername>
    至該 folder 內輸入
    git fetch
    git pull

將現有的 repository push 還原至其它 repository
    git push http://<git repo url> +<current branch>:master

--------------------
收拾失控的 repository (objects/pack/ 資料夾內出現一堆 pack file)
    git gc --aggressive
統計 repository objects
    git count-objects -v

2011-11-13

Objective-C 執行緒同步 ( NSCondition )

撰寫多執行緒程式都會碰到資料同步問題,objc 在這邊可使用 NSCondition 來達成,底下是 NSCondition 與 C#,C++用法比較:
Objective-C 的用法如下: 
NSCondition* pLock =[NSCondition new];
[pLock lock];

    //...
}
[pLock unlock];
[pLock release];



C++ 的用法如下:  HANDLE m_Handle =CreateSemaphore( NULL, 1, 1, L"SemaphoreName" );

WaitForSingleObject( m_Handle, nWaitTime );

    //...
}
ReleaseSemaphore( m_Handle, 1, NULL );
CloseHandle( m_Handle );



C# 的用法如下: 
private static AutoResetEvent m_Handle =new AutoResetEvent( true ); 
m_Handle.WaitOne(); 

    //...
}
m_Handle.Set();
其它有關執行緒同步的文章參考這篇

Objective-C 多執行緒 ( NSOperationQueue )

objc 的 NSOperationQueue 跟 Thread Pool 很類似,用起來也非常的容易,這邊把 Operation 看成 Thread Task , Operation Queue 則看成 Thread Pool 。
底下舉一個簡單的例子:主執行緒使用另一個執行緒印出 “i am taskClass” 字串
//taskClass 負責印出 “i am taskClass” 字串 
@interface taskClass : NSOperation {
}
//main 繼承於 NSOperation, 執行緒啟動時將執行這個函數
-(void) main;
@end


 
@implementation taskClass
-(void) main
{
    NSAutoreleasePool* nsap =[NSAutoreleasePool new];
    NSLog(@"i am taskClass");
    [nsap drain];
}
@end



//主程式
int main (int argc, const char * argv[])
{
    NSAutoreleasePool* nsap =[NSAutoreleasePool new];

    //建立 NSOperationQueue
    NSOperationQueue* nsoq =[NSOperationQueue new];

    //設定最多同時執行的執行緒數
    [nsoq setMaxConcurrentOperationCount:10];

    //建立 taskClass
    taskClass* myTaskClass =[taskClass new];

    //將 taskClass 丟給 NSOperationQueue
    //NSOperationQueue 會分配執行緒去執行 taskClass 的 main 函數

    [nsoq addOperation:myTaskClass];

    //等待 Queue 裡所有的 Operation 執行完畢
    [nsoq waitUntilAllOperationsAreFinished];
   
    [myTaskClass release];
   
    [nsoq release];
   
    [nsap drain];
}
此外,假如 Operation 執行的程式屬於無限迴圈,則在主程式要結束時,可用 cancelAllOperations 函數來通知 Queue 裡的 Operation 中斷迴圈並結束程式,舉例如下:
@interface taskClass : NSOperation {
}
-(void) main;
@end


@implementation taskClass
-(void) main
{
    //檢查 Cancelled 是否為 true, 否則繼續執行
    while ([self isCancelled]==false) {
        //迴圈工作... 
    }
}
@end


//主程式
int main (int argc, const char * argv[])
{
    NSAutoreleasePool* nsap =[NSAutoreleasePool new];

    NSOperationQueue* nsoq =[NSOperationQueue new];
    [nsoq setMaxConcurrentOperationCount:10]; 

    taskClass* myTaskClass =[taskClass new]; 
    [nsoq addOperation:myTaskClass];


    //通知所有執行中的 Operation 中斷執行
    [nsoq cancelAllOperations]; 

    [nsoq waitUntilAllOperationsAreFinished];

    [myTaskClass release];

    [nsoq release];

    [nsap drain];
}

2011-11-07

Objective-C dot(.) 與 arrow(->)

objc 在這裡跟 C++ 一樣,可以透過 (.) 及 (->) 來存取類別(class) 的成員 “變數”,但在 objc 的 property 機制影響之下,有些地方可能會搞不清楚。底下做了一些整理。
假如目前有一個 class 如下:
定義:
@interface classA :NSObject{
@private
    int val;
@public
    int pubVal;
   
}

-(void) initVal: (int) newVal;
-(void) printVal;
@end

實作:
@implementation classA
@synthesize val, pubVal;
-(void) initVal:(int)newVal
{
    val =newVal;
}

-(void) printVal
{
    NSLog(@"val=%d", val);
}

@end
dot(.) 與 arrow(->) 的操作:
classA* bbb =[classA new];
//dot notation
//設定值

bbb.pubVal =5;        //dot 透過 property 機制存取, 同等於 [bbb setPubVal:5];
bbb.val =6;              //dot 透過 property 機制存取, 同等於 [bbb setVal:6];
(*bbb).pubVal =7;    //dot 可直接存取 @public member
//(*bbb).val =8;      //Error, 不是 @public member
//取值
int tmpVal;
tmpVal =bbb.pubVal;      //tmpVal =7,同等於tmpVal =[bbb pubVal];
tmpVal =bbb.val;           //tmpVal =6,同等於tmpVal =[bbb val];
tmpVal =(*bbb).pubVal;  //tmpVal =7
//tmpVal =(*bbb).val;  //Error, 不是 @public member
//arrow notation
//設定值

bbb->pubVal =5;     //arrow 可直接存取 @public member 
//bbb->val =5;             //Error, 不是 @public member
//取值
tmpVal =bbb->pubVal;   //tmpVal =7
//tmpVal =bbb->val;     //Error, 不是 @public member

//使用函數操作
//設定值

[bbb setPubVal:5];  //setPubVal 函數由 property 機制自動產生
[bbb setVal:6];        //setVal 函數由 property 機制自動產生
//取值
tmpVal =[bbb pubVal];
tmpVal =[bbb val];

[bbb initVal:10];
[bbb printVal];

[bbb release];
執行的結果為:
val=10

2011-11-04

Objective-C SEL ( Selector )

暫時先“想像” objc 的 SEL 就像是 C 的函數指標(但在 objc 裡另外還有 IMP, 其定義同等於 C 的函數指標),例如現在有一個類別如下:
定義:
@interface classA :NSObject{
@private
    int val;
}

-(void) initVal: (int) newVal;
-(void) printVal;
@end


實作內容:
@implementation classA
-(void) initVal:(int)newVal
{
    val =newVal;
}

-(void) printVal
{
    NSLog(@"val=%d", val);
}

@end
SEL ( Selector ) 的操作範例如下:
id ppp =[classA new];
[ppp initVal:99];
SEL printPP1 =@selector(printVal);
SEL printPP2 =NSSelectorFromString(@"printVal");

if ([ppp respondsToSelector:printPP1])
    [ppp performSelector:printPP1];

if ([ppp respondsToSelector:printPP2])
    [ppp performSelector:printPP2];

[ppp release];
其中的 printPP1, printPP2 皆指向 classAprintVal 函數, 因此 SEL 的產生方式可以有 @selector 或是 NSSelectorFromString 兩種。
執行的結果為:
val=99
val=99

2011-07-23

freeimage + DDS ( nvidia texture tools )

前段時間遇到一個需求是把 bmp, png 轉成 dds 格式,且在過程中自動把 bmp, png 的圖形放大到二的冪次方大小。 

後來使用兩套工具解決這個需求:
  • Freeimage 來做圖檔的讀取工具,
  • nvidia 提供的 texture tools 來做圖檔的格式轉換及壓縮工具,
freeimage library 提供方便快速的圖形讀取和寫入功能,但對(DirectX Surface)DDS 格式的支援只有到讀取的程度,致使無法儲存 DDS 格式檔案。texture tools 則是提供簡單的圖檔讀取及完整的 DDS 檔案格式支援,其 DDS 支援的部分剛好可以補足 freeimage 在支援 DDS 格式不足之處。

底下為把圖片轉成 DDS 格式的簡單實作:

1) 載入圖檔  (src.jpg):
std::string filename("src.jpg");
FREE_IMAGE_FORMAT fif =FreeImage_GetFileType( filename.c_str() );
FIBITMAP* dib =NULL;
dib = FreeImage_Load( fif, filename.c_str() );

2) 將圖檔轉成 RGBA 32bit 格式:
FIBITMAP* dib32 = FreeImage_ConvertTo32Bits(dib);

3) 取得圖形資料:
int nWidth =FreeImage_GetWidth(dib);
int nHeight =FreeImage_GetHeight(dib);
BYTE* pSrcDIB =FreeImage_GetBits(dib32);

4) 設定欲壓縮的圖形資料格式
nvtt::InputOptions inputOptions;
inputOptions.setTextureLayout(nvtt::TextureType_2D, nWidth, nHeight);
inputOptions.setMipmapData(pSrcDIB, nWidth, nHeight);
inputOptions.setFormat(nvtt::InputFormat_BGRA_8UB);

inputOptions.setWrapMode(nvtt::WrapMode_Clamp);
inputOptions.setAlphaMode(nvtt::AlphaMode_Transparency);

inputOptions.setNormalMap(false);
inputOptions.setConvertToNormalMap(false);
inputOptions.setGamma(2.2f, 2.2f);
inputOptions.setNormalizeMipmaps(false);

inputOptions.setMipmapGeneration(false);

5) 設定 DDS 檔格式,此處使用的是 DXT1a 格式
nvtt::CompressionOptions compressionOptions;
compressionOptions.setFormat(nvtt::Format_DXT1a);
//compressionOptions.setQuality(nvtt::Quality_Fastest);
//compressionOptions.setQuality(nvtt::Quality_Normal);
//compressionOptions.setQuality(nvtt::Quality_Production);
compressionOptions.setQuality(nvtt::Quality_Highest);

6) 壓縮並儲存成 DDS 檔 (dst.dds):
nvtt::OutputOptions outputOptions;
outputOptions.setFileName("dst.dds");

nvtt::Compressor compressor;
compressor.enableCudaAcceleration(false);
compressor.process(inputOptions, compressionOptions, outputOptions);

7) 最後不忘刪除記憶體:
FreeImage_Unload(dib32);
FreeImage_Unload(dib);

2011-05-15

TextEdit 上字型會自動更換的問題

中文版 OSX SnowLeopard 上 TextEdit 的預設字型是 Heiti TC,它在英文字的呈現上不易閱讀,可以在 TextEdit --> Preferences --> Font 的地方更改成比較容易閱讀的字型,但惡夢來了,文字輸入的過程中若輸入中文之後再輸入英文,字型會被自動改回 Heiti TC,但 Preferences --> Font 裡仍然是自己設定的字型,網路上也 有人 提出一樣的問題這邊 也提到...
Snow Leopard 增加了一項自作聰明的新設計-會偵測目前使用的輸入法切換字體,也就是,就算你切換到英文或其他語系,但是當你在「文字編輯」(TextEdit)等軟體中,只要是使用繁體中文語系輸入法打字,輸出的文字就會自動切換以 Heiti TC 顯示…。

個人認為...

其實是因為設定的字型無法顯示目前輸入法所輸入的字,所以為了顯示該字,才又跳回預設的字型。

發生在我這裡的情況是將字型設定成 Consolas 之後,輸入中文再輸入英文,英文字的字型就變成 Heiti TC,原因是 Consolas 不是 Unicode 字型 的 unicode set 裡不包含中文字,無法顯示中文,後來使用雅黑-Consolas混合字體就不再出現字型被切換回 Heiti TC 的問題了。

2011-05-01

Unity 3D 將程式部署在 iOS 4.3.2 (iphone4) 上執行

最近建立了在 ios 上開發 unity3d 程式的環境,建立過程大概敘述如下:

1) 作業系統 OSX 10.6.7 + Xcode 4.0,手機部分為 iOS4.3.2。
2) 參考這個連結,設定 Xcode (http://www.alexwhittemore.com/?p=398)。
    連結內前兩項的意思是:
        a) 對 iOS4.3.2 進行 JB 動作,完成之後安裝 AppSync for 4.0+ 軟體。
        b) 在 mac 上建立一個 Certificate:
            i) 在功能表執行 Keychain Access --> Certificate Assistant --> Create a Certificate 。
            ii) Name 的部分設定為 "iPhone Developer"。
                Identity Type 為 Self Signed Root。
                Certificate Type 為 Code Signing。
                將 Let me override defaults 打勾。
            iii) Serial Number : 1
                Validity Period (days): 3650
            iv) 一直按下一步到底。

3) 完成 2) 所提供連結之後續步驟(3~7)。
    步驟到這邊就已足夠用 Xcode 開發一般的 iOS Project 。

4) 在 unity3D 下建立 project 並 switch platform 至 ios。
5) Player Settings --> Other Settings --> Bundle Identifier 設定為 my.company.[project name](注意前段 my.company 部分與 3) 中的 script 一致。 

6) Target Platform 設定為 Universal armv6 + armv7
7) SDK Version 設定為 iOS latest
8) Target iOS Version 設定為 4.2
9) 按下 Build And Run 之後將自動生成 Xcode project 且被 Xcode 開啟。
10) 在 Xcode 下重覆 3) 步驟。
11) 在 Build Settings 頁面下的 Code Signing 項目裡的 Code Signing Identity 全設定成 Any iOS SDK : Don't Code Sign。

12) Summary 的 Deployment Target 改成 4.3
13) 按下 Run (在 Stop 右方的下拉式功能表選擇 Unity-iPhone | [device name] (4.3.2)

2011-04-26

NodeJS 在 mac 上的安裝, 刪除

node.js 可以在 http://nodejs.org/ 取得。
解壓縮之後,在 nodejs 目錄下輸入下列指令:
1) ./configure
2) make
3) sudo make install

刪除 nodejs 的指令:
1) make uninstall

update 20110429:
或是透過 mac port 也可以安裝 nodejs。
1) sudo port install nodejs 即可

透過 mac port 刪除 nodejs 的指令
1) sudo port uninstall nodejs

但在安裝前須先安裝 mac port (http://www.macports.org/install.php)。

mac port 一些指令:

1) port selfupdate 檢查更新
2) port installed 檢查已安裝項目
3) port search [item] 搜尋可安裝項目 (例 port search nodejs)
4) port install [item] 安裝項目
5) port uninstall [item] 反安裝項目

2011-03-08

Unity 3D 非對稱投影

透過修改投影矩陣可以達到非對稱的透視投影效果,下圖是正常的透視投影結果:

正常的透視矩陣所投影的結果

若是我們直接移動攝影機位置讓這三個圖柱向左偏移(攝影機向右偏),將得到結果如下圖:

圖柱向左移動但扭曲變形

雖然圓柱向左偏移,但因為透視投影矩陣的關係產生扭曲變形的結果。若要使圓柱偏移且不扭曲變形,以此例在 Unity3D 而言,修改投影矩陣的 m02 元素即可:

修改過的投影矩陣


2011-02-24

Unity 3D 和 CodePage 950

在 Unity 裡使用 System.Text.Encoding 功能時,如果 CodePage 設定成 950 (BIG-5) 的話,各位可能會發現,在編輯器下執行沒有問題(甚至預設的 CodePage 就是 950),但將程式編譯為執行檔之後執行會得到類似的訊息:

System.NotSupportedException: CodePage 950 not supported
  at System.Text.Encoding.GetEncoding (Int32 codepage) [0x00000] in <filename unknown>:0
  ...

而且預設的 CodePage 變成 UTF8 @@

參考這篇討論,原因是少了幾個動態連結檔,將 C:\Program Files\Unity\Editor\Data\Mono\lib\mono\unity 目錄下的 I18N.dll 和 I18N.CJK.dll 複製到編譯結果的目錄裡即可排除上述情況(與 System.Data.dll 同目錄)。

2011-01-22

Mac OS 睡眠之後無法 umount(eject) smb 目錄或連上 smb 的問題

根據這篇連結,MAC OS 進入睡眠再醒來之後會遇到類似的問題:

1. 原本 mount 的 smb 分享目錄無法存取也無法 eject。
2. 無法再連到 smb server,也找不到 smb server 分享的目錄。

這裡把這篇連結提出的解決方法做個筆記如下:

sudo sysctl -w net.inet.tcp.delayed_ack=0
defaults write com.apple.desktopservices DSDontWriteNetworkStores true

2011-01-05

Windows Message in the Unity3D : WndProc

先前提到可以用 Hooks 的方法在 Unity 裡監控 Windows Message,但是使用 Hooks 這個方法我們沒辦法更改 Message 的內容。因此這邊提出第二個方式。Windows 傳送 Message 給 Unity 時,會呼叫 Unity 預設的 Message 處理函數,但透過函數:

pOldWndProc =(WNDPROC)SetWindowLong(hWnd, GWL_WNDPROC, (LONG)SubWndProc);

我們可以將原本 Windows 呼叫 Unity 預設的 Message 處理函數改為呼叫我們指定的函數,指定的函數把我們想要處理的 Message 處理完,再把剩下的 Message 丟回給 Unity 來處理。

原本實作是使用 dllimport 讓 SetWindowLong function 可以在 C# 裡呼叫, 並把整個 callback function 及流程實作出來,且測試時運作都相當正常,但程式在關閉時會出現 Access Violation 的錯誤,後來將整個實作改成 C DLL 之後錯誤才沒有出現,不知道是什麼原因?底下是 DLL 部分的原始碼:
#include "stdafx.h"
LRESULT CALLBACK SubWndProc(
 HWND hWnd, 
 UINT nMessage, 
 WPARAM wParam, LPARAM lParam); 
 
 WNDPROC  gOldWndProc = NULL; 
 HWND  gUnityWnd = NULL; 
 
 #ifdef    __cplusplus
 extern "C" {
 #endif    /*    __cplusplus    */
 
 __declspec(dllexport) bool __stdcall init(HWND hWnd)
 {
  gOldWndProc =(WNDPROC)SetWindowLong(hWnd, GWL_WNDPROC, (LONG)SubWndProc);
  gUnityWnd =hWnd;
 
  if (gOldWndProc !=NULL)
   return true;
 
  return false;
 }
 
 __declspec(dllexport) void __stdcall release()
 {
  SetWindowLong(gUnityWnd, GWL_WNDPROC, (LONG)gOldWndProc);
  gOldWndProc =0;
  gUnityWnd =0;
 }
 
#ifdef    __cplusplus
}
#endif    /*    __cplusplus    */
 
 
LRESULT CALLBACK SubWndProc(
 HWND hWnd, 
 UINT nMessage, 
 WPARAM wParam, LPARAM lParam)
 {
  switch(nMessage)
  {
   case WM_IME_SETCONTEXT:
   case WM_IME_STARTCOMPOSITION:
   case WM_IME_ENDCOMPOSITION:
   case WM_IME_COMPOSITION:
   case WM_IME_REQUEST:
   {
    //...
   }
   break;
 }
 return CallWindowProc(gOldWndProc, hWnd, nMessage, wParam, lParam);
}

Unity 可以透過呼叫 DLL 提供的 init() 函數,讓 Windows 改為呼叫我們指定的函數 (SubWndProc) 來處理 Message,透過 release() 函數讓 Message 處理流程復原。底下是 Unity 部分的原始碼(DLL 檔名為 UnityIMEDLL.dll 且檔案放在 Assets/Plugins 目錄下)
using UnityEngine;
 
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
 
public class IMEInputBox : MonoBehaviour
{
    //-----------------------------------------------------------
    [DllImport("UnityIMEDLL")]
    protected static extern bool init(IntPtr hWnd);
 
    [DllImport("UnityIMEDLL")]
    protected static extern void release();
 
    [DllImport("user32")]
    protected static extern IntPtr GetActiveWindow();
 
    //-----------------------------------------------------------
    // Use this for initialization
    void Start ()
    {
        Debug.Log("init UnityIMEDLL.");
        try
        {
            init(GetActiveWindow());
        }
        catch (Exception e)
        {
            Debug.Log(e.ToString());
        }
    }
 
    void OnDisable()
    {
        Debug.Log("release UnityIMEDLL.");
        try
        {
            release();
        }
        catch (Exception e)
        {
            Debug.Log(e.ToString());
        }
    }
}