在C ++中使用C#作为脚本语言

时间:2012-10-01 10:51:37

标签: c# c++ com

我正在尝试将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 ++应用程序访问这些对象,如下所示: 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:

最后从内存中的编译切换到编译到临时文件后,它突然开始正常工作。所以最后一个问题可能有人知道为什么它在内存中编译时无法工作,是否有可能这样做。

1 个答案:

答案 0 :(得分:4)

如果您可以将应用程序功能公开为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程序集时遇到问题,请确保调试设置正确无误:

  • 如果您使用原生应用正常开始调试(F5),请转到Project Settings -> Debugging -> Debugger Type并将其设为Mixed
  • 如果您将调试程序附加到正在运行的进程,请在Attach to Process表单中单击“附加到”文本框附近的Select...按钮,然后选择您需要的文件(托管和本机)

这假设您的程序集中有源代码和.pdb文件。