4

我正在尝试将 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:

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

4

1 回答 1

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 组件,而是“互操作魔法”,或多或少,只是编组这两方之间的东西。

如果您在调试包含您的实现的原始 .NET 程序集时遇到问题,请确保调试设置正确:

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

这假定您确实有程序集的源代码和 .pdb 文件。

于 2012-10-01T11:30:54.660 回答