我正在尝试将C#作为脚本语言嵌入到我的C++库中。我意识到这可能不是一项简单的任务,所以我首先进行了最小测试项目,以查看是否可能。
我已经成功创建了一个包含管理简单脚本和在运行时编译它们的代码的C#程序集,使用CSharpCodeProvider进行测试。该程序集已在C#控制台应用程序中进行了测试(给定的C#源文件在内存中编译并在必要时执行)。
因此,下一步是将其与C++应用程序桥接起来。
我通过COM设法做到了这一点。我将我的C# dll、类和接口导出为COM对象,并使用Regasm生成了tlb文件。
我能够在C++项目中创建这些类的实例并调用它们的方法,一切似乎都工作正常(例如显示Windows.Forms消息框),直到需要执行实际逻辑时才会抛出不应该抛出的异常。由于我不知道是否可以调试COM组件(我认为无法进入此C# dll的代码),因此我添加了大量消息框和try-catch块。
当我尝试从已编译的程序集中检索任何类型时,似乎会出现问题。它会抛出:
使用C#触发这些方法可以100%正常工作,但是在从C++执行时,它会以某种方式中断。
可能是什么原因?或者可能有另一种方法来做我正在尝试做的事情吗?我确实认为COM在这种情况下应该被使用,但是是否有我不知道的方面导致这样的代码中断?
编辑:这是导出为COM的托管C#程序集: http://nopaste.info/9da70dbcbd.html 所以这些对象是像这样从C++应用程序中访问的: http://nopaste.info/50c4c9726a.html 脚本非常简单,只需从
编辑2:
以下是有关抛出的异常的详细信息: “无法加载文件或程序集'lame2.scripting,版本=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");
这是“脚本”内容:
我已经成功创建了一个包含管理简单脚本和在运行时编译它们的代码的C#程序集,使用CSharpCodeProvider进行测试。该程序集已在C#控制台应用程序中进行了测试(给定的C#源文件在内存中编译并在必要时执行)。
因此,下一步是将其与C++应用程序桥接起来。
我通过COM设法做到了这一点。我将我的C# dll、类和接口导出为COM对象,并使用Regasm生成了tlb文件。
我能够在C++项目中创建这些类的实例并调用它们的方法,一切似乎都工作正常(例如显示Windows.Forms消息框),直到需要执行实际逻辑时才会抛出不应该抛出的异常。由于我不知道是否可以调试COM组件(我认为无法进入此C# dll的代码),因此我添加了大量消息框和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,版本=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:
最终,在从内存编译转换为编译到临时文件后,它突然开始正常工作。所以最后一个问题是,有人知道为什么在内存中编译时它无法工作,如果可能的话,是否可以这样做。
obj = (IScript)Activator.CreateInstance(script_type);
还是script_assembly.GetTypes()
? - Zdeslav Vojkovic