Mex function cannot find Matlab object for callback.

7 views (last 30 days)
Hi,
I wrote an example where Matlab calls C++ code (EventProducer) which is supposed to callback a method of a Matlab object (EventConsumer).
But when I run my test "producer.run1()" (see below), mexCallMATLAB raises an error because it does not seem able to retreive the EventConsumer Matlab object :
Undefined function 'consumeEvent' for input arguments of type 'EventProducer'.
It has to be noted that if you replace "producer.run1();" by "producer.run2(consumer);" (where you pass the EventConsumer object), everything works well !
Any advice ? Thanks in advance.
The C++ classes :
class EventConsumer {
public:
virtual ~EventConsumer() {}
virtual void consumeEvent() = 0;
protected:
EventConsumer() {}
};
class EventProducer {
public:
EventProducer::EventProducer() : mConsumer(nullptr) {}
virtual ~EventProducer() {}
void setConsumer(EventConsumer* consumer) {
mConsumer = consumer;
}
void run(EventConsumer* consumer = nullptr) {
if (consumer != nullptr)
consumer->consumeEvent();
else if (mConsumer != nullptr)
mConsumer->consumeEvent();
}
private:
EventConsumer* mConsumer;
};
The Matlab code :
classdef EventConsumer
methods
function this = EventConsumer(varargin)
end
function consumeEvent(varargin)
disp('Matlab consumeEvent called')
end
end
end
classdef EventProducer < handle
properties (SetAccess = private, Hidden = true)
objectHandle; % Handle to the underlying C++ class instance
end
methods
%% Constructor
function this = EventProducer(varargin)
this.objectHandle = EventProducer_mex('new', varargin{:});
end
%% Destructor
function delete(this)
EventProducer_mex('delete', this.objectHandle);
end
%% Other methods
function setConsumer(this, consumer)
EventProducer_mex('setConsumer', this.objectHandle, consumer);
end
function run1(this)
EventProducer_mex('run1', this.objectHandle);
end
function run2(this, consumer)
EventProducer_mex('run2', this.objectHandle, consumer);
end
end
end
producer = EventProducer();
consumer = EventConsumer();
producer.setConsumer(consumer);
producer.run1();
%% producer.run2(consumer);
delete(producer);
The Mex file :
#include "../Class_Handle.hpp"
#include "EventProducer.h"
#include <iostream>
class MyEventConsumer : public EventConsumer {
public:
MyEventConsumer(const mxArray* matlabConsumer) {
mMatlabConsumer = matlabConsumer;
}
virtual ~MyEventConsumer() {}
void consumeEvent() {
std::cout << "C++ consumeEvent called" << std::endl;
mxArray* prhs[1];
prhs[0] = (mxArray*)mMatlabConsumer;
mexCallMATLAB(0, NULL, 1, prhs, "consumeEvent");
}
private:
const mxArray* mMatlabConsumer;
};
// The mex entry point
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
char fcn[64];
if (nrhs < 1 || mxGetString(prhs[0], fcn, sizeof(fcn))) {
mexErrMsgTxt("EventProducer_mex : First argument should be a function string less than 64 characters long.");
return;
}
// Constructor
if (! strcmp("new", fcn)) {
if (nlhs != 1 || nrhs != 1) {
mexErrMsgTxt("EventProducer_mex : 'new' function has wrong number of arguments.");
return;
}
// Return a handle to a new C++ instance
plhs[0] = convertPtr2Mat<EventProducer>(new EventProducer());
return;
}
// Destructor
if (! strcmp("delete", fcn)) {
if (nlhs != 0 || nrhs != 2) {
mexErrMsgTxt("EventProducer_mex : 'delete' function has wrong number of arguments.");
return;
}
// Destroy the C++ object
destroyObject<EventProducer>(prhs[1]);
return;
}
// Other methods
if (! strcmp("setConsumer", fcn)) {
if (nlhs != 0 || nrhs != 3) {
mexErrMsgTxt("EventProducer_mex : 'setConsumer' function has wrong number of arguments.");
return;
}
// Get the C++ EventProducer object, then call setConsumer
EventProducer* producer = convertMat2Ptr<EventProducer>(prhs[1]);
if (producer == NULL) {
mexErrMsgTxt("EventProducer_mex : 'setHandler' second argument should be a EventProducer class handle.");
return;
}
MyEventConsumer* consumer = new MyEventConsumer(prhs[2]);
producer->setConsumer(consumer);
return;
}
// run1
if (! strcmp("run1", fcn))
{
if (nlhs != 0 || nrhs != 2) {
mexErrMsgTxt("EventProducer_mex : 'run1' function has wrong number of arguments.");
return;
}
// Get the C++ EventProducer object, then call run
EventProducer* producer = convertMat2Ptr<EventProducer>(prhs[1]);
if (producer == NULL) {
mexErrMsgTxt("EventProducer_mex : 'run1' second argument should be a EventProducer class handle.");
return;
}
producer->run();
return;
}
// run2
if (! strcmp("run2", fcn)) {
if (nlhs != 0 || nrhs != 3) {
mexErrMsgTxt("EventProducer_mex : 'run2' function has wrong number of arguments.");
return;
}
// Get the C++ EventProducer object, then call run
EventProducer* producer = convertMat2Ptr<EventProducer>(prhs[1]);
if (producer == NULL) {
mexErrMsgTxt("EventProducer_mex : 'run2' second argument should be a EventProducer class handle.");
return;
}
MyEventConsumer* consumer = new MyEventConsumer(prhs[2]);
producer->run(consumer);
return;
}
mexErrMsgTxt("Function not recognized.");
}

Answers (0)

Categories

Find more on Write C Functions Callable from MATLAB (MEX Files) in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!