1. 程式人生 > >如何直接在unity3d中執行.net4.5等高階版本的機器碼

如何直接在unity3d中執行.net4.5等高階版本的機器碼

PE格式,是微軟Win32環境可移植可執行檔案(如exe、dll、vxd、sys和vdm等)的標準檔案格式。
普通Win32應用的PE檔案裡,PE格式的程式碼段裡的程式碼就是程式的主要程式碼了,是以平臺相關的機器碼形式儲存的;而對.NET Assembly而言,其程式碼主體是以MSIL(或者叫CIL)的中間程式碼形式儲存在PE格式的“資源”部分而不是在程式碼部分;其PE格式的程式碼段裡只包含一小塊“樁程式”(stub),負責將程式控制權交給CLR去繼續執行該assembly裡的MSIL程式碼。也就是說,.exe字尾的.NETAssembly的PE格式程式碼段裡其實只有這樣一個函式呼叫:https://www.zhihu.com/question/27124375


_CorExeMain(...)
.dll字尾的則是:
_CorDllMain(...)

unity3D指令碼編譯與執行
把指令碼編譯成.NET dll(動態連結庫)檔案,這些託管程式碼的執行都是在mono的CLR上執行的。當編譯連結的時候,編譯器會根據dll版本號等資訊來判斷是否支援該dll中的程式碼,微軟的.NET 生成的dll是無法通過編譯的,要想執行微軟.NET的程式碼,只有直接生成普通win32格式的檔案,程式碼是與平臺相關的機器碼,而不是依賴於mono的CLR來執行的。

安裝:
1.首先安裝NuGethttp://docs.nuget.org/consume/installing-nuget


2.vs專案->管理NuGet程式包->聯機->nuget.org->搜尋”Unmanaged Exports”安裝
使用方法參見:https://sites.google.com/site/robertgiesecke/Home/uploads/unmanagedexports
提示:
1.必須指定生產程式碼執行的目標平臺x86或者x64(vs專案右鍵->屬性->生成中設定),選擇AnyCPU將會導致輸出失敗(應該同unity3d匹配,否則會出現“DllNotFoundException”錯誤)
2.生成時出現如下錯誤
error : syntax error at token '{' in:

需要設定計算機語言:控制面板->時鐘、語言和區域->更改顯示語言->管理->更改系統區域設定(設定非Unicode程式中所使用的當前語言為:英語(美國))
3.在build的時候需要將製得的dll移除unity,否則會出現
Unhandled Exception: System.Reflection.ReflectionTypeLoadException: The classes in the module cannot be loaded
等一系列錯誤,生成之後將dll放置到data資料夾下面的Plugins中即可。

下面是一個測試例子:
工具為vs2012、unity3d version 4.3.0f4
1.原始碼

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RGiesecke.DllExport;

namespace Unmanaged_ExportsTest
{
    class Program
    {
        [DllExport]
        static int getNum()
        {
            return Environment.ProcessorCount;
        }
    }
}

2.unity中呼叫程式碼

using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;

public class LoadDll : MonoBehaviour {
    [DllImport("Unmanaged ExportsTest",EntryPoint="getNum",CallingConvention=CallingConvention.Cdecl)]
    private static extern int getNum();
    int num;
    void Start () {
        Debug.Log(getNum());
        num=getNum();
    }
    void OnGUI()
    {
        GUILayout.TextArea(num.ToString());
    }
}

`
結果:

ps:1.除錯Unmanaged Exports還發現一種可以使用c++/CLI來實現在c++中呼叫c#的方法,但是該方法依然依賴CLRhttp://http://stackoverflow.com/questions/17127825/c-sharp-unmanaged-exports
2.後面會測試一下.NET4.5並行程式設計的一些特性,看是否適用於unity3d中
3.計算量大的程式碼是否考慮直接編譯成native code 達到類似c++一樣的效能?