1

For reference, this question deals with accessing the C++ NaturalPoint Camera SDK via C#.

I am trying to pass along the implementation of a virtual method from C++ to C#. The trouble I am having is that the C++ virtual method is not in an interface class and I am not able to change that. Here is the class declaration:

class CLAPI cCameraListener
{
public:
    cCameraListener()  {};
    ~cCameraListener() {};

    virtual void FrameAvailable();
    virtual void FrameOverflow();
    virtual void ButtonPressed();
};

The CLAPI is defined as:

#define CLAPI __declspec(dllexport)

I can't inherit from the cCameraListener class in a ref class since it isn't an interface class and haven't come up with any way to expose the virtual methods to a managed class. I also need to be able to register the listener which I talk about more below.

Here is the working C++ implementation for listening for frames:

// process frames as they arrive
class FrameListener: public cCameraListener
{
public:
  Camera *myCamera;
  FrameListener(Camera *cameraPtr)
  {
    myCamera = cameraPtr;
  };

  void FrameAvailable()
  {
    Frame *thisFrame = myCamera->GetFrame();

    // do something with the frame here

    thisFrame->Release();
  };
};

int _tmain(int argc, _TCHAR* argv[])
{
  // startup camera
  CameraManager::X().WaitForInitialization();
  Camera *camera = CameraManager::X().GetCamera();
  if(camera==0)
  {
      // print an error
      return 1;
  }

  // set camera properties
  camera->SendEmptyFrames(false);
  camera->SendInvalidFrames(false);
  camera->SetVideoType(SegmentMode);

  // setup frame listener
  FrameListener *myListener = new FrameListener(camera);
  camera->AttachListener(myListener);

  // start the camera
  camera->Start();

  // while loop holding thread

  // clean up
  camera->Release();
  CameraManager::X().Shutdown();

  return 0;
}

Here is some of the existing C++/CLI wrapper code: Link: https://code.google.com/p/npcamerasdkdotnet/

public ref class MCamera{
public:

  MCamera(Camera * camera){
    this->camera = camera;

  }
  ~MCamera(){
    delete this->camera;
  }

  void        Start(){camera->Start();} 

  void        SetExposure(int Value){camera->SetExposure(Value);}          
  void        SetThreshold(int Value){camera->SetThreshold(Value);}        
  void        SetIntensity(int Value){camera->SetIntensity(Value);}

  // TODO - WRAP THESE METHODS
  //void AttachListener(cCameraListener * Listener);
  //void RemoveListener(cCameraListener * Listener);

  // other wrapped methods here...

private:
  Camera * camera;
};

Notice that within the MCamera wrapper class, the AttachListener method needs to be implemented and requires a pointer to the cCameraListener class talked about above.

Any suggestions would be appreciated! Thanks!

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
christurnerio
  • 1,469
  • 11
  • 13
  • possible duplicate of [c++/cli pass (managed) delegate to unmanaged code](http://stackoverflow.com/questions/2972452/c-cli-pass-managed-delegate-to-unmanaged-code) – Hans Passant Jun 23 '11 at 04:00
  • @Hans: That other question doesn't have anything to do with inheritance or virtual methods, that I can see. – Ben Voigt Jun 23 '11 at 06:50

1 Answers1

2

The solution is not so hard you need to wrap the listener in the manage class something like that:


class CameraListenerImp;

/** * Managed Version of the listener which will be used by managed clients */ public ref class ManagedCameraListener abstract { public: ManagedCameraListener();

    virtual void FrameAvailable() abstract;
    virtual void FrameOverflow() abstract;
    virtual void ButtonPressed() abstract;

    ~ManagedCameraListener();

    CameraListenerImp* GetUnManagedListener()
    {
        return _unmanagedListener;
    }

private: CameraListenerImp* _unmanagedListener; };

// Unmanaged to managed listener wraper class CameraListenerImp : public cCameraListener { public: CameraListenerImp( ManagedCameraListener^ in ) { theClass = in; } virtual void FrameAvailable() { theClass->FrameAvailable(); } virtual void FrameOverflow() { theClass->FrameOverflow(); } virtual void ButtonPressed() { theClass->ButtonPressed(); } private: gcroot < ManagedCameraListener^ > theClass; };

/////////////////////////////////////////////////////////// // ManagedCameraListener imp ManagedCameraListener::ManagedCameraListener() { _unmanagedListener = new CameraListenerImp( this ); }

ManagedCameraListener::~ManagedCameraListener() { delete _unmanagedListener; } /////////////////////////////////////////////////////////// // ManagedCameraListener imp end

public ref class MCamera { public: MCamera(Camera * camera) { this->camera = camera; } ~MCamera() { delete this->camera; }

    void AttachListener( ManagedCameraListener^ listener )
    {
            // call unmanaged version of the AttachListener
            this->camera->AttachListener( listener->GetUnManagedListener() );
    }

    void RemoveListener( ManagedCameraListener^ listener )
    {
            // call unmanaged version of the RemoveListener
            this->camera->RemoveListener( listener->GetUnManagedListener() );
    }

private: Camera * camera; };

/** * Managed implementation */ public ref class MyOwnManagedCameraListener : public ManagedCameraListener { public: virtual void FrameAvailable() override { / do something hard / } virtual void FrameOverflow() override { / do something hard / } virtual void ButtonPressed() override { / do something hard */ } };

int main(array ^args) { MCamera^ cam = gcnew MCamera( camera ); MyOwnManagedCameraListener^ listener = gcnew MyOwnManagedCameraListener();

cam->AttachListener( listener ); cam->RemoveListener( listener ); return 0;

}

Sasha
  • 846
  • 5
  • 9
  • This works wonderfully, thanks Sasha! I'll pass this link along to the NaturalPoint forum and I'm sure the folks there will benefit from it as well. Thanks again! – christurnerio Jun 23 '11 at 14:34