Adamski Adamski - 23 days ago 10
C++ Question

How to pass a std::function from Objective-C++ to C++ method

I'm trying to create a

std::function
within an Objective-C++ method, and pass it to a C++ method.

However I'm getting a bad access exception. I've tried using an Objective-C block and a lambda:

Using a block:

std::function<void(void)> callback = ^{
[self doSomething];
};

callback(); // <-- this works

self.myCppObject-> setButtonCallback(callback);


Using a lambda:

std::function<void()> callback = [self]() {
[self doSomething];
};

callback(); // <-- this works

self.myCppObject->setButtonCallback(callback);


In my C++ class:

void MyCppClass::setButtonCallback (std::function<void()> callback)
{
buttonCallback = std::move (callback); // <-- crash here
}


I've also tried storing
callback
in the Objective-C++ class as a property:

@property (nonatomic, assign) std::function<void()> callback;


The exception is thrown here: (line 1717 from
<functional>
)

template<class _Rp, class ..._ArgTypes>
function<_Rp(_ArgTypes...)>&
function<_Rp(_ArgTypes...)>::operator=(function&& __f) _NOEXCEPT
{
if (__f_ == (__base*)&__buf_) // <-- EXC_BAD_ACCESS here
__f_->destroy();
else if (__f_)
__f_->destroy_deallocate();
__f_ = 0;

...


Which comes from the callback assignment in the C++ method. I tried using both
std::move
and copy via
=
.

UPDATE

The issue turned out to be that myCppObject had not been initialised, as it was a subclass of a class which initialised it in its constructor, however I was calling the base
[super init]
instead of the
[super initWith...]
that I needed. Thanks to @Roman for the clue.

Answer

I tried to run your code and I received the same error only if property self.myCppObject was not initialised before. Try to replace

self.myCppObject-> setButtonCallback(callback);

with

self.myCppObject = new MyCppClass();
self.myCppObject-> setButtonCallback(callback);

or check if your properly initialised property self.myCppObject.

Comments