Unity中將c#導出DLL動態庫

本文只作爲參考,個人水平有限,望見諒!
C#導出DLL,一開始就想到了將c++代碼做成DLL的方法,各種複製粘貼宏定義,於是就找了一下C#導出DLL的一般方法,和後者如出一折,只是更簡單一些,這裏我就不詳述了。於是乎就想到能不能寫一個腳本,在Unity中可以直接導出動態庫呢?再然後就知道了原來導出動態庫全靠的是.net文件目錄之下的csc.exe,這個程序的作用還不止導出.cs文件的dll,還可以編譯甚至在控制檯裏寫程序,這裏也不詳述了,有興趣的話可以瞭解一下。
代碼原理爲開一個Thread將inspecor中已勾選的.cs文件、Library中的UnityEngine.dll等動態庫以及用戶自定義dll都複製到.net文件夾中,接着執行csc.exe,在輸入流中寫入對以上dll的引用、宏定義define、禁止out警告、導出*.cs文件爲Library,最後再開一個Thread將生成的DLL文件拷貝至目標目錄,並將之前複製進.net文件夾的文件全部刪除。原本嘗試在導出Dll之後 將scene中所有的.cs腳本引用替換成Dll中的引用,最終還是失敗了,希望有高手指點!
下面是代碼,DllExportInspector.cs主要用來自定義inspector,需要將此代碼放入Asset/Editor文件夾中,DllExport.cs用來執行導出方法。

DllExportInspector.cs

using UnityEngine;
using System.Collections;
using UnityEditor;

[CustomEditor(typeof(DllExport))]
public class DllExportInspector:Editor
{
    bool init = false;
    public override void OnInspectorGUI()
    {



        DllExport d = (DllExport)target;

        GUILayout.Space(10);
        EditorGUILayout.LabelField("【代碼文件】");
        foreach(var fn in d.fileList)
            fn.selected=EditorGUILayout.Toggle(fn.name,fn.selected);

        GUILayout.Space(10);
        EditorGUILayout.LabelField("【路徑選擇】");
        d.netPath = EditorGUILayout.TextField("csc文件路徑:",d.netPath);
        d.savePath = EditorGUILayout.TextField("dll保存路徑:", d.savePath);

        GUILayout.Space(10);
        EditorGUILayout.LabelField("【選項設置】");

        GUILayout.BeginHorizontal();
        d.delOrigional = EditorGUILayout.Toggle(d.delOrigional);
        EditorGUILayout.LabelField("是否刪除原文件");
        EditorGUILayout.LabelField("                ");
        GUILayout.EndHorizontal();

        d.mainDLLName = EditorGUILayout.TextField("導出DLL文件名:", d.mainDLLName);

        d.defineString=EditorGUILayout.TextField("#define:", d.defineString);

        GUILayout.Space(20);
        GUILayout.BeginHorizontal();
        string btName = d.isConverting ? "Quit" : "Convert";

        if (GUILayout.Button(btName))
        {
            if (d.isConverting)
                d.Quit();
            else
                d.Convert();
        }
        if (GUILayout.Button("Reset"))
            d.Reset();
        GUILayout.EndHorizontal();

    }
}

DllExport.cs

using UnityEngine;
using UnityEditor;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Diagnostics;
using System.Threading;
using System.Text;


[System.Serializable]
public class FileName
{
    public string fullName;
    public string directoryName;
    public string name;
    public bool selected;

   public FileName(string fName,string dName,string na)
    {
        fullName = fName;
        directoryName = dName;
        name = na;
        selected = true;
    }
}


public class DllExport : MonoBehaviour
{
    [MenuItem("Tools/DllExport")]
    static void AddScript()  {  Selection.activeGameObject.AddComponent<DllExport>(); }


    public string mainDLLName;
    public string netPath;
    public string savePath;
    public string defineString;

    public bool delOrigional;
    public bool isConverting;

    [SerializeField]
    public List<FileName> fileList = new List<FileName>();

    List<FileName> convertList = new List<FileName>();
    List<FileName> sysDllList = new List<FileName>();

    Thread exportThread;
    Thread opFileThread;

    public void Convert()
    {
        UnityEngine.Debug.Log("Convert...");
        sysDllList.Clear();
        convertList.Clear();

        foreach(var fn in fileList)
        {
            if (fn.selected)
                convertList.Add(fn);
        }
        string fPath;
        fPath = Application.dataPath;
        CopyFile(fPath, "*.cs", ref convertList,false);
        CopyFile(fPath, "*.dll", ref sysDllList,true);
        fPath = Application.dataPath.Substring(0, Application.dataPath.Length - 6) + "Library/UnityAssemblies";
        CopyFile(fPath, "*.dll", ref sysDllList,true);

        exportThread = new Thread(ExportFunction);
        exportThread.Start();
        isConverting = true;
    }
    public void Quit()
    {
        if (exportThread != null) exportThread.Abort();
        if (opFileThread != null) opFileThread.Abort();
        UnityEngine.Debug.Log("Quit!");
        isConverting = false;
    }
    public void Reset()
    {
        fileList.Clear();
        mainDLLName = "MainDLL";
        defineString = "EXAMPLE,EXAMPLE";
        netPath = @"C:\Windows\Microsoft.NET\Framework\v3.5";
        GetFiles(new DirectoryInfo(Application.dataPath), "*.cs", ref fileList);
        savePath = Application.dataPath.Substring(0, Application.dataPath.Length - 6).Replace("/", @"\") + @"DllExport\";
        delOrigional = isConverting=false;
    }

    void CopyFile(string path, string partern, ref List<FileName> fList,bool getfile)
    {
        if(getfile)
            GetFiles(new DirectoryInfo(path), partern, ref fList);
        foreach (var fStr in fList)
            File.Copy(fStr.fullName, netPath + @"\" + fStr.name, true);
    }
    void EndConvert()
    {
        foreach (var cn in convertList)
        {
            string trueName = cn.name.Substring(0, cn.name.Length - 3);
            string oPath = netPath + @"\" + trueName + ".dll";
            string sPath = savePath;
            if (!Directory.Exists(sPath))
                Directory.CreateDirectory(sPath);
            sPath += trueName + ".dll";
            if (File.Exists(oPath))
            {
                File.Copy(oPath, sPath, true);
                File.Delete(oPath);
            }
        }
        DeleteFile(ref fileList,delOrigional);
        DeleteFile(ref sysDllList,false);

    }
    void DeleteFile(ref List<FileName> fList,bool delOri)
    {
        foreach (var fn in fList)
        {
            if (delOri && File.Exists(fn.fullName))
                File.Delete(fn.fullName);
            string sPath = netPath + @"\" + fn.name;
            if (File.Exists(sPath))
                File.Delete(sPath);
        }
    }
    bool ExportSingleDll(string referDll, string target, string origion)
    {
        Process p = new Process();
        p.StartInfo.FileName = "cmd.exe";
        p.StartInfo.UseShellExecute = false;
        p.StartInfo.RedirectStandardInput = true;
        p.StartInfo.RedirectStandardOutput = true;
        p.StartInfo.RedirectStandardError = true;
        p.StartInfo.CreateNoWindow = true;
        System.Console.InputEncoding = System.Text.Encoding.UTF8;
        p.Start();
        StreamWriter sw = p.StandardInput;
        p.StandardInput.WriteLine("");
        p.StandardInput.WriteLine("C:");
        p.StandardInput.WriteLine("cd "+netPath);
        p.StandardInput.WriteLine("csc" + referDll + GetDefineStr()+" /out:" + target + " /warn:0" + " /target:library " + origion); // GetReferStr(ref fList, " ")
        sw.Close();
        string logText = p.StandardOutput.ReadToEnd();
        if(logText.Contains("error"))
        {
            UnityEngine.Debug.LogError(logText);
            return false;
        }
        else
        {
            UnityEngine.Debug.Log(logText);
            return true;
        }
    }

    string GetReferStr(ref List<FileName> fList)
    {
        string str = "";
        foreach (var fn in fList)
            str += ToReferStr(fn.name);
        return str;
    }
    string ToReferStr(string str) { return " /r:" + str; }
    string GetDefineStr()
    {
        string str = "";
        string[] deStr = defineString.Split(',');
        foreach (var de in deStr)
            str += (" /define:" + de);
        return str;
    }
    void ExportFunction()
    {
        string mName = mainDLLName + ".dll";
       if( ExportSingleDll(GetReferStr(ref sysDllList), mName, " *.cs"))
        {
            System.Diagnostics.Process.Start("explorer.exe", savePath);
            UnityEngine.Debug.Log("Successful Convert!");
        }
        else
           UnityEngine.Debug.LogError("Fail Convert!");

        mName = mainDLLName + ".cs";
        convertList.Clear();
        convertList.Add(new FileName(mName, savePath, mName));
        opFileThread = new Thread(EndConvert);
        opFileThread.Start();

        isConverting = false;

    }
     void GetFiles(DirectoryInfo directory, string pattern, ref List<FileName> result)
     {
         if (directory.Exists || pattern.Trim() != string.Empty)
         {
             foreach (FileInfo info in directory.GetFiles(pattern))
             {
                 if(info.Name.Equals("DllExport.cs")) continue;
                 if (info.Name.Equals("DllExportInspector.cs")) continue;
                     result.Add(new FileName(info.FullName, info.DirectoryName, info.Name));
             }
             foreach (DirectoryInfo info in directory.GetDirectories())
                 GetFiles(info, pattern, ref result);
         }
     }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章