致电 C++ 来自 C#/.NET 的函数

发布于 2024-07-29 20:12:58 字数 235 浏览 5 评论 0原文

我有一个包含 C++ 项目和 C# 项目的解决方案。

C++ 项目定义了一个类,我想在 C# 中实例化该类并调用其成员函数。 到目前为止,我成功实例化了该类:

CFoo Bar = new CFoo();

但是当我尝试调用它的函数时,编译器说它不可用。

另外,当我检查调试器中的对象时,没有显示任何成员。

我在这里缺少什么?

I have a solution which has a C++ project and a C# project.

The C++ project defines a class, which I want to instantiate in C# and call its member functions. So far I managed to instantiate the class:

CFoo Bar = new CFoo();

But when I try to call a function on it, the compiler says, it is not available.

Also, when I inspect the object in the debugger, no members are shown.

What am I missing here?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

瞎闹 2024-08-05 20:12:59

您需要在 C++/CLI 中将该类声明为ref class

(请注意,我们谈论的是 C++/CLI,而不是 C++。我假设您必须在 C++ 项目中启用 CLR,否则您将无法让新的 CFoo 工作。)

编辑:

您不需要将所有旧类转换为 ref 类。

假设您有一些旧的 C++:

class FooUnmanaged
{
    int x;

    FooUnmanaged() : x(5) {}
};

然后您尝试将其包装在 CLR 类中:

ref class FooManaged
{
    FooUnmanaged m;
};

正如您所注意到的,您会收到一条错误消息,指出这是不允许的。 但试试这个:

ref class FooManaged
{
    FooUnmanaged *m;
};

完全没问题。 编译器不想分配嵌入在托管堆上的对象内的非托管对象的实例,但它很高兴有一个指针,它在生成的 IL 中将其转换为 System.IntPtr

这意味着您必须决定如何调用delete。 最可能的解决方案是:

ref class FooManaged
{
    FooUnmanaged *u;

public:
    FooManaged(FooUnmanaged *u_)
        : u(u_) { }

    ~FooManaged() { delete u; }
};

就像在任何其他 C++ 类中一样。 C++/CLI 可能会在未来的版本中自动为我们完成此转换。

请注意,生成的 IL 是 FooManaged 类现在实现了 IDisposable,并且析构函数已转变为 Dispose 方法。 这允许 .NET 客户端正确地释放它,例如在 C# 中

using (var m = new FooManaged())
{

    // end of block: m will be disposed (and so FooUnmanaged will be deleted)
}

You need to declare the class in C++/CLI as a ref class.

(Note that we're talking about C++/CLI, not C++. I assume you must have enabled the CLR in your C++ project or you wouldn't be able to get the new CFoo to work.)

Edit:

You don't need to convert all your old classes in to ref classes.

Suppose you have some old C++:

class FooUnmanaged
{
    int x;

    FooUnmanaged() : x(5) {}
};

Then you try to wrap it in a CLR class:

ref class FooManaged
{
    FooUnmanaged m;
};

As you've noticed, you get an error saying this isn't allowed. But try this:

ref class FooManaged
{
    FooUnmanaged *m;
};

That's perfectly OK. The compiler doesn't want to allocate an instance of an unmanaged object embedded inside an object on the managed heap, but it's quite happy to have a pointer, which it turns into System.IntPtr in the resulting IL.

This means that you have to make a decision about how to call delete. The most likely solution is:

ref class FooManaged
{
    FooUnmanaged *u;

public:
    FooManaged(FooUnmanaged *u_)
        : u(u_) { }

    ~FooManaged() { delete u; }
};

Just as it would be in any other C++ class. It's possible that C++/CLI will be able to do this translation for us automatically in some future version.

Note that the resulting IL is that the FooManaged class now implements IDisposable, and the destructor has been turned into a Dispose method. This allows .NET clients to properly deallocate it, e.g. in C#

using (var m = new FooManaged())
{

    // end of block: m will be disposed (and so FooUnmanaged will be deleted)
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文