[new] MonoPInvokeCallback支持任意签名的函数

[refactor] 重构模板文件,除去重复。统一调整生成文件的输出目录到 hybridclr/generated
main
walon 2022-10-17 21:38:39 +08:00
parent 9ea240ab82
commit d8e155dc25
24 changed files with 204 additions and 279 deletions

View File

@ -1,5 +1,3 @@
#include "MethodBridge.h"
#include <codegen/il2cpp-codegen-metadata.h> #include <codegen/il2cpp-codegen-metadata.h>
#include "vm/ClassInlines.h" #include "vm/ClassInlines.h"
#include "vm/Object.h" #include "vm/Object.h"
@ -8,14 +6,15 @@
#include "../metadata/MetadataModule.h" #include "../metadata/MetadataModule.h"
#include "../metadata/MetadataUtil.h" #include "../metadata/MetadataUtil.h"
#include "Interpreter.h" #include "../interpreter/MethodBridge.h"
#include "MemoryUtil.h" #include "../interpreter/Interpreter.h"
#include "InstrinctDef.h" #include "../interpreter/MemoryUtil.h"
#include "../interpreter/InstrinctDef.h"
using namespace hybridclr::interpreter; using namespace hybridclr::interpreter;
#if HYBRIDCLR_ABI_ARM_64 #if {PLATFORM_ABI}
//!!!{{INVOKE_STUB //!!!{{CODE
//!!!}}INVOKE_STUB //!!!}}CODE
#endif #endif

View File

@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 1249fb131a848a14f8dd0938e3cc2558
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,21 +0,0 @@
#include "MethodBridge.h"
#include <codegen/il2cpp-codegen-metadata.h>
#include "vm/ClassInlines.h"
#include "vm/Object.h"
#include "vm/Class.h"
#include "../metadata/MetadataModule.h"
#include "../metadata/MetadataUtil.h"
#include "Interpreter.h"
#include "MemoryUtil.h"
#include "InstrinctDef.h"
using namespace hybridclr::interpreter;
#if HYBRIDCLR_ABI_UNIVERSAL_32
//!!!{{INVOKE_STUB
//!!!}}INVOKE_STUB
#endif

View File

@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: e06e14385d246aa4ab853d3fd04d6eec
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,21 +0,0 @@
#include "MethodBridge.h"
#include <codegen/il2cpp-codegen-metadata.h>
#include "vm/ClassInlines.h"
#include "vm/Object.h"
#include "vm/Class.h"
#include "../metadata/MetadataModule.h"
#include "../metadata/MetadataUtil.h"
#include "Interpreter.h"
#include "MemoryUtil.h"
#include "InstrinctDef.h"
using namespace hybridclr::interpreter;
#if HYBRIDCLR_ABI_UNIVERSAL_64
//!!!{{INVOKE_STUB
//!!!}}INVOKE_STUB
#endif

View File

@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 2965fa89651ee0c4eb4c4fdcf95b76b8
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,32 @@
#include "../metadata/ReversePInvokeMethodStub.h"
#include "../metadata/MetadataModule.h"
namespace hybridclr
{
namespace metadata
{
#if {PLATFORM_ABI}
//!!!{{CODE
void __ReversePInvokeMethod_0(void* xState)
{
CallLuaFunction(xState, 0);
}
void __ReversePInvokeMethod_1(void* xState)
{
CallLuaFunction(xState, 1);
}
Il2CppMethodPointer s_ReversePInvokeMethodStub[]
{
(Il2CppMethodPointer)__ReversePInvokeMethod_0,
(Il2CppMethodPointer)__ReversePInvokeMethod_1,
nullptr,
};
//!!!}}CODE
#endif
}
}

View File

@ -1,37 +0,0 @@
#include "ReversePInvokeMethodStub.h"
#include "MetadataModule.h"
namespace hybridclr
{
namespace metadata
{
void CallLuaFunction(void* xState, int32_t wrapperIndex)
{
const MethodInfo* method = MetadataModule::GetMethodInfoByReversePInvokeWrapperIndex(wrapperIndex);
typedef void (*Callback)(void* xState, const MethodInfo* method);
((Callback)(method->methodPointerCallByInterp))(xState, method);
}
//!!!{{REVERSE_PINVOKE_METHOD_STUB
void __ReversePInvokeMethod_0(void* xState)
{
CallLuaFunction(xState, 0);
}
void __ReversePInvokeMethod_1(void* xState)
{
CallLuaFunction(xState, 1);
}
Il2CppMethodPointer s_ReversePInvokeMethodStub[]
{
(Il2CppMethodPointer)__ReversePInvokeMethod_0,
(Il2CppMethodPointer)__ReversePInvokeMethod_1,
nullptr,
};
//!!!}}REVERSE_PINVOKE_METHOD_STUB
}
}

View File

@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 6447cdc1825eeef49a3679545ac31d95
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

22
Editor/ABI/ABIUtil.cs Normal file
View File

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HybridCLR.Editor.ABI
{
public static class ABIUtil
{
public static string GetHybridCLRPlatformMacro(PlatformABI abi)
{
switch(abi)
{
case PlatformABI.Arm64: return "HYBRIDCLR_ABI_ARM_64";
case PlatformABI.Universal64: return "HYBRIDCLR_ABI_UNIVERSAL_64";
case PlatformABI.Universal32: return "HYBRIDCLR_ABI_UNIVERSAL_32";
default: throw new NotSupportedException();
}
}
}
}

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 69e748de769c24948afd4f8a9df82b8c guid: edeb86f4b5b13ca4cb0fe9d87ce509bb
MonoImporter: MonoImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2

View File

@ -11,20 +11,21 @@ namespace HybridCLR.Editor.ABI
{ {
public class MethodDesc : IEquatable<MethodDesc> public class MethodDesc : IEquatable<MethodDesc>
{ {
public string Sig { get; private set; }
public MethodDef MethodDef { get; set; } public MethodDef MethodDef { get; set; }
public ReturnInfo ReturnInfo { get; set; } public ReturnInfo ReturnInfo { get; set; }
public List<ParamInfo> ParamInfos { get; set; } public List<ParamInfo> ParamInfos { get; set; }
private int _hashCode;
public void Init() public void Init()
{ {
for(int i = 0; i < ParamInfos.Count; i++) for(int i = 0; i < ParamInfos.Count; i++)
{ {
ParamInfos[i].Index = i; ParamInfos[i].Index = i;
} }
Sig = CreateCallSigName();
} }
public void TransfromSigTypes(Func<TypeInfo, bool, TypeInfo> transformer) public void TransfromSigTypes(Func<TypeInfo, bool, TypeInfo> transformer)
@ -65,45 +66,12 @@ namespace HybridCLR.Editor.ABI
public bool Equals(MethodDesc other) public bool Equals(MethodDesc other)
{ {
if (other == null) return Sig == other.Sig;
{
return false;
}
if (!ReturnInfo.Type.Equals(other.ReturnInfo.Type))
{
return false;
}
if (ParamInfos.Count != other.ParamInfos.Count)
{
return false;
}
for(int i = 0; i < ParamInfos.Count; i++)
{
if (!ParamInfos[i].Type.Equals(other.ParamInfos[i].Type))
{
return false;
}
}
return true;
} }
public override int GetHashCode() public override int GetHashCode()
{ {
if (_hashCode != 0) return Sig.GetHashCode();
{
return _hashCode;
}
int hash = 17;
hash = hash * 23 + ReturnInfo.Type.GetHashCode();
foreach(var p in ParamInfos)
{
hash = hash * 23 + p.Type.GetHashCode();
}
return _hashCode = hash;
} }
} }
} }

View File

@ -28,20 +28,6 @@ namespace HybridCLR.Editor.Commands
Directory.Delete(il2cppBuildCachePath, true); Directory.Delete(il2cppBuildCachePath, true);
} }
private static string GetTemplateCode(PlatformABI platform)
{
string tplFile;
switch (platform)
{
case PlatformABI.Universal32: tplFile = "Universal32"; break;
case PlatformABI.Universal64: tplFile = "Universal64"; break;
case PlatformABI.Arm64: tplFile = "Arm64"; break;
default: throw new NotSupportedException();
};
return File.ReadAllText($"{SettingsUtil.TemplatePathInPackage}/MethodBridge_{tplFile}.cpp.txt");
}
private static void GenerateMethodBridgeCppFile(Analyzer analyzer, PlatformABI platform, string templateCode, string outputFile) private static void GenerateMethodBridgeCppFile(Analyzer analyzer, PlatformABI platform, string templateCode, string outputFile)
{ {
var g = new Generator(new Generator.Options() var g = new Generator(new Generator.Options()
@ -84,18 +70,11 @@ namespace HybridCLR.Editor.Commands
analyzer.Run(); analyzer.Run();
var generateJobs = new List<(PlatformABI, string)>()
{
(PlatformABI.Arm64, "MethodBridge_Arm64"),
(PlatformABI.Universal64, "MethodBridge_Universal64"),
(PlatformABI.Universal32, "MethodBridge_Universal32"),
};
var tasks = new List<Task>(); var tasks = new List<Task>();
foreach (var (platform, stubFile) in generateJobs) string templateCode = File.ReadAllText($"{SettingsUtil.TemplatePathInPackage}/MethodBridgeStub.cpp");
foreach (PlatformABI platform in Enum.GetValues(typeof(PlatformABI)))
{ {
string templateCode = GetTemplateCode(platform); string outputFile = $"{SettingsUtil.GeneratedCppDir}/MethodBridge_{platform}.cpp";
string outputFile = $"{SettingsUtil.MethodBridgeCppDir}/{stubFile}.cpp";
tasks.Add(Task.Run(() => tasks.Add(Task.Run(() =>
{ {
GenerateMethodBridgeCppFile(analyzer, platform, templateCode, outputFile); GenerateMethodBridgeCppFile(analyzer, platform, templateCode, outputFile);

View File

@ -1,6 +1,7 @@
using HybridCLR.Editor.ABI; using HybridCLR.Editor.ABI;
using HybridCLR.Editor.Link; using HybridCLR.Editor.Link;
using HybridCLR.Editor.Meta; using HybridCLR.Editor.Meta;
using HybridCLR.Editor.ReversePInvokeWrap;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
@ -24,28 +25,21 @@ namespace HybridCLR.Editor.Commands
using (var cache = new AssemblyCache(MetaUtil.CreateBuildTargetAssemblyResolver(EditorUserBuildSettings.activeBuildTarget))) using (var cache = new AssemblyCache(MetaUtil.CreateBuildTargetAssemblyResolver(EditorUserBuildSettings.activeBuildTarget)))
{ {
var analyzer = new ReversePInvokeWrap.Analyzer(cache, SettingsUtil.HotUpdateAssemblyNames); var analyzer = new ReversePInvokeWrap.Analyzer(cache, SettingsUtil.HotUpdateAssemblyNames);
var methods = analyzer.CollectMonoPInvokeCallbackMethods(); analyzer.Run();
foreach (var method in methods)
string templateCode = File.ReadAllText($"{SettingsUtil.TemplatePathInPackage}/ReversePInvokeMethodStub.cpp");
foreach (PlatformABI abi in Enum.GetValues(typeof(PlatformABI)))
{ {
Debug.Log($"method:{method.Method}"); string outputFile = $"{SettingsUtil.GeneratedCppDir}/ReversePInvokeMethodStub_{abi}.cpp";
List<ABIReversePInvokeMethodInfo> methods = analyzer.BuildABIMethods(abi);
Debug.Log($"GenerateReversePInvokeWrapper. abi:{abi} wraperCount:{methods.Sum(m => m.Count)} output:{outputFile}");
var generator = new Generator();
generator.Generate(templateCode, abi, methods, outputFile);
} }
var generateJobs = new List<(PlatformABI, string)>()
{
(PlatformABI.Arm64, "HYBRIDCLR_ABI_ARM_64"),
(PlatformABI.Universal64, "HYBRIDCLR_ABI_UNIVERSAL_64"),
(PlatformABI.Universal32, "HYBRIDCLR_ABI_UNIVERSAL_32"),
};
} }
return; MethodBridgeGeneratorCommand.CleanIl2CppBuildCache();
//string ReversePInvokeWrapperStubFile = $"{SettingsUtil.LocalIl2CppDir}/libil2cpp/hybridclr/metadata/ReversePInvokeMethodStub.cpp";
//string wrapperTemplateStr = File.ReadAllText($"{SettingsUtil.TemplatePathInPackage}/ReversePInvokeMethodStub.cpp.txt");
//int wrapperCount = SettingsUtil.HybridCLRSettings.ReversePInvokeWrapperCount;
//var generator = new Generator();
//generator.Generate(wrapperTemplateStr, wrapperCount,ReversePInvokeWrapperStubFile);
//Debug.Log($"GenerateReversePInvokeWrapper. wraperCount:{wrapperCount} output:{ReversePInvokeWrapperStubFile}");
//MethodBridgeGeneratorCommand.CleanIl2CppBuildCache();
} }
} }
} }

View File

@ -30,6 +30,8 @@ namespace HybridCLR.Editor.MethodBridge
public IReadOnlyCollection<GenericMethod> GenericMethods { get; set; } public IReadOnlyCollection<GenericMethod> GenericMethods { get; set; }
} }
private PlatformABI _platformABI;
private readonly IReadOnlyList<MethodDef> _notGenericMethods; private readonly IReadOnlyList<MethodDef> _notGenericMethods;
private readonly IReadOnlyCollection<GenericMethod> _genericMethods; private readonly IReadOnlyCollection<GenericMethod> _genericMethods;
@ -56,6 +58,7 @@ namespace HybridCLR.Editor.MethodBridge
public Generator(Options options) public Generator(Options options)
{ {
_platformABI = options.PlatformABI;
_notGenericMethods = options.NotGenericMethods; _notGenericMethods = options.NotGenericMethods;
_genericMethods = options.GenericMethods; _genericMethods = options.GenericMethods;
_templateCode = options.TemplateCode; _templateCode = options.TemplateCode;
@ -98,26 +101,20 @@ namespace HybridCLR.Editor.MethodBridge
private void AddManaged2NativeMethod(MethodDesc method) private void AddManaged2NativeMethod(MethodDesc method)
{ {
if (_managed2nativeMethodSet.Add(method)) method.Init();
{ _managed2nativeMethodSet.Add(method);
method.Init();
}
} }
private void AddNative2ManagedMethod(MethodDesc method) private void AddNative2ManagedMethod(MethodDesc method)
{ {
if (_native2managedMethodSet.Add(method)) method.Init();
{ _native2managedMethodSet.Add(method);
method.Init();
}
} }
private void AddAdjustThunkMethod(MethodDesc method) private void AddAdjustThunkMethod(MethodDesc method)
{ {
if (_adjustThunkMethodSet.Add(method)) method.Init();
{ _adjustThunkMethodSet.Add(method);
method.Init();
}
} }
private void ProcessMethod(MethodDef method, List<TypeSig> klassInst, List<TypeSig> methodInst) private void ProcessMethod(MethodDef method, List<TypeSig> klassInst, List<TypeSig> methodInst)
@ -200,7 +197,7 @@ namespace HybridCLR.Editor.MethodBridge
public void Generate() public void Generate()
{ {
var frr = new FileRegionReplace(_templateCode); var frr = new FileRegionReplace(_templateCode.Replace("{PLATFORM_ABI}", ABIUtil.GetHybridCLRPlatformMacro(_platformABI)));
List<string> lines = new List<string>(20_0000); List<string> lines = new List<string>(20_0000);
@ -228,7 +225,7 @@ namespace HybridCLR.Editor.MethodBridge
_platformAdaptor.GenerateAdjustThunkStub(_adjustThunkMethodList, lines); _platformAdaptor.GenerateAdjustThunkStub(_adjustThunkMethodList, lines);
frr.Replace("INVOKE_STUB", string.Join("\n", lines)); frr.Replace("CODE", string.Join("\n", lines));
Directory.CreateDirectory(Path.GetDirectoryName(_outputFile)); Directory.CreateDirectory(Path.GetDirectoryName(_outputFile));

View File

@ -36,7 +36,7 @@ Managed2NativeMethodInfo hybridclr::interpreter::g_managed2nativeStub[] =
lines.Add($"\t{{\"{method.CreateInvokeSigName()}\", __M2N_{method.CreateInvokeSigName()}}},"); lines.Add($"\t{{\"{method.CreateInvokeSigName()}\", __M2N_{method.CreateInvokeSigName()}}},");
} }
lines.Add($"\t{{nullptr, nullptr}},"); lines.Add($"\t{{\"\", nullptr}},");
lines.Add("};"); lines.Add("};");
} }

View File

@ -1,4 +1,5 @@
using dnlib.DotNet; using dnlib.DotNet;
using HybridCLR.Editor.ABI;
using HybridCLR.Editor.Meta; using HybridCLR.Editor.Meta;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -9,18 +10,27 @@ using UnityEngine;
namespace HybridCLR.Editor.ReversePInvokeWrap namespace HybridCLR.Editor.ReversePInvokeWrap
{ {
public class ReversePInvokeMethodInfo public class RawReversePInvokeMethodInfo
{ {
public MethodDef Method { get; set; } public MethodDef Method { get; set; }
public CustomAttribute GenerationAttribute { get; set; } public CustomAttribute GenerationAttribute { get; set; }
} }
public class ABIReversePInvokeMethodInfo
{
public MethodDesc Method { get; set; }
public int Count { get; set; }
}
public class Analyzer public class Analyzer
{ {
private readonly List<ModuleDefMD> _rootModules = new List<ModuleDefMD>(); private readonly List<ModuleDefMD> _rootModules = new List<ModuleDefMD>();
private readonly List<RawReversePInvokeMethodInfo> _reversePInvokeMethods = new List<RawReversePInvokeMethodInfo>();
public Analyzer(AssemblyCache cache, List<string> assemblyNames) public Analyzer(AssemblyCache cache, List<string> assemblyNames)
{ {
foreach(var assemblyName in assemblyNames) foreach(var assemblyName in assemblyNames)
@ -29,10 +39,9 @@ namespace HybridCLR.Editor.ReversePInvokeWrap
} }
} }
public List<ReversePInvokeMethodInfo> CollectMonoPInvokeCallbackMethods() private void CollectReversePInvokeMethods()
{ {
var wrapperMethods = new List<ReversePInvokeMethodInfo>(); foreach (var mod in _rootModules)
foreach(var mod in _rootModules)
{ {
Debug.Log($"ass:{mod.FullName} methodcount:{mod.Metadata.TablesStream.MethodTable.Rows}"); Debug.Log($"ass:{mod.FullName} methodcount:{mod.Metadata.TablesStream.MethodTable.Rows}");
for (uint rid = 1, n = mod.Metadata.TablesStream.MethodTable.Rows; rid <= n; rid++) for (uint rid = 1, n = mod.Metadata.TablesStream.MethodTable.Rows; rid <= n; rid++)
@ -52,14 +61,48 @@ namespace HybridCLR.Editor.ReversePInvokeWrap
//{ //{
// Debug.Log($"{ca.AttributeType.FullName} {ca.TypeFullName}"); // Debug.Log($"{ca.AttributeType.FullName} {ca.TypeFullName}");
//} //}
wrapperMethods.Add(new ReversePInvokeMethodInfo() _reversePInvokeMethods.Add(new RawReversePInvokeMethodInfo()
{ {
Method = method, Method = method,
GenerationAttribute = method.CustomAttributes.FirstOrDefault(ca => ca.AttributeType.FullName == "HybridCLR.ReversePInvokeWrapperGenerationAttribute"), GenerationAttribute = method.CustomAttributes.FirstOrDefault(ca => ca.AttributeType.FullName == "HybridCLR.ReversePInvokeWrapperGenerationAttribute"),
}); });
} }
} }
return wrapperMethods; }
public List<ABIReversePInvokeMethodInfo> BuildABIMethods(PlatformABI abi)
{
var methodsBySig = new Dictionary<string, ABIReversePInvokeMethodInfo>();
var typeCreator = TypeCreatorFactory.CreateTypeCreator(abi);
foreach(var method in _reversePInvokeMethods)
{
MethodDesc desc = new MethodDesc
{
MethodDef = method.Method,
ReturnInfo = new ReturnInfo { Type = typeCreator.CreateTypeInfo(method.Method.ReturnType)},
ParamInfos = method.Method.Parameters.Select(p => new ParamInfo { Type = typeCreator.CreateTypeInfo(p.Type)}).ToList(),
};
desc.Init();
if (!methodsBySig.TryGetValue(desc.Sig, out var arm))
{
arm = new ABIReversePInvokeMethodInfo()
{
Method = desc,
Count = 0,
};
methodsBySig.Add(desc.Sig, arm);
}
int preserveCount = method.GenerationAttribute != null ? (int)method.GenerationAttribute.ConstructorArguments[0].Value : 1;
arm.Count += preserveCount;
}
var methods = methodsBySig.Values.ToList();
methods.Sort((a, b) => a.Method.Sig.CompareTo(b.Method.Sig));
return methods;
}
public void Run()
{
CollectReversePInvokeMethods();
} }
} }
} }

View File

@ -1,45 +1,56 @@
using HybridCLR.Editor.Template; using HybridCLR.Editor.ABI;
using HybridCLR.Editor.Template;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using UnityEngine;
using System.Threading.Tasks;
namespace HybridCLR.Editor.ReversePInvokeWrap namespace HybridCLR.Editor.ReversePInvokeWrap
{ {
public class Generator public class Generator
{ {
public void Generate(string template, int wrapperCount, string outputFile) public void Generate(string template, PlatformABI abi, List<ABIReversePInvokeMethodInfo> methods, string outputFile)
{ {
template = template.Replace("{PLATFORM_ABI}", ABIUtil.GetHybridCLRPlatformMacro(abi));
var frr = new FileRegionReplace(template); var frr = new FileRegionReplace(template);
var codes = new List<string>(); var codes = new List<string>();
for(int i = 0; i < wrapperCount; i++) int methodIndex = 0;
var stubCodes = new List<string>();
foreach(var methodInfo in methods)
{ {
codes.Add($@" MethodDesc method = methodInfo.Method;
void __ReversePInvokeMethod_{i}(void* xState) string paramDeclaringListWithoutMethodInfoStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}"));
string paramNameListWithoutMethodInfoStr = string.Join(", ", method.ParamInfos.Select(p => $"__arg{p.Index}"));
string paramTypeListWithMethodInfoStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()}").Concat(new string[] { "const MethodInfo*" }));
string methodTypeDef = $"typedef {method.ReturnInfo.Type.GetTypeName()} (*Callback)({paramTypeListWithMethodInfoStr})";
for (int i = 0; i < methodInfo.Count; i++, methodIndex++)
{
codes.Add($@"
void __ReversePInvokeMethod_{methodIndex}({paramDeclaringListWithoutMethodInfoStr})
{{ {{
CallLuaFunction(xState, {i}); const MethodInfo* method = MetadataModule::GetMethodInfoByReversePInvokeWrapperIndex({i});
{methodTypeDef};
((Callback)(method->methodPointerCallByInterp))({paramNameListWithoutMethodInfoStr}, method);
}} }}
"); ");
stubCodes.Add($"\t\t{{\"{method.Sig}\", (Il2CppMethodPointer)__ReversePInvokeMethod_{methodIndex}}},\n");
}
Debug.Log($"[ReversePInvokeWrap.Generator] method:{method.MethodDef} wrapperCount:{methodInfo.Count}");
} }
codes.Add(@" codes.Add(@"
Il2CppMethodPointer s_ReversePInvokeMethodStub[] ReversePInvokeMethodData g_reversePInvokeMethodStub[]
{ {
"); ");
for(int i = 0; i < wrapperCount; i++) codes.AddRange(stubCodes);
{
codes.Add($"\t\t(Il2CppMethodPointer)__ReversePInvokeMethod_{i},\n");
}
codes.Add(@" codes.Add(@"
nullptr, {nullptr, nullptr},
}; };
"); ");
frr.Replace("REVERSE_PINVOKE_METHOD_STUB", string.Join("", codes)); frr.Replace("CODE", string.Join("", codes));
frr.Commit(outputFile); frr.Commit(outputFile);
} }
} }

View File

@ -18,7 +18,6 @@ namespace HybridCLR.Editor
private SerializedProperty m_OutputLinkFile; private SerializedProperty m_OutputLinkFile;
private SerializedProperty m_OutputAOTGenericReferenceFile; private SerializedProperty m_OutputAOTGenericReferenceFile;
private SerializedProperty m_MaxGenericReferenceIteration; private SerializedProperty m_MaxGenericReferenceIteration;
private SerializedProperty m_ReversePInvokeWrapperCount;
private SerializedProperty m_MaxMethodBridgeGenericIteration; private SerializedProperty m_MaxMethodBridgeGenericIteration;
private GUIStyle buttonStyle; private GUIStyle buttonStyle;
public HybridCLRSettingsProvider() : base("Project/HybridCLR Settings", SettingsScope.Project) { } public HybridCLRSettingsProvider() : base("Project/HybridCLR Settings", SettingsScope.Project) { }
@ -37,7 +36,6 @@ namespace HybridCLR.Editor
m_OutputLinkFile = m_SerializedObject.FindProperty("outputLinkFile"); m_OutputLinkFile = m_SerializedObject.FindProperty("outputLinkFile");
m_OutputAOTGenericReferenceFile = m_SerializedObject.FindProperty("outputAOTGenericReferenceFile"); m_OutputAOTGenericReferenceFile = m_SerializedObject.FindProperty("outputAOTGenericReferenceFile");
m_MaxGenericReferenceIteration = m_SerializedObject.FindProperty("maxGenericReferenceIteration"); m_MaxGenericReferenceIteration = m_SerializedObject.FindProperty("maxGenericReferenceIteration");
m_ReversePInvokeWrapperCount = m_SerializedObject.FindProperty("ReversePInvokeWrapperCount");
m_MaxMethodBridgeGenericIteration = m_SerializedObject.FindProperty("maxMethodBridgeGenericIteration"); m_MaxMethodBridgeGenericIteration = m_SerializedObject.FindProperty("maxMethodBridgeGenericIteration");
} }
public override void OnTitleBarGUI() public override void OnTitleBarGUI()
@ -110,7 +108,6 @@ namespace HybridCLR.Editor
EditorGUILayout.PropertyField(m_OutputLinkFile); EditorGUILayout.PropertyField(m_OutputLinkFile);
EditorGUILayout.PropertyField(m_OutputAOTGenericReferenceFile); EditorGUILayout.PropertyField(m_OutputAOTGenericReferenceFile);
EditorGUILayout.PropertyField(m_MaxGenericReferenceIteration); EditorGUILayout.PropertyField(m_MaxGenericReferenceIteration);
EditorGUILayout.PropertyField(m_ReversePInvokeWrapperCount);
EditorGUILayout.PropertyField(m_MaxMethodBridgeGenericIteration); EditorGUILayout.PropertyField(m_MaxMethodBridgeGenericIteration);
if (EditorGUI.EndChangeCheck()) if (EditorGUI.EndChangeCheck())
{ {

View File

@ -32,8 +32,8 @@ namespace HybridCLR.Editor
[Header("AOT泛型实例化搜索迭代次数")] [Header("AOT泛型实例化搜索迭代次数")]
public int maxGenericReferenceIteration = 10; public int maxGenericReferenceIteration = 10;
[Header("预留MonoPInvokeCallbackAttribute函数个数")] //[Header("预留MonoPInvokeCallbackAttribute函数个数")]
public int ReversePInvokeWrapperCount = 10; //public int ReversePInvokeWrapperCount = 10;
[Header("MethodBridge泛型搜索迭代次数")] [Header("MethodBridge泛型搜索迭代次数")]
public int maxMethodBridgeGenericIteration = 10; public int maxMethodBridgeGenericIteration = 10;

View File

@ -37,7 +37,7 @@ namespace HybridCLR.Editor
public static string LocalIl2CppDir => $"{LocalUnityDataDir}/il2cpp"; public static string LocalIl2CppDir => $"{LocalUnityDataDir}/il2cpp";
public static string MethodBridgeCppDir => $"{LocalIl2CppDir}/libil2cpp/hybridclr/interpreter"; public static string GeneratedCppDir => $"{LocalIl2CppDir}/libil2cpp/hybridclr/generated";
public static string Il2CppBuildCacheDir { get; } = $"{ProjectDir}/Library/Il2cppBuildCache"; public static string Il2CppBuildCacheDir { get; } = $"{ProjectDir}/Library/Il2cppBuildCache";

View File

@ -31,16 +31,44 @@ namespace HybridCLR.Editor.Template
foreach (var c in _regionReplaceContents) foreach (var c in _regionReplaceContents)
{ {
resultContent = TemplateUtil.ReplaceRegion(resultContent, c.Key, c.Value); resultContent = ReplaceRegion(resultContent, c.Key, c.Value);
} }
return resultContent; return resultContent;
} }
public void Commit(string outputFile) public void Commit(string outputFile)
{ {
string dir = Path.GetDirectoryName(outputFile);
Directory.CreateDirectory(dir);
string resultContent = GenFinalString(); string resultContent = GenFinalString();
var utf8WithoutBOM = new System.Text.UTF8Encoding(false); var utf8WithoutBOM = new System.Text.UTF8Encoding(false);
File.WriteAllText(outputFile, resultContent, utf8WithoutBOM); File.WriteAllText(outputFile, resultContent, utf8WithoutBOM);
} }
public static string ReplaceRegion(string resultText, string region, string replaceContent)
{
int startIndex = resultText.IndexOf("//!!!{{" + region);
if (startIndex == -1)
{
throw new Exception($"region:{region} start not find");
}
int endIndex = resultText.IndexOf("//!!!}}" + region);
if (endIndex == -1)
{
throw new Exception($"region:{region} end not find");
}
int replaceStart = resultText.IndexOf('\n', startIndex);
int replaceEnd = resultText.LastIndexOf('\n', endIndex);
if (replaceStart == -1 || replaceEnd == -1)
{
throw new Exception($"region:{region} not find");
}
if (resultText.Substring(replaceStart, replaceEnd - replaceStart) == replaceContent)
{
return resultText;
}
resultText = resultText.Substring(0, replaceStart) + "\n" + replaceContent + "\n" + resultText.Substring(replaceEnd);
return resultText;
}
} }
} }

View File

@ -1,38 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HybridCLR.Editor.Template
{
public static class TemplateUtil
{
public static string ReplaceRegion(string resultText, string region, string replaceContent)
{
int startIndex = resultText.IndexOf("//!!!{{" + region);
if (startIndex == -1)
{
throw new Exception($"region:{region} start not find");
}
int endIndex = resultText.IndexOf("//!!!}}" + region);
if (endIndex == -1)
{
throw new Exception($"region:{region} end not find");
}
int replaceStart = resultText.IndexOf('\n', startIndex);
int replaceEnd = resultText.LastIndexOf('\n', endIndex);
if (replaceStart == -1 || replaceEnd == -1)
{
throw new Exception($"region:{region} not find");
}
if (resultText.Substring(replaceStart, replaceEnd - replaceStart) == replaceContent)
{
return resultText;
}
resultText = resultText.Substring(0, replaceStart) + "\n" + replaceContent + "\n" + resultText.Substring(replaceEnd);
return resultText;
}
}
}

View File

@ -1,6 +1,6 @@
{ {
"name": "com.focus-creative-games.hybridclr_unity", "name": "com.focus-creative-games.hybridclr_unity",
"version": "0.4.5", "version": "0.5.0",
"displayName": "HybridCLR", "displayName": "HybridCLR",
"description": "Unity package for HybridCLR. It includes editor and runtime scripts and assets for HybridCLR", "description": "Unity package for HybridCLR. It includes editor and runtime scripts and assets for HybridCLR",
"category": "Runtime", "category": "Runtime",