Доступ к свойству Obj-C из функции C++ (iOS)
Я пишу приложение для iOS, которое выполняет некоторую обработку звука в AppDelegate с использованием Core Audio API. у меня есть @property
в моем AppDelegate, который обновляется в ViewController, и это @property
должен быть доступен в моей функции обратного вызова рендеринга, которая написана на C++. К моему сожалению, я обнаружил, что вы не можете получить доступ к Obj-C @property
в функции C++, просто используя _propertyName
как и в методе Obj-C, теперь мне интересно, как это сделать.
Вот мой @property
в AppDelegate.h:
@property float centerFreq
Вот моя функция обратного вызова рендеринга в AppDelegate.m:
static OSStatus audioProcessingRenderCallback (
void * inRefCon,
AudioUnitRenderActionFlags * ioActionFlags,
const AudioTimeStamp * inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList * ioData
) {
//audio processing stuff that needs to access _centerFreq
}
Моей первой мыслью было просто сделать audioProcessingRenderCallback
метод Objective C, но это вызывает ошибку, когда я пытаюсь установить это как функцию обратного вызова с этим кодом:
AURenderCallbackStruct callbackStruct;
callbackStruct.inputProc = audioProcessingRenderCallback;
Что было бы лучшим решением этой проблемы?
2 ответа
Один из способов, как я описал в своем комментарии к вашему сообщению, это изменить расширение вашего файла C++. Сделайте расширение.mm (т.е. AudioProcessor.mm). Это включает Objective-C++, и тогда вы можете просто передать свой объект и вызвать его из файла C++. Это, наверное, проще всего.
Если вы не можете изменить расширение файла C++, тогда вам нужно сделать функцию моста.
В вашем ViewController (файл.m) создайте функцию C следующим образом:
void updateCenterFreq( float value ) {
myViewControllerInstance.centerFreq = value;
}
Очевидно, вы должны найти способ сделать экземпляр ViewController видимым для функции C. Одним из способов является назначение статического указателя в вашем файле.m. Полезно, только если у вас есть один экземпляр, и вы не беспокоитесь о потоках, но это может сработать для вас. Если у вас есть более одного экземпляра контроллера представления, вы должны найти способ найти этот экземпляр. Как это сделать, выходит за рамки моего ответа здесь. Я исправлю это, чтобы сказать, что если вы планируете вызывать updateCenterFreq() в неосновном потоке, то вам нужно использовать performSelectorOnMainThread
чтобы попасть в основной поток, прежде чем устанавливать centerFreq (я предполагаю, что именно в контроллере представления вы планируете обновить пользовательский интерфейс, что необходимо сделать в основном потоке).
Теперь в вашем файле AudioProcessor.h (заголовок файла C++) выполните:
extern "C" {
void updateCenterFreq( float value );
}
Затем вы можете вызвать updateCenterFreq(), когда вам нужно.
Опять же, это не касается безопасности потоков или того, как вы находите свой экземпляр, но это то, как вы можете это сделать.
Все, что вам нужно сделать, это передать ссылку на centerFreq
к вашему методу:
static OSStatus audioProcessingRenderCallback (
float * centerFrequency,
void * inRefCon,
AudioUnitRenderActionFlags * ioActionFlags,
const AudioTimeStamp * inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList * ioData
) {
//audio processing stuff that needs to access _centerFreq
}
затем сделайте то, что вы хотите сделать по этой ссылке, и обновления будут отражаться в вашей собственности.