开发者

Calling overridden method of derived native class through wrappers (derived Managed Classes) in C++/CLI

开发者 https://www.devze.com 2023-04-12 06:35 出处:网络
I have a tale of 6 classes: 3 managed and 3 native. The 3 managed classes are ManagedChildA, ManagedChildB and ManagedParent.

I have a tale of 6 classes: 3 managed and 3 native. The 3 managed classes are ManagedChildA, ManagedChildB and ManagedParent.

ManagedChildA, ManagedChildB both inherit from ManagedParentA.

The 3 nativeclasses are NativeChildA, NativeChildB and NativeParent.

NativeChildA, NativeChildB both inherit from NativeParentA.

Moreover, ManagedChildA wraps NativeChildB, ManagedChildB wraps ManagedChildB and ManagedParentA wraps NativeParentA.

Now here the tale gows awry:

ManagedParentA has a method called ManagedExecute() that wraps NativeParentA's NativeExecute(). When this method is called, everything runs smoothly.

NativeChildB, ManagedChildB override ManagedExecute() to provide their own implementations, with ManagedChildA::ManagedExecute() wrapping NativeChildA::NativeExecute() and ManagedChildB::ManagedExecute() wrapping NativeChildB::NativeExecute().

When for example the overriden ManagedExecute() of ManagedChildA is called, NativeChildA::NativeExecute() gets called albeit with a System.AccessViolation error. That is, the pointer to the original parent of NativeChildA cannot be located.

I guess the pointer has been moved from its original address. I read on the internet, I have to pin pointers to prevent the Garbage Collector (GC) from moving memory around but I don't know what to pin, since the exception gets thrown at the native level. Any useful hints?

Example:

//C++ -native classes
class NativeFoo
{
  public:
  NativeFoo(): tested(true){}
  virtual void execute()
  {
     std::cout << "Native Foo" << std::endl;
  }

  protected:
  bool tested;

 };


 class NativeBarA :NativeFoo
 {
  public:
  NativeBarA(): NativeFoo(){}
  void execute()
  {
     std::cout << "Native Bar A" << std::endl;
  }
 };

 class NativeBarB : public NativeFoo
 {
  public:
  NativeBarB() :NativeFoo(){}
  void execute()
  {
     std::cout << "Native Bar B" << std::endl;
  }
 };

//CLI interface
 public interface class IExecutable
 {
     publi开发者_如何转开发c:
       Execute();
 }

//C++-CLI classes 
public ref class ManagedFoo: public IExecutable
{

  private:
  NativeFoo* impl;

  public:

 ManagedFoo(): impl(NULL)
 {
  impl = new NativeFoo();
 }

 void __clrcall Execute()
 {
  impl->execute(); 
 }
};

public ref class ManagedBarA: public ManagedFoo
{

  private:
  NativeBarA* impl;

  public:

 ManagedBarA(): ManagedFoo(), impl(NULL)
 {
  impl = new NativeBarA();
 }

 void __clrcall Execute() override
 {
  impl->execute(); 
 }
};

public ref class ManagedBarB: public ManagedFoo
{

  private:
  NativeBarB* impl;

  public:

 ManagedBarB(): ManagedFoo(), impl(NULL)
 {
  impl = new NativeBarB();
 }

 void __clrcall Execute() override
 {
  impl->execute(); 
 }
};


//Calling code
[STAThread]
static void Main()
{
   ManagedFoo^ mfoo = gcnew ManagedFoo();
   ManagedBarA  mbarA = gcnew ManagedBarA();
   ManagedBarB  mbarB = gcnew ManagedBarB();
   mfoo->Execute(); //OK
   mbarA->Execute(); //Error. Debugger sees value of tested as false
   mBarB->Execute(); //Error
}


The snippet is very low quality, it is littered with uncompilable code. No repro once I fixed all the mistakes.

#include "stdafx.h"
#include <iostream>
using namespace System;

//C++ -native classes
class NativeFoo
{
public:
    NativeFoo(): tested(true){}
    virtual void execute()
    {
        std::cout << "Native Foo" << std::endl;
    }

protected:
    bool tested;

};


class NativeBarA :NativeFoo
{
public:
    NativeBarA(): NativeFoo(){}
    void execute()
    {
        std::cout << "Native Bar A" << std::endl;
    }
};

class NativeBarB : public NativeFoo
{
public:
    NativeBarB() :NativeFoo(){}
    void execute()
    {
        std::cout << "Native Bar B" << std::endl;
    }
};

//CLI interface
public interface class IExecutable
{
public:
    void Execute();
};

//C++-CLI classes 
public ref class ManagedFoo: public IExecutable
{

private:
    NativeFoo* impl;

public:

    ManagedFoo(): impl(NULL)
    {
        impl = new NativeFoo();
    }

    virtual void Execute()
    {
        impl->execute(); 
    }
};

public ref class ManagedBarA: public ManagedFoo
{

private:
    NativeBarA* impl;

public:

    ManagedBarA(): ManagedFoo(), impl(NULL)
    {
        impl = new NativeBarA();
    }

    virtual void __clrcall Execute() override
    {
        impl->execute(); 
    }
};

public ref class ManagedBarB: public ManagedFoo
{

private:
    NativeBarB* impl;

public:

    ManagedBarB(): ManagedFoo(), impl(NULL)
    {
        impl = new NativeBarB();
    }

    virtual void __clrcall Execute() override
    {
        impl->execute(); 
    }
};


//Calling code
[STAThread]
int main(array<System::String ^> ^args)
{
    ManagedFoo^ mfoo = gcnew ManagedFoo();
    ManagedBarA^  mbarA = gcnew ManagedBarA();
    ManagedBarB^  mbarB = gcnew ManagedBarB();
    mfoo->Execute(); //OK
    mbarA->Execute(); //Fine
    mbarB->Execute(); //Fine
}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号