2012-10-01 59 views
4

我想將C#作爲腳本語言嵌入到我的C++庫中。我意識到這可能不是一項微不足道的任務,所以我參加了一個最小的測試項目,以查看這是否可能首先發生。在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,版本= 1.0.0.0,文化=中性公鑰= 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:

最後從編譯在內存中的編譯到臨時文件切換後,突然開始正常工作,所以。最後一個問題可以有人知道爲什麼它不能在內存中編譯時工作,如果有可能這樣做

+0

你見過[Roslyn](http://blogs.msdn.com/b/visualstudio/archive/2011/10/19/introducing-the-microsoft-roslyn-ctp.aspx)。 – MoonKnight

+0

感謝您的鏈接,但因爲它看起來不是生產代碼,所以我無法看到這個更適合我的需求的解決方案,然後使用CSharpCodeProvider和dll庫中的反射來說實話。 –

+0

我同意,但這是可以發佈到生產環境中的東西,所以很好意識到這一點。祝你好運:] – MoonKnight

回答

4

如果你可以公開你的應用程序功能作爲一個COM對象模型,那麼它應該可以做到這一點你應該小心模型接口的方式可以通過.NET interop層正確處理。

如果我理解正確,您在調試從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...按鈕附近的「附加to`文本框,然後選擇你需要的那些(託管和本機)

這假定您的程序集有源代碼和.pdb文件。

+0

其實我在調試管理DLL本身(使用運行時編譯器)時遇到困難。 我會發佈一個示例源代碼,到目前爲止我所做的。 –

+0

我已經添加了一些關於可能原因的信息。 –

+0

感謝您提供有關debbuging的信息。它像一個魅力!儘管如此,仍然存在異常問題,但它會使事情變得更容易。 –