本文只作为参考,个人水平有限,望见谅!
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);
}
}
}