Using C # as a scripting language in C ++

I am trying to insert C # as langague scripts in my C ++ library. I knew that this might not be a trivial task, so I went for a minimal test project to see if this was possible in the first place.

I managed to create a C # assembly containing code for managing simple scripts and compiling them @ run-time with CSharpCodeProvider . The assembly was tested using the C # console application as a test project (provided that the C # source files were compiled in memory and executed if necessary).

So, the next step was to overcome this with a C ++ application.

I somehow managed to do this with COM. I exported my C # dll, classes and interfaces as COM objects and generated a tlb file using Regasm.

I can create instances of these classes in a C ++ project and call their methods, and everything seemed to work fine (for example, displaying a Windows.Forms message box) until the actual logic was executed. It just throws exceptions that should not be thrown, since it already worked with the C # console application as the library host.

I don’t know if I can debug COM components (well, AFAIK is impossible to enter into the code of this C # dll), so I added a lot of message blocks and try-catch blocks.

It seems to break when I try to extract any type from a compiled assembly. It throws: Reflection.ReflectionTypeLoadException

Compilation on the other hand does not interrupt and does not generate any error messages.

Using C # to run these methods works 100%, only when executed from C ++ it somehow breaks.

What could be the reason for this? Or maybe there is another way to do what I'm trying to do? I really think COM is somehow correct for use in such a scenario, but are there any aspects that I don’t know about this reason that this code breaks?

EDIT: This is a C # managed assembly exported as COM: http://nopaste.info/9da70dbcbd.html

Thus, these objects are accessible from a C ++ application, for example: http://nopaste.info/50c4c9726a.html

And the script is as simple as a class derived from IScript that implements the Execute method, which displays a message box.

Edit 2:

Details about the exception: "Failed to load file or assembly lame2.scripting, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = 84d0df983ded76a1" or one of its dependencies. Nie można odnaleźć określonego pliku.

The last sentence means that the file was not found.

But this is strange, since when compiling I have the following line: compilerparams.ReferencedAssemblies.Add ("D: \ Interop \ lame2.scripting \ lame2.scripting \ bin \ Debug" + "\ lame2.scripting.dll");

This is the contents of the script:

 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"); } } } 

Edit 3:

Finally, after moving from compiling to memory to compiling to a temporary file, it suddenly started working correctly. Thus, the last question may someone know why it did not work during compilation in memory, and if possible.

+4
source share
1 answer

If you can use the functionality of your application as a COM object model, then this should be possible. You must take care to model the interfaces in such a way that they can be correctly processed using the .NET interaction layer.

If I understood correctly, you are having problems debugging the .NET assembly generated from your C # script, right? In this case, you can use the following compiler options when compiling the assembly:

 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); 

This will allow you to debug the generated code, since you have the source code, debugging symbols, and assembly. However, you mention “COM components” several times, but I don’t see them - there is a C ++ application and .NET assembly. The material between them is not a real COM component, but "interop magic", which is more or less just marshals between the two sides.

If you have problems debugging the original .NET assembly containing your implementation, make sure the Debug settings are correct:

  • if you usually start debugging normally (F5) using your own application, go to Project Settings -> Debugging -> Debugger Type and set it to Mixed
  • if you attach the debugger to the running process, in the Attach to Process form, click the Select... button next to the "Attach to" text box and select the ones you need (managed and native).

This assumes that you have the source code and the .pdb file for your build.

+4
source

Source: https://habr.com/ru/post/1437156/


All Articles