[new] MonoPInvokeCallback支持任意签名的函数
[refactor] 重构模板文件,除去重复。统一调整生成文件的输出目录到 hybridclr/generatedmain
parent
9ea240ab82
commit
d8e155dc25
|
@ -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
|
|
@ -1,7 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 1249fb131a848a14f8dd0938e3cc2558
|
|
||||||
TextScriptImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -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
|
|
|
@ -1,7 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: e06e14385d246aa4ab853d3fd04d6eec
|
|
||||||
TextScriptImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -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
|
|
|
@ -1,7 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 2965fa89651ee0c4eb4c4fdcf95b76b8
|
|
||||||
TextScriptImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 6447cdc1825eeef49a3679545ac31d95
|
|
||||||
TextScriptImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 69e748de769c24948afd4f8a9df82b8c
|
guid: edeb86f4b5b13ca4cb0fe9d87ce509bb
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)
|
|
||||||
{
|
|
||||||
Debug.Log($"method:{method.Method}");
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
//string ReversePInvokeWrapperStubFile = $"{SettingsUtil.LocalIl2CppDir}/libil2cpp/hybridclr/metadata/ReversePInvokeMethodStub.cpp";
|
string templateCode = File.ReadAllText($"{SettingsUtil.TemplatePathInPackage}/ReversePInvokeMethodStub.cpp");
|
||||||
//string wrapperTemplateStr = File.ReadAllText($"{SettingsUtil.TemplatePathInPackage}/ReversePInvokeMethodStub.cpp.txt");
|
foreach (PlatformABI abi in Enum.GetValues(typeof(PlatformABI)))
|
||||||
//int wrapperCount = SettingsUtil.HybridCLRSettings.ReversePInvokeWrapperCount;
|
{
|
||||||
//var generator = new Generator();
|
string outputFile = $"{SettingsUtil.GeneratedCppDir}/ReversePInvokeMethodStub_{abi}.cpp";
|
||||||
//generator.Generate(wrapperTemplateStr, wrapperCount,ReversePInvokeWrapperStubFile);
|
|
||||||
//Debug.Log($"GenerateReversePInvokeWrapper. wraperCount:{wrapperCount} output:{ReversePInvokeWrapperStubFile}");
|
List<ABIReversePInvokeMethodInfo> methods = analyzer.BuildABIMethods(abi);
|
||||||
//MethodBridgeGeneratorCommand.CleanIl2CppBuildCache();
|
Debug.Log($"GenerateReversePInvokeWrapper. abi:{abi} wraperCount:{methods.Sum(m => m.Count)} output:{outputFile}");
|
||||||
|
var generator = new Generator();
|
||||||
|
generator.Generate(templateCode, abi, methods, outputFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MethodBridgeGeneratorCommand.CleanIl2CppBuildCache();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
@ -97,27 +100,21 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddManaged2NativeMethod(MethodDesc method)
|
private void AddManaged2NativeMethod(MethodDesc method)
|
||||||
{
|
|
||||||
if (_managed2nativeMethodSet.Add(method))
|
|
||||||
{
|
{
|
||||||
method.Init();
|
method.Init();
|
||||||
}
|
_managed2nativeMethodSet.Add(method);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddNative2ManagedMethod(MethodDesc method)
|
private void AddNative2ManagedMethod(MethodDesc method)
|
||||||
{
|
|
||||||
if (_native2managedMethodSet.Add(method))
|
|
||||||
{
|
{
|
||||||
method.Init();
|
method.Init();
|
||||||
}
|
_native2managedMethodSet.Add(method);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddAdjustThunkMethod(MethodDesc method)
|
private void AddAdjustThunkMethod(MethodDesc method)
|
||||||
{
|
|
||||||
if (_adjustThunkMethodSet.Add(method))
|
|
||||||
{
|
{
|
||||||
method.Init();
|
method.Init();
|
||||||
}
|
_adjustThunkMethodSet.Add(method);
|
||||||
}
|
}
|
||||||
|
|
||||||
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));
|
||||||
|
|
||||||
|
|
|
@ -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("};");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
{
|
||||||
|
MethodDesc method = methodInfo.Method;
|
||||||
|
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($@"
|
codes.Add($@"
|
||||||
void __ReversePInvokeMethod_{i}(void* xState)
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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())
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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";
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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",
|
||||||
|
|
Loading…
Reference in New Issue