Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
东方怂天
xLua
提交
6a5ba401
X
xLua
项目概览
东方怂天
/
xLua
通知
4
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
X
xLua
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
6a5ba401
编写于
1月 01, 2017
作者:
J
johnche(车雄生)
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
支持泛化函数的热补丁
上级
426d6a5f
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
386 addition
and
4 deletion
+386
-4
Assets/XLua/Doc/features.md
Assets/XLua/Doc/features.md
+1
-0
Assets/XLua/Doc/hotfix.md
Assets/XLua/Doc/hotfix.md
+2
-0
Assets/XLua/Examples/08_Hotfix/HotfixTest2.cs
Assets/XLua/Examples/08_Hotfix/HotfixTest2.cs
+72
-1
Assets/XLua/Examples/08_Hotfix/StatefullTest.cs
Assets/XLua/Examples/08_Hotfix/StatefullTest.cs
+5
-0
Assets/XLua/Src/Editor/Hotfix.cs
Assets/XLua/Src/Editor/Hotfix.cs
+182
-2
Assets/XLua/Src/LuaFunction.cs
Assets/XLua/Src/LuaFunction.cs
+123
-0
README.md
README.md
+1
-1
未找到文件。
Assets/XLua/Doc/features.md
浏览文件 @
6a5ba401
...
...
@@ -44,6 +44,7 @@
*
析构函数
*
成员函数
*
静态函数
*
泛化函数
*
操作符重载
*
成员属性
*
静态属性
...
...
Assets/XLua/Doc/hotfix.md
浏览文件 @
6a5ba401
...
...
@@ -72,6 +72,8 @@ end)
普通参数对于lua的参数,ref参数对应lua的一个参数和一个返回值,out参数对于lua的一个返回值。
泛化函数的打补丁规则和普通函数一样。
*
构造函数
构造函数对应的method_name是".ctor"。
...
...
Assets/XLua/Examples/08_Hotfix/HotfixTest2.cs
浏览文件 @
6a5ba401
using
UnityEngine
;
using
System.Collections
;
using
System.Collections
.Generic
;
using
XLua
;
[
CSharpCallLua
]
...
...
@@ -29,6 +29,31 @@ public class HotfixCalc
{
return
TestOut
(
a
,
out
b
,
ref
c
);
}
public
T
Test1
<
T
>()
{
return
default
(
T
);
}
public
T1
Test2
<
T1
,
T2
,
T3
>(
T1
a
,
out
T2
b
,
ref
T3
c
)
{
b
=
default
(
T2
);
return
a
;
}
public
static
int
Test3
<
T
>(
T
a
)
{
return
0
;
}
public
static
void
Test4
<
T
>(
T
a
)
{
}
public
void
Test5
<
T
>(
int
a
,
params
T
[]
arg
)
{
}
}
public
class
NoHotfixCalc
...
...
@@ -93,6 +118,47 @@ public class HotfixTest2 : MonoBehaviour {
ret
=
calc
.
TestOut
(
100
,
out
num
,
ref
str
);
Debug
.
Log
(
"ret = "
+
ret
+
", num = "
+
num
+
", str = "
+
str
);
luaenv
.
DoString
(
@"
xlua.hotfix(CS.HotfixCalc, {
Test1 = function(self)
print('Test1', self)
return 1
end;
Test2 = function(self, a, b)
print('Test1', self, a, b)
return a + 10, 1024, b
end;
Test3 = function(a)
print(a)
return 10
end;
Test4 = function(a)
print(a)
end;
Test5 = function(self, a, ...)
print('Test4', self, a, ...)
end
})
"
);
int
r1
=
calc
.
Test1
<
int
>();
double
r2
=
calc
.
Test1
<
double
>();
Debug
.
Log
(
"r1:"
+
r1
+
",r2:"
+
r2
);
string
ss
=
"heihei"
;
int
r3
=
calc
.
Test2
(
r1
,
out
r2
,
ref
ss
);
Debug
.
Log
(
"r1:"
+
r1
+
",r2:"
+
r2
+
",r3:"
+
r3
+
",ss:"
+
ss
);
r3
=
HotfixCalc
.
Test3
(
"test3"
);
r3
=
HotfixCalc
.
Test3
(
2
);
r3
=
HotfixCalc
.
Test3
(
this
);
Debug
.
Log
(
"r3:"
+
r3
);
HotfixCalc
.
Test4
(
this
);
HotfixCalc
.
Test4
(
2
);
calc
.
Test5
(
10
,
"a"
,
"b"
,
"c"
);
calc
.
Test5
(
10
,
1
,
3
,
5
);
Debug
.
Log
(
"----------------------before------------------------"
);
TestStateful
();
System
.
GC
.
Collect
();
...
...
@@ -139,6 +205,9 @@ public class HotfixTest2 : MonoBehaviour {
StaticFunc = function(a, b, c)
print(a, b, c)
end;
GenericTest = function(self, a)
print(self, a)
end;
Finalize = function(self)
print('Finalize', self)
end
...
...
@@ -171,6 +240,8 @@ public class HotfixTest2 : MonoBehaviour {
sft
.
Start
();
StatefullTest
.
StaticFunc
(
1
,
2
);
StatefullTest
.
StaticFunc
(
"e"
,
3
,
4
);
sft
.
GenericTest
(
1
);
sft
.
GenericTest
(
"hehe"
);
}
// Update is called once per frame
...
...
Assets/XLua/Examples/08_Hotfix/StatefullTest.cs
浏览文件 @
6a5ba401
...
...
@@ -30,6 +30,11 @@ public class StatefullTest {
}
public
void
GenericTest
<
T
>(
T
a
)
{
}
static
public
void
StaticFunc
(
int
a
,
int
b
)
{
}
...
...
Assets/XLua/Src/Editor/Hotfix.cs
浏览文件 @
6a5ba401
...
...
@@ -25,11 +25,30 @@ namespace XLua
static
TypeReference
objType
=
null
;
static
TypeReference
luaTableType
=
null
;
static
TypeDefinition
luaFunctionType
=
null
;
static
MethodDefinition
invokeSessionStart
=
null
;
static
MethodDefinition
functionInvoke
=
null
;
static
MethodDefinition
invokeSessionEnd
=
null
;
static
MethodDefinition
invokeSessionEndWithResult
=
null
;
static
MethodDefinition
inParam
=
null
;
static
MethodDefinition
inParams
=
null
;
static
MethodDefinition
outParam
=
null
;
static
void
init
(
AssemblyDefinition
assembly
)
{
objType
=
assembly
.
MainModule
.
Import
(
typeof
(
object
));
luaTableType
=
assembly
.
MainModule
.
Types
.
Single
(
t
=>
t
.
FullName
==
"XLua.LuaTable"
);
luaFunctionType
=
assembly
.
MainModule
.
Types
.
Single
(
t
=>
t
.
FullName
==
"XLua.LuaFunction"
);
invokeSessionStart
=
luaFunctionType
.
Methods
.
Single
(
m
=>
m
.
Name
==
"InvokeSessionStart"
);
functionInvoke
=
luaFunctionType
.
Methods
.
Single
(
m
=>
m
.
Name
==
"Invoke"
);
invokeSessionEnd
=
luaFunctionType
.
Methods
.
Single
(
m
=>
m
.
Name
==
"InvokeSessionEnd"
);
invokeSessionEndWithResult
=
luaFunctionType
.
Methods
.
Single
(
m
=>
m
.
Name
==
"InvokeSessionEndWithResult"
);
inParam
=
luaFunctionType
.
Methods
.
Single
(
m
=>
m
.
Name
==
"InParam"
);
inParams
=
luaFunctionType
.
Methods
.
Single
(
m
=>
m
.
Name
==
"InParams"
);
outParam
=
luaFunctionType
.
Methods
.
Single
(
m
=>
m
.
Name
==
"OutParam"
);
}
static
List
<
TypeDefinition
>
hotfix_delegates
=
null
;
...
...
@@ -143,7 +162,8 @@ namespace XLua
{
if
(
method
.
Name
!=
".cctor"
)
{
if
(!
InjectCode
(
assembly
,
method
,
hotfixType
,
stateTable
))
if
(
method
.
HasGenericParameters
?
!
InjectGenericMethod
(
assembly
,
method
,
hotfixType
,
stateTable
)
:
!
InjectMethod
(
assembly
,
method
,
hotfixType
,
stateTable
))
{
return
;
}
...
...
@@ -161,7 +181,7 @@ namespace XLua
static
readonly
int
MAX_OVERLOAD
=
100
;
static
bool
Inject
Code
(
AssemblyDefinition
assembly
,
MethodDefinition
method
,
int
hotfixType
,
FieldDefinition
stateTable
)
static
bool
Inject
Method
(
AssemblyDefinition
assembly
,
MethodDefinition
method
,
int
hotfixType
,
FieldDefinition
stateTable
)
{
string
fieldName
=
method
.
Name
;
if
(
fieldName
.
StartsWith
(
"."
))
...
...
@@ -247,6 +267,166 @@ namespace XLua
return
true
;
}
static
MethodReference
MakeGenericMethod
(
this
MethodReference
self
,
params
TypeReference
[]
arguments
)
{
if
(
self
.
GenericParameters
.
Count
!=
arguments
.
Length
)
throw
new
ArgumentException
();
var
instance
=
new
GenericInstanceMethod
(
self
);
foreach
(
var
argument
in
arguments
)
instance
.
GenericArguments
.
Add
(
argument
);
return
instance
;
}
static
bool
InjectGenericMethod
(
AssemblyDefinition
assembly
,
MethodDefinition
method
,
int
hotfixType
,
FieldDefinition
stateTable
)
{
string
fieldName
=
method
.
Name
;
if
(
fieldName
.
StartsWith
(
"."
))
{
fieldName
=
fieldName
.
Substring
(
1
);
}
string
luaDelegateName
=
null
;
var
type
=
method
.
DeclaringType
;
for
(
int
i
=
0
;
i
<
MAX_OVERLOAD
;
i
++)
{
string
tmp
=
"__Hitfix"
+
i
+
"_"
+
fieldName
;
if
(!
type
.
Fields
.
Any
(
f
=>
f
.
Name
==
tmp
))
// injected
{
luaDelegateName
=
tmp
;
break
;
}
}
if
(
luaDelegateName
==
null
)
{
Debug
.
LogError
(
"too many overload!"
);
return
false
;
}
FieldDefinition
fieldDefinition
=
new
FieldDefinition
(
luaDelegateName
,
Mono
.
Cecil
.
FieldAttributes
.
Static
|
Mono
.
Cecil
.
FieldAttributes
.
Private
,
luaFunctionType
);
type
.
Fields
.
Add
(
fieldDefinition
);
int
param_start
=
method
.
IsStatic
?
0
:
1
;
int
param_count
=
method
.
Parameters
.
Count
+
param_start
;
var
firstIns
=
method
.
Body
.
Instructions
[
0
];
var
processor
=
method
.
Body
.
GetILProcessor
();
processor
.
InsertBefore
(
firstIns
,
processor
.
Create
(
OpCodes
.
Ldsfld
,
fieldDefinition
));
processor
.
InsertBefore
(
firstIns
,
processor
.
Create
(
OpCodes
.
Brfalse
,
firstIns
));
processor
.
InsertBefore
(
firstIns
,
processor
.
Create
(
OpCodes
.
Ldsfld
,
fieldDefinition
));
processor
.
InsertBefore
(
firstIns
,
processor
.
Create
(
OpCodes
.
Callvirt
,
invokeSessionStart
));
bool
isVoid
=
method
.
ReturnType
.
FullName
==
"System.Void"
;
int
outCout
=
0
;
for
(
int
i
=
0
;
i
<
param_count
;
i
++)
{
if
(
i
==
0
&&
!
method
.
IsStatic
)
{
processor
.
InsertBefore
(
firstIns
,
processor
.
Create
(
OpCodes
.
Ldsfld
,
fieldDefinition
));
processor
.
InsertBefore
(
firstIns
,
processor
.
Create
(
OpCodes
.
Ldarg_0
));
if
(
hotfixType
==
1
)
{
processor
.
InsertBefore
(
firstIns
,
processor
.
Create
(
OpCodes
.
Ldfld
,
stateTable
));
processor
.
InsertBefore
(
firstIns
,
processor
.
Create
(
OpCodes
.
Callvirt
,
MakeGenericMethod
(
inParam
,
luaTableType
)));
}
else
{
processor
.
InsertBefore
(
firstIns
,
processor
.
Create
(
OpCodes
.
Callvirt
,
MakeGenericMethod
(
inParam
,
method
.
DeclaringType
)));
}
}
else
{
var
param
=
method
.
Parameters
[
i
-
param_start
];
if
(
param
.
ParameterType
.
IsByReference
)
{
outCout
++;
}
if
(!
param
.
IsOut
)
{
processor
.
InsertBefore
(
firstIns
,
processor
.
Create
(
OpCodes
.
Ldsfld
,
fieldDefinition
));
if
(
i
<
ldargs
.
Length
)
{
processor
.
InsertBefore
(
firstIns
,
processor
.
Create
(
ldargs
[
i
]));
}
else
{
processor
.
InsertBefore
(
firstIns
,
processor
.
Create
(
OpCodes
.
Ldarg
,
(
short
)
i
));
}
var
paramType
=
param
.
ParameterType
;
if
(
param
.
ParameterType
.
IsByReference
)
{
paramType
=
((
ByReferenceType
)
paramType
).
ElementType
;
if
(
paramType
.
IsValueType
||
paramType
.
IsGenericParameter
)
{
processor
.
InsertBefore
(
firstIns
,
processor
.
Create
(
OpCodes
.
Ldobj
,
paramType
));
}
else
{
processor
.
InsertBefore
(
firstIns
,
processor
.
Create
(
OpCodes
.
Ldind_Ref
));
}
}
if
(
i
==
param_count
-
1
&&
param
.
CustomAttributes
.
Any
(
ca
=>
ca
.
AttributeType
.
FullName
==
"System.ParamArrayAttribute"
))
{
processor
.
InsertBefore
(
firstIns
,
processor
.
Create
(
OpCodes
.
Callvirt
,
MakeGenericMethod
(
inParams
,
((
ArrayType
)
paramType
).
ElementType
)));
}
else
{
processor
.
InsertBefore
(
firstIns
,
processor
.
Create
(
OpCodes
.
Callvirt
,
MakeGenericMethod
(
inParam
,
paramType
)));
}
}
}
}
int
outStart
=
(
isVoid
?
0
:
1
);
processor
.
InsertBefore
(
firstIns
,
processor
.
Create
(
OpCodes
.
Ldsfld
,
fieldDefinition
));
processor
.
InsertBefore
(
firstIns
,
processor
.
Create
(
OpCodes
.
Ldc_I4
,
outCout
+
outStart
));
processor
.
InsertBefore
(
firstIns
,
processor
.
Create
(
OpCodes
.
Callvirt
,
functionInvoke
));
int
outPos
=
outStart
;
for
(
int
i
=
0
;
i
<
method
.
Parameters
.
Count
;
i
++)
{
if
(
method
.
Parameters
[
i
].
ParameterType
.
IsByReference
)
{
processor
.
InsertBefore
(
firstIns
,
processor
.
Create
(
OpCodes
.
Ldsfld
,
fieldDefinition
));
processor
.
InsertBefore
(
firstIns
,
processor
.
Create
(
OpCodes
.
Ldc_I4
,
outPos
));
int
arg_pos
=
param_start
+
i
;
if
(
arg_pos
<
ldargs
.
Length
)
{
processor
.
InsertBefore
(
firstIns
,
processor
.
Create
(
ldargs
[
arg_pos
]));
}
else
{
processor
.
InsertBefore
(
firstIns
,
processor
.
Create
(
OpCodes
.
Ldarg
,
(
short
)
arg_pos
));
}
processor
.
InsertBefore
(
firstIns
,
processor
.
Create
(
OpCodes
.
Callvirt
,
MakeGenericMethod
(
outParam
,
((
ByReferenceType
)
method
.
Parameters
[
i
].
ParameterType
).
ElementType
)));
outPos
++;
}
}
processor
.
InsertBefore
(
firstIns
,
processor
.
Create
(
OpCodes
.
Ldsfld
,
fieldDefinition
));
if
(
isVoid
)
{
processor
.
InsertBefore
(
firstIns
,
processor
.
Create
(
OpCodes
.
Callvirt
,
invokeSessionEnd
));
}
else
{
processor
.
InsertBefore
(
firstIns
,
processor
.
Create
(
OpCodes
.
Callvirt
,
MakeGenericMethod
(
invokeSessionEndWithResult
,
method
.
ReturnType
)));
}
processor
.
InsertBefore
(
firstIns
,
processor
.
Create
(
OpCodes
.
Ret
));
return
true
;
}
}
}
#endif
Assets/XLua/Src/LuaFunction.cs
浏览文件 @
6a5ba401
...
...
@@ -17,6 +17,7 @@ using LuaCSFunction = XLua.LuaDLL.lua_CSFunction;
#endif
using
System
;
using
System.Collections.Generic
;
namespace
XLua
{
...
...
@@ -229,6 +230,128 @@ namespace XLua
{
return
"function :"
+
luaReference
;
}
#if HOTFIX_ENABLE
private
int
_oldTop
=
0
;
private
Stack
<
int
>
_stack
=
new
Stack
<
int
>();
public
void
InvokeSessionStart
()
{
lock
(
luaEnv
.
luaEnvLock
)
{
var
L
=
luaEnv
.
L
;
_stack
.
Push
(
_oldTop
);
_oldTop
=
LuaAPI
.
lua_gettop
(
L
);
LuaAPI
.
load_error_func
(
L
,
luaEnv
.
errorFuncRef
);
LuaAPI
.
lua_getref
(
L
,
luaReference
);
}
}
public
void
Invoke
(
int
nRet
)
{
lock
(
luaEnv
.
luaEnvLock
)
{
int
error
=
LuaAPI
.
lua_pcall
(
luaEnv
.
L
,
LuaAPI
.
lua_gettop
(
luaEnv
.
L
)
-
_oldTop
-
2
,
nRet
,
_oldTop
+
1
);
if
(
error
!=
0
)
{
var
lastOldTop
=
_oldTop
;
InvokeSessionEnd
();
luaEnv
.
ThrowExceptionFromError
(
lastOldTop
);
}
}
}
public
void
InvokeSessionEnd
()
{
lock
(
luaEnv
.
luaEnvLock
)
{
LuaAPI
.
lua_settop
(
luaEnv
.
L
,
_oldTop
);
}
_oldTop
=
_stack
.
Pop
();
}
public
TResult
InvokeSessionEndWithResult
<
TResult
>()
{
lock
(
luaEnv
.
luaEnvLock
)
{
if
(
LuaAPI
.
lua_gettop
(
luaEnv
.
L
)
<
_oldTop
+
2
)
{
InvokeSessionEnd
();
throw
new
InvalidOperationException
(
"no result!"
);
}
try
{
TResult
ret
;
luaEnv
.
translator
.
Get
(
luaEnv
.
L
,
_oldTop
+
2
,
out
ret
);
return
ret
;
}
finally
{
InvokeSessionEnd
();
}
}
}
public
void
InParam
<
T
>(
T
p
)
{
try
{
lock
(
luaEnv
.
luaEnvLock
)
{
luaEnv
.
translator
.
PushByType
(
luaEnv
.
L
,
p
);
}
}
catch
(
Exception
e
)
{
InvokeSessionEnd
();
throw
e
;
}
}
public
void
InParams
<
T
>(
T
[]
ps
)
{
try
{
lock
(
luaEnv
.
luaEnvLock
)
{
for
(
int
i
=
0
;
i
<
ps
.
Length
;
i
++)
{
luaEnv
.
translator
.
PushByType
<
T
>(
luaEnv
.
L
,
ps
[
i
]);
}
}
}
catch
(
Exception
e
)
{
InvokeSessionEnd
();
throw
e
;
}
}
//pos start from 0
public
void
OutParam
<
TResult
>(
int
pos
,
out
TResult
ret
)
{
lock
(
luaEnv
.
luaEnvLock
)
{
if
(
LuaAPI
.
lua_gettop
(
luaEnv
.
L
)
<
_oldTop
+
2
+
pos
)
{
InvokeSessionEnd
();
throw
new
InvalidOperationException
(
"no result in "
+
pos
);
}
try
{
luaEnv
.
translator
.
Get
(
luaEnv
.
L
,
_oldTop
+
2
+
pos
,
out
ret
);
}
catch
(
Exception
e
)
{
InvokeSessionEnd
();
throw
e
;
}
}
}
#endif
}
}
README.md
浏览文件 @
6a5ba401
...
...
@@ -10,7 +10,7 @@ xLua为Unity3D增加Lua脚本编程的能力,进而提供代码逻辑增量更
xLua在功能、性能、易用性都有不少突破,这几方面分别最具代表性的突破是:
*
Unity3D全平台热补丁技术,可以运行时把C#实现(整个类,或者单个方法,操作符,属性,事件,构造函数,析构函数)替换成lua实现;
*
Unity3D全平台热补丁技术,可以运行时把C#实现(整个类,或者单个方法,
泛化方法,
操作符,属性,事件,构造函数,析构函数)替换成lua实现;
*
自定义struct,枚举在Lua和C#间传递无C# gc alloc;
*
编辑器下无需生成代码,开发更轻量;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录