jsi*_*ons 12 .net c# reflection lua code-generation
为了在C中定义可由Lua调用的方法,它必须匹配给定的签名并使用Lua API来检索参数并返回结果.我正在编写Lua的C#包装器,我对能够调用任意C#方法而不使它们遵循这些约定感兴趣.在包装类似D的东西时,可以使用模板系统为任何给定方法动态创建此粘合代码.我认为这在C#中可能也是可能的,但是通过使用动态代码生成.
C API看起来像这样,生成的代码将通过我的库的较低级别部分来操作它,该部分P/Invokes Lua C库.
static int foo (lua_State *L)
{
int n = lua_gettop(L); /* number of arguments */
lua_Number sum = 0;
int i;
for (i = 1; i <= n; i++)
{
if (!lua_isnumber(L, i))
{
lua_pushstring(L, "incorrect argument");
lua_error(L);
}
sum += lua_tonumber(L, i);
}
lua_pushnumber(L, sum/n); /* first result */
lua_pushnumber(L, sum); /* second result */
return 2; /* number of results */
}
Run Code Online (Sandbox Code Playgroud)
所以基本上我的想法是采用C#方法,反映其参数和返回值,生成(或从缓存中检索)一个方法,该方法使用上面的Lua API传递这些参数并返回这些返回类型,最后将该方法推送到Lua .因此,当从Lua调用C#函数时,它看起来像lua - > magic wrapper function - >普通的C#函数.
谢谢.
Che*_*eso 14
如果我理解你想要的东西,你似乎有两个选择:
CodeDom是一种毛茸茸的,非常低级的代码.我们的想法是有一个C#语言的对象模型.首先实例化CodeTypeDeclaration - 这将生成一个类型或类.然后添加属性和字段 - 在这里你可能会DllImport为你的p/invoke函数添加声明.然后对类型使用不同的CodeDOM添加方法 - 这将是您插入生成的方法的位置.无论你喜欢什么,你都可以公开,静态.
CodeDOM看起来像这样:
System.Type mt= a[0].GetType();
System.CodeDom.CodeTypeDeclaration class1 = new System.CodeDom.CodeTypeDeclaration(mt.Name);
class1.IsClass=true;
class1.TypeAttributes = System.Reflection.TypeAttributes.Public;
class1.Comments.Add(new System.CodeDom.CodeCommentStatement("Wrapper class for " + mt.Name));
System.CodeDom.CodeConstructor ctor;
ctor= new System.CodeDom.CodeConstructor();
ctor.Attributes = System.CodeDom.MemberAttributes.Public;
ctor.Comments.Add(new System.CodeDom.CodeCommentStatement("the null constructor"));
class1.Members.Add(ctor);
ctor.Statements.Add(new System.CodeDom.CodeAssignStatement(new System.CodeDom.CodeVariableReferenceExpression("m_wrapped"), new System.CodeDom.CodeObjectCreateExpression(mt)));
ctor= new System.CodeDom.CodeConstructor();
ctor.Attributes = System.CodeDom.MemberAttributes.Public;
ctor.Comments.Add(new System.CodeDom.CodeCommentStatement("the 'copy' constructor"));
class1.Members.Add(ctor);
ctor.Parameters.Add(new System.CodeDom.CodeParameterDeclarationExpression(mt,"X"));
ctor.Statements.Add(new System.CodeDom.CodeAssignStatement(new System.CodeDom.CodeVariableReferenceExpression("m_wrapped"), new System.CodeDom.CodeVariableReferenceExpression("X")));
// embed a local (private) copy of the wrapped type
System.CodeDom.CodeMemberField field1;
field1= new System.CodeDom.CodeMemberField();
field1.Attributes = System.CodeDom.MemberAttributes.Private;
field1.Name= "m_wrapped";
field1.Type=new System.CodeDom.CodeTypeReference(mt);
class1.Members.Add(field1);
...
Run Code Online (Sandbox Code Playgroud)
它继续.并且.如你所见,它变得非常难看.然后你编译它,我没有显示.我假设你不想采取这种方法.
我发现CodeDom使用非常苛刻; 相反,现在当我需要动态生成的程序集时,我会通常通过模板将实际的C#代码发送到内存中的字符串中,然后编译它.这对我的目的来说简单得多.编译看起来像这样:
var cp = new System.CodeDom.Compiler.CompilerParameters {
ReferencedAssemblies.Add(filesystemLocation), // like /R: option on csc.exe
GenerateInMemory = true, // you will get a System.Reflection.Assembly back
GenerateExecutable = false, // Dll
IncludeDebugInformation = false,
CompilerOptions = ""
};
var csharp = new Microsoft.CSharp.CSharpCodeProvider();
// this actually runs csc.exe:
System.CodeDom.Compiler.CompilerResults cr =
csharp.CompileAssemblyFromSource(cp, LiteralSource);
// cr.Output contains the output from the command
if (cr.Errors.Count != 0)
{
// handle errors
}
System.Reflection.Assembly a = cr.CompiledAssembly;
// party on the type here, either via reflection...
System.Type t = a.GetType("TheDynamicallyGeneratedType");
// or via a wellknown interface
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,LiteralSource包含要编译的源代码.正如我所说的,我通过阅读模板并填充空白来生成这个.
| 归档时间: |
|
| 查看次数: |
9703 次 |
| 最近记录: |