[英]Using C# as scripting language in C++
我试图将C#作为脚本语言嵌入到我的C ++库中。 我知道这可能不是一项微不足道的任务,所以我去了一个最小的测试项目,看看这是否可能首先。
我设法创建了一个C#程序集,其中包含用于管理简单脚本的代码,并使用CSharpCodeProvider
运行时编译它们。 使用C#console app作为测试项目测试程序集(给定C#源文件在内存中编译并在必要时执行)。
因此,下一步是将其与C ++应用程序联系起来。
我已经设法使用COM做到了这一点。 我将C#dll,类和接口导出为COM对象,并使用Regasm生成tlb文件。
我能够在C ++项目中创建这些类的实例并调用它们的方法,一切似乎都能正常工作(例如显示Windows.Forms
消息框),直到需要执行实际逻辑。 它只会抛出不应抛出的异常,因为它已经与C#控制台应用程序一起作为库的主机。
因为我不知道我是否可以调试COM组件(很好地踩到这个C#dll的代码是不可能的AFAIK)所以我添加了大量的消息框和try-catch块。
当我尝试从编译的程序集中检索任何类型时,它似乎会中断。 它抛出: Reflection.ReflectionTypeLoadException
另一方面,编译不会失败也不会生成任何错误消息。
使用C#触发这些方法可以100%工作,只有在从C ++执行时才会以某种方式中断。
可能是什么原因造成的? 或者可能还有另一种方法可以做我想做的事情? 我发现COM在某种程度上适合在这种情况下使用,但有哪些方面,我不知道这导致这样的代码打破?
编辑:这是作为COM导出的托管C#程序集: http : //nopaste.info/9da70dbcbd.html
所以这些对象可以从C ++ app访问,如下所示: http : //nopaste.info/50c4c9726a.html
并且脚本就像从IScript
派生的类一样简单,并实现显示消息框的Execute
方法。
编辑2:
有关抛出的异常的详细信息如下:“无法加载文件或程序集'lame2.scripting,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = 84d0df983ded76a1'或其中一个依赖项.Niemożnaodnaleźćokreślonegopliku。”
最后一句意味着无法找到文件。
但是很奇怪,因为编译时我有以下行:compilerparams.ReferencedAssemblies.Add(“D:\\ Interop \\ lame2.scripting \\ lame2.scripting \\ bin \\ Debug”+“\\ lame2.scripting.dll”);
这是“脚本”内容:
using System;
using System.Linq;
using System.Windows.Forms;
using System.Reflection;
using lame2.scripting;
namespace Olaboga
{
public class TestScript : IScript
{
public TestScript() { }
public void Execute(Event ev)
{
MessageBox.Show("Script that has been compiled from a source file has been invoked. TestScript.Execute");
}
}
}
编辑3:
最后,从内存中的编译切换到编译到临时文件后,它突然开始正常工作。 所以最后一个问题可能有人知道为什么它在内存中编译时无法工作,如果可以的话。
如果您可以将应用程序功能公开为COM对象模型,则应该可以执行此操作。 您应该注意以.NET互操作层可以正确处理的方式建模接口。
如果我理解正确,你在调试从C#脚本生成的.NET程序集时遇到问题,对吗? 在这种情况下,您可以在编译程序集时使用以下编译器设置:
CompilerParameters cp = new CompilerParameters();
// Generate debug information.
cp.IncludeDebugInformation = true;
// Save the assembly as a physical file.
cp.GenerateInMemory = false;
// Set a temporary files collection.
// The TempFileCollection stores the temporary files
// generated during a build in the current directory,
// and does not delete them after compilation.
cp.TempFiles = new TempFileCollection(".", true);
这将启用生成代码的调试,就像您拥有源代码,调试符号和程序集一样。 但是,你提到'COM组件'几次,但我没有看到 - 有一个C ++应用程序和.NET程序集 - 介于两者之间的东西不是真正的COM组件,而是'interop magic',或多或少,只是整理这两方之间的东西。
如果在调试包含实现的原始.NET程序集时遇到问题,请确保调试设置正确:
Project Settings -> Debugging -> Debugger Type
并将其设置为Mixed
Attach to Process
表单中单击“附加到”文本框附近的“ Select...
按钮,然后选择所需的那些(托管和本机) 这假定您确实拥有程序集的源代码和.pdb文件。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.