返回对非托管对象的引用

返回对非托管对象的引用

本文介绍了C ++ / CLI:返回对非托管对象的引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一种将引用返回到另一个对象的方法,该对象是托管对象的成员。这可以在C ++中轻松实现,但是对于将C ++ / CLI包装器与C#一起使用是一个挑战。下面是可重现的场景(有很多代码,但是都非常容易,仅演示问题)

I'm looking for a way to return the reference to another object that is a member of a managed object. This can be easily achieved in C++, but is a challenge for C++/CLI wrapper to be used with C#. Below is reproducible scenario (it's a lot of code, but it's all very easy, just demonstrating the problem)

C ++类:

class NATIVEAPI NativeSlave
{
public:
    NativeSlave() : x_( 0 ), y_( 0.0 )
    {}

    NativeSlave( int x, double y ) : x_( x ), y_( y )
    {}

    int x_;
    double y_;
};

class NATIVEAPI NativeMaster
{
public:
    __declspec( property( get = getSlave, put = setSlave ) ) NativeSlave& slave;
    NativeSlave& getSlave()
    {
        return *pSlave; //returns a reference
    }
    void setSlave( const NativeSlave& slave )
    {
        *pSlave = slave;
    }

public:
    NativeMaster() : pSlave( new NativeSlave( 4, 5.0 ) )
    {}
    ~NativeMaster()
    {
        delete pSlave;
    }

private:
    NativeSlave* pSlave;
};

C ++用法:

NativeSlave slave = NativeSlave( 1, 2.0 ); //now, slave.x==1, slave.y==2.0
NativeMaster master; //now, master.slave.x==4, master.slave.y==5.0

master.slave = slave; //now, master.slave.x==1, master.slave.y==2.0
master.slave.x_ = 6; //now, master.slave.x==6
master.slave.y_ = 10.0; //now, master.slave.y==10.0

因此在C ++中,我们可以轻松获得

So in C++, we can easily get a reference to an underlying object and operate on its methods (here, members are public to simplify the example).

然后,目标是将其包装在C ++ / CLI中,以实现以下目的:在C#中实现与上述C ++中相同的功能(用法):

Then, the goal is to wrap this in C++/CLI to achieve the same functionality(usage) in C# as in C++ above:

C#(所需)

ManagedSlave slave = new ManagedSlave(1, 2.0); //now, slave.x==1, slave.y==2.0
ManagedMaster master = new ManagedMaster(); //desired: master.slave.x==4, master.slave.y==5.0

master.slave = slave; //desired: master.slave.x==1, master.slave.y==2.0
master.slave.x = 6; //no appropriate get() method to change master.slave
master.slave.y = 10.0; //no appropriate get() method to change master.slave

这里是尝试编写包装器的尝试:

Here is an attempt to write a wrapper:

C ++ / CLI(获取/设置属性方法有问题):

C++/CLI (with a problem in get/set property methods):

public ref class ManagedSlave
{
public:
    property int x
    {
        int get()
        {
            return mSlave->x_;
        }
        void set( int x )
        {
            mSlave->x_ = x;
        }
    }
    property double y
    {
        double get()
        {
            return mSlave->y_;
        }
        void set( double y )
        {
            mSlave->y_ = y;
        }
    }
public:
    ManagedSlave( int x, double y ) : mSlave( new NativeSlave( x, y ) )
    {}
    ~ManagedSlave()
    {
        delete mSlave;
    }

internal:
    NativeSlave* mSlave;
};

public ref class ManagedMaster
{
public:
    property ManagedSlave^ slave
    {
        ManagedSlave^ get()
        {
            //??????????????????????????
        };
        void set( ManagedSlave^ slave )
        {
            //is this correct???????????
            mMaster->slave.x_ = slave->x;
            mMaster->slave.y_ = slave->y;
        };
    }

public:
    ManagedMaster() : mMaster( new NativeMaster() )
    {}
    ~ManagedMaster()
    {
        delete mMaster;
    }

internal:
    NativeMaster* mMaster;
};


推荐答案

.NET引用与C ++引用完全不同。

.NET "references" are nothing like C++ references.

.NET中有一些与C ++引用等效的内容, ref 关键字用于限定参数。但是除了参数之外,没有其他方法可以使用它。 (在IL级别,它也可以用于局部变量,但仍不能用于返回类型)

There is something in .NET that is the equivalent of a C++ reference, the ref keyword that qualifies arguments. But there's no way to use it for anything except arguments. (At the IL level it can be used for local variables also, but still not on return types)

大多数时候,您可以通过额外的间接层来解决此问题。

Most of the time you can solve this by an extra layer of indirection.

在您的特定情况下,这真的很容易:

In your particular case, it's really easy:

ManagedSlave( NativeSlave* s ) : mSlave( s )
{}
~ManagedSlave()
{
    // empty
}

ManagedSlave^ ManagedMaster::slave::get()
{
     return gcnew ManagedSlave( &mMaster->getSlave() );
}

// remove ManagedMaster::slave::set

基本上,没有理由让 ManagedSlave 负责分配和释放,因为 NativeMaster 已经做到了。

Basically, there's no reason for ManagedSlave to be responsible for allocating and freeing a NativeSlave, because NativeMaster already does that.

这篇关于C ++ / CLI:返回对非托管对象的引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-03 07:23