【问题标题】:Accessing a C++ non-member function from C# via reflection通过反射从 C# 访问 C++ 非成员函数
【发布时间】:2011-08-09 09:12:44
【问题描述】:

我需要获得一些关于 C++ 程序的运行时信息,这有点困难,因为 C++ 没有提供一些复杂的反射机制。现在,我的方法是使用 /clr 编译 C++ 代码并反映从 C# 生成的程序集(仅仅是因为我更喜欢这种语言而不是 C++)。

虽然结果或多或少都很好,但我现在陷入了需要通过调用 main 方法来实际运行程序的地步。考虑到我已经走了多远,这有点令人沮丧......

这是有问题的 C++ 程序:

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

没什么特别的,真的......

这是用于检查生成的程序集的 C# 方法:

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

现在,虽然 hello Type-array 包含 HelloWorld 类(或者至少我假设它是那个类),但 main var 包含三种类型,它们都处理 doMAIN(即与 sc_main 无关)我正在寻找的方法)。我认为它与它不是公共的有关,但是将其声明为 HelloWorld 类的静态公共成员函数也不起作用,因为该函数预计是要找到的非成员函数。还是我只是忽略了一些非常愚蠢的事情?

【问题讨论】:

  • 曾经考虑过为此使用 COM 吗?您可以制作 C++ 接口,将其转换为 C#,并通过 COM 像 dotNET 一样使用您的 HelloWorld C++ 类。
  • Iirc,P-Invoke 可用于调用本机函数,但正如我所说,“我需要获取一些运行时信息”,这就是我选择反射的原因。我打算将程序运行到某个点,然后查看创建了哪些对象实例。
  • @Cipi:如果我没听错的话,COM 要求您更改底层 C++ 源代码……这是我想避免的。我的项目的最佳情况是运行现有的 C++ 项目,看看那里发生了什么。提供了对源代码的访问权限,但任何需要更改 C++ 代码库的方法目前都被认为是次优解决方案。
  • @Jay:嗯,是的,你必须对 COM 采用源代码......实现几个方法,并添加一些头文件。而且你还必须用 regsvr32 注册它......但我想这不是你想要的。快乐编码! :D

标签: c# c++ reflection clr non-member-functions


【解决方案1】:

不,它没有。您需要了解 C++/CLI 的工作原理——您不能只使用 /CLR 重新编译 C++ 程序并完成它。这里的sc_main 方法是本机的,不是托管的,您无法对其进行反思,HelloWorld 类型也是如此,除非您将其重新定义为ref class,但我怀疑您这样做是因为您在那里go in main 按值实例化它,这只有在它是原生类时才合法。

.NET 和本机代码的语义完全不同,而神奇的编译器开关不会在这方面为您提供帮助。

【讨论】:

  • 您介意详细说明一下吗?这个MSDN entry 声明“如果 .exe 是使用 /clr:pure 或 /clr:safe 编译器选项构建的,则允许对使用 Visual C++ 编译器构建的 .exe 进行反思”,那里的给定示例都只需要 / clr 选项。您是否有任何资源可以让我“了解 C++/CLI 的工作原理”?
  • @Jay:对 .exe 的反射与对 all 内容的反射不同——您只能对 managed 进行反射内容。至于资源,我手头没有任何好的 C++/CLI 教程。如果您想反映内容,则必须将整个代码库转换为 .NET,这是一个非常不理想的解决方案。
  • 现在,我觉得我越来越少了......即使在 sc_main 上方添加一个类似 int sc_main_managed() {return 0;} 的方法,它似乎根本不包含任何非托管代码不要将其作为原始问题中给出的 main[]-array 的一部分。添加#pragma managed 没有帮助,将方法添加到HelloWorld 类也没有帮助,无论是否静态。你能给我一两个关于是什么让方法被管理的提示吗?
  • 我不完全确定,我没有详细使用 C++/CLI,但我相信它一定是 public ref class 的静态成员。但是,我确实知道您不能毫不费力地将现有 C++ 代码转换为可管理的 - 您必须大量重写它。
  • 不完全是我希望听到的,但我想如果系统不支持它,那么就没有办法做到这一点。我现在正在查看Reflex library 以获取运行时信息......也许这是一种更有前途的方法,以便通过简单地重新编译给定的源而不需要任何手动更改来获取信息。感谢您的帮助:)。
猜你喜欢
  • 2014-07-29
  • 2010-10-15
  • 2023-04-05
  • 2013-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-30
相关资源
最近更新 更多