1

I need to gain some run-time information about a C++ program, which is kinda difficult due to C++ not offering some sophisticated reflection mechanism. Now, my approach is to compile the C++ code using /clr and to reflect over the resulting assembly from C# (simply because I like that language more than C++).

While this is all turning out more or less fine, I'm now stuck at a point where I need to actually run the program by calling its main method. Which is kind of frustrating considering how far I got already...

This is the C++ program in question:

#include "systemc.h"
#include <iostream>
using namespace std;

// Hello_world is module name
SC_MODULE (HelloWorld) {
    SC_CTOR (HelloWorld) {
        // Nothing in constructor 
    }
    void HelloWorld::say_hello() {
        //Print "Hello World" to the console.
        cout << "Hello World.\n";
    }
};

//sc_main in top level function like in C++ main
int sc_main(int argc, char* argv[]) {
  HelloWorld hello("HELLO");
  hello.say_hello();
  string input = "";
  getline(cin, input);
  return(0);
}

Nothing fancy, really...

This is the C# method used to inspect the resulting assembly:

System.Reflection.Assembly ass = System.Reflection.Assembly.LoadFrom(filename);

System.Console.WriteLine(filename + " is an assembly and has been properly loaded.");

Type[] hello = ass.GetTypes().Where(type => type.Name.ToLower().Contains("hello")).ToArray();
Type[] main = ass.GetTypes().Where(type => type.Name.ToLower().Contains("main")).ToArray();

Now, while the hello Type-array contains the HelloWorld class (or at least I assume that it is that class), the main var contains three types, all of which deal with doMAINs (ie have nothing to do with the sc_main method I'm looking for). I assume that it has something to do with it not being public, but declaring it a static public member function of the HelloWorld class doesn't work either since the function is expected to be a non-member function to be found. Or am I just overlooking something terribly stupid?

Jay
  • 237
  • 2
  • 14
  • 1
    Ever considered using COM for this? You can make C++ interface, translate it to C# and utilize your HelloWorld C++ class via COM like it is dotNET. – Cipi Aug 09 '11 at 09:17
  • Iirc, P-Invoke can be used to call a native function, but as I said, "I need to gain some run-time information", which is why I picked reflection. I intended to run the program to a certain point and then see what object instances have been created. – Jay Aug 09 '11 at 10:03
  • @Cipi: If I don't get it wrong, COM requires you to change the underlying C++ source code... which is something I want to avoid. The best-case-scenario for my project is running an existing C++ projet and see what's happening in there. Access to the source code is given, but any approach that would require changes in the C++ code base is currently considered a suboptimal solution. – Jay Aug 09 '11 at 10:09
  • @Jay: Well yes, you would have to adopt source to COM... implement a couple of methods, and add some header files. And also you would have to register it with regsvr32... but I guess that's not what you want. Happy coding! :D – Cipi Aug 09 '11 at 10:44

1 Answers1

3

No, it doesn't. You need to learn how C++/CLI works- you can't just recompile a C++ program with /CLR and be done with it. The sc_main method here is native, not managed, and you can't reflect over it, and the same is true about the HelloWorld type, unless you redefined it to be a ref class, but I doubt you did because there you go in main instantiating it by value, which would only be legal if it was a native class.

.NET and native code have very fundamentally different semantics and a magic compiler switch will not help you in this regard.

Puppy
  • 144,682
  • 38
  • 256
  • 465
  • Would you mind to elaborate? This [MSDN entry](http://msdn.microsoft.com/en-us/library/y0114hz2.aspx) states that "Reflection on an .exe built with the Visual C++ compiler is allowed if the .exe is built with the /clr:pure or /clr:safe compiler options", the given examples there all just require the /clr option. Do you have any sources which allow me to "learn how C++/CLI works"? – Jay Aug 09 '11 at 10:15
  • @Jay: Reflection on an `.exe` is not the same as reflection over *all* of it's contents- you can only reflect over the *managed* contents. As for sources, well, I don't have any good C++/CLI tutorials to hand. If you wanted to reflect on the contents, you would have to convert the whole code-base to .NET, which is a very sub-optimal solution. – Puppy Aug 09 '11 at 10:27
  • Now, I feel like I'm getting this less ans less... Even adding a method like `int sc_main_managed() {return 0;}` just above the `sc_main` that does not seem to contain any unmanaged code at all does not make that one part of the main[]-array given in the original question. Adding `#pragma managed` didn't help, neither did adding the method to the HelloWorld class, static or not. Could you give me one or two hints concerning what makes a method managed or not? – Jay Aug 09 '11 at 14:06
  • I'm not completely sure, I haven't used C++/CLI to any great detail, but I believe that it must be a static member of a `public ref class`. However, I *do* know that you can't convert existing C++ code effortlessly to be managed- you have to significantly re-write it. – Puppy Aug 09 '11 at 14:19
  • Not exactly what I hoped to hear, but I guess if the system just doesn't support it then there's just no way to do it. I'm now looking into the [Reflex library](http://root.cern.ch/drupal/content/reflex) to get the run time information... Maybe that's a more promising approach in order to get the information by simply re-compiling the given sources without any manual changes. Thank your for your help :). – Jay Aug 10 '11 at 07:19