【发布时间】:2012-09-22 05:16:15
【问题描述】:
我正在尝试将 C# 作为脚本语言嵌入到我的 C++ 库中。我知道这可能不是一项微不足道的任务,所以我首先进行了一个最小的测试项目,看看这是否可能。
我设法创建了一个 C# 程序集,其中包含用于管理简单脚本并在运行时使用 CSharpCodeProvider 编译它们的代码。该程序集使用 C# 控制台应用程序作为测试项目进行了测试(假设 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++ 应用程序访问的,如下所示: http://nopaste.info/50c4c9726a.html
并且脚本就像从IScript 派生的类并实现显示消息框的Execute 方法一样简单。
编辑 2:
有关抛出异常的详细信息如下: “无法加载文件或程序集 'lame2.scripting, Version=1.0.0.0, Culture=neutral, PublicKeyToken=84d0df983ded76a1' 或其依赖项之一。Nie można odnaleźć określonego pliku。”
最后一句表示找不到文件。
但这很奇怪,因为在编译时我有以下行: 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:
终于在从内存编译切换到编译到临时文件后,它突然开始正常工作了。所以最后一个问题有人可以知道为什么它在内存中编译时无法工作,是否可以这样做。
【问题讨论】:
-
你见过Roslyn。
-
感谢您的链接,但因为这似乎还没有准备好生产代码,我看不到这个更适合我需要的解决方案,然后使用 CSharpCodeProvider 和 dll 库中的反射说实话。
-
我同意,但这是要发布到生产环境中的东西,所以最好了解它。祝你好运:]
-
究竟在哪一行抛出异常?你能显示异常的完整堆栈跟踪吗? lame2.scripting 程序集相对于 c++ 控制台和主 .NET 程序集的位置是什么?是
obj = (IScript)Activator.CreateInstance(script_type);还是script_assembly.GetTypes()? -
GetTypes() 抛出异常。我正在使用程序集的绝对路径,即 D:\Interop\lame2.scripting\lame2.scripting\bin\Debug\lame2.scripting.dll"(当然我使用双斜杠)