最終更新日 2024-09-25
マクロから渡した関数名でリアルタイムにdllを生成する
概要
.NET Frameworkは、「System.Reflection」を利用することで、クラスやメソッド等をリアルタイムに生成するだけではなく、
.dllや.exeへと具体的にコンパイルするメソッドまでをも提供しています。
以下のファイルをdynamicasm.macとして保存します。
#PY = loaddll( hidemarudir + @"\hmPy.dll" );
#_ = dllfuncw(#PY, "DoString", R"IPY(
my_sum_method_name = "hm_sum";
)IPY"
);
#_ = dllfuncw(#PY, "DoString", R"IPY(
from System import *
from System.Threading import *
from System.Reflection import *
from System.Reflection.Emit import *
try:
my_sum_method_name = my_sum_method_name
except:
my_sum_method_name = "myfunc"
def addMethodDynamically(typeBuilder, methodName, methodParams, returnType):
methodBuilder = typeBuilder.DefineMethod(
methodName,
MethodAttributes.Public | MethodAttributes.Static,
returnType,
methodParams
)
ILout = methodBuilder.GetILGenerator()
numParams = len(methodParams)
x = 0
while x < numParams:
ILout.Emit(OpCodes.Ldarg_S, x)
x += 1
y = 0
while y < (numParams - 1):
ILout.Emit(OpCodes.Add)
y += 1
ILout.Emit(OpCodes.Ret)
def main():
domain = Thread.GetDomain()
asmName = AssemblyName()
asmName.Name = "DynamicAssembly"
asmBuilder = domain.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.RunAndSave)
module = asmBuilder.DefineDynamicModule("DynamicModule", "DynamicAsm.dll")
typeBuilder = module.DefineType("DynamicType", TypeAttributes.Public)
global my_sum_method_name
methodName = my_sum_method_name
inputNumsList = (2, 3, 4, 5)
methodParams = Array[Type]((Int32, Int32, Int32, Int32))
inputValsList = Array[object](inputNumsList)
returnType = Int32
# Now, call the method building method with the parameters, passing the TypeBuilder.
addMethodDynamically(typeBuilder, methodName, methodParams, returnType)
myType = typeBuilder.CreateType()
result = myType.InvokeMember(methodName,
BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static,
None, None,
inputValsList
)
hm.debuginfo( "入力された数値の総計: %s" % result )
hm.debuginfo( "---" )
# ダイナミックにMSILを生成しています。
asmBuilder.Save("DynamicAsm.dll")
methodInfo = myType.GetMethod(methodName)
hm.debuginfo( "生成したメソッド: %r;" % methodInfo )
main()
)IPY"
);
freedll( #PY );
出来上がったDynamicAsm.dllをILSpyで見ると
以下のように秀丸マクロで渡したパラメータに基づいて、.dllが出来上がっているのがわかります。
