我正在为XCode中的Blackmagic Design AV设备编写设备驱动程序,我在将BMD的SyncController类从其缩写示例代码(下面)中包含到我纯粹的Objective-C项目中时遇到了麻烦。
他们的DecklinkAPI.h文件包含丰富的C ++代码,因此当我尝试在Objective-C类中按原样包含此头文件时,API中的编译器包括:未知类型名称'类“;你的意思是'上课'吗?
我试图将C ++位捆绑成一个Obj-C类扩展,如here所述,但没有太大成功。我从来没有做过任何C ++编程(并且从未使用过Obj-C类扩展),所以这对我来说是个新领域。
我不确定是否需要为我的SyncController对象创建一个额外的包装类,或者我是否可以在这个上执行类扩展并将C ++位拖放到.mm文件中。
我希望能够在没有编译器阻塞的情况下在Objective-C类中执行#include "SyncController.h"
(或其包装器)。
非常感谢您提供的任何帮助。
首先,这是我当前的SyncController.h文件:
#import <Cocoa/Cocoa.h>
#import "DeckLinkAPI.h" // this is rich in C++ code
class PlaybackDelegate;
@interface SyncController : NSObject {
PlaybackDelegate* playerDelegate;
IDeckLink* deckLink;
IDeckLinkOutput* deckLinkOutput;
}
- (void)scheduleNextFrame:(BOOL)prerolling;
- (void)writeNextAudioSamples;
@end
class PlaybackDelegate : public IDeckLinkVideoOutputCallback, public IDeckLinkAudioOutputCallback
{
SyncController* mController;
IDeckLinkOutput* mDeckLinkOutput;
public:
PlaybackDelegate (SyncController* owner, IDeckLinkOutput* deckLinkOutput);
// IUnknown needs only a dummy implementation
virtual HRESULT QueryInterface (REFIID iid, LPVOID *ppv) {return E_NOINTERFACE;}
virtual ULONG AddRef () {return 1;}
virtual ULONG Release () {return 1;}
virtual HRESULT ScheduledFrameCompleted (IDeckLinkVideoFrame* completedFrame, BMDOutputFrameCompletionResult result);
virtual HRESULT ScheduledPlaybackHasStopped ();
virtual HRESULT RenderAudioSamples (bool preroll);
};
void ScheduleNextVideoFrame (void);
接下来,这是我的(简化的)SyncController.mm文件:
#import <CoreFoundation/CFString.h>
#import "SyncController.h"
@implementation SyncController
- (instancetype)init
{
self = [super init];
return self;
}
- (void)dealloc
{
}
- (void)scheduleNextFrame:(BOOL)prerolling
{
}
- (void)writeNextAudioSamples
{
}
@end
PlaybackDelegate::PlaybackDelegate (SyncController* owner, IDeckLinkOutput* deckLinkOutput)
{
mController = owner;
mDeckLinkOutput = deckLinkOutput;
}
HRESULT PlaybackDelegate::ScheduledFrameCompleted (IDeckLinkVideoFrame* completedFrame, BMDOutputFrameCompletionResult result)
{
[mController scheduleNextFrame:NO];
return S_OK;
}
HRESULT PlaybackDelegate::ScheduledPlaybackHasStopped ()
{
return S_OK;
}
HRESULT PlaybackDelegate::RenderAudioSamples (bool preroll)
{
[mController writeNextAudioSamples];
if (preroll)
mDeckLinkOutput->StartScheduledPlayback(0, 100, 1.0);
return S_OK;
}
答案 0 :(得分:1)
不是一个完整的答案,但错误如:
未知类型名称'class';你的意思是'上课'吗?
Objective-C ++是一个经典问题,其中 Objective-C实现文件正在查看C ++头文件。
我只能提供关于如何避免它的建议,因为你没有发布完整的构建输出。
隐藏任何头文件中C ++的使用,例如使用私有实例变量:
#import <vector>
@implementation MyObjCppClass {
std::vector<int> _stuff;
}
- (id)init {
...
}
@end
如果您正在混合使用Objective-C和Objective-C ++,那么您可能会发现需要为C ++类提供Objective-C包装器(从外部看起来是Objective-C但实际上是在Objective-C ++中实现的) )。
答案 1 :(得分:1)
将.m文件(objective-c)重命名为.mm(objective-c ++)。这应该允许您通过包含c ++标头和引用来自objc的c ++代码来混合objc和c ++。
--- --- EDIT
您在objective-c中包含的任何头文件都必须只包含objective-c。从包装器类的头中删除任何c ++,以获取要构建的其他objc类。在现代objc中,您可以在.h和.m文件之间拆分ivars;将所有方法保存在.h中以供其他objc类使用,并在.mm中声明你的c ++ ivars。将你的c ++委托类放在它自己的.h中,它只包含在.mm包装器中。
答案 2 :(得分:1)
使用#if __cplusplus
。
例如,
#import <Cocoa/Cocoa.h>
#if __cplusplus
#import "DeckLinkAPI.h" // this is rich in C++ code
#endif // __cplusplus
@interface SyncController : NSObject {
void* playerDelegate; // should be cast as C++ PlaybackDelegate class.
...
}
@end
#if __cplusplus
class PlaybackDelegate : public IDeckLinkVideoOutputCallback, public IDeckLinkAudioOutputCallback
{
...
};
#endif // __cplusplus
头文件可以与Objective-C和Objective-C ++一起使用。但是你不能在头部的SyncController Objective-C类声明中使用C ++类签名。使用void *
代替PlaybackDelegate *
进行正确的类型转换。
同样使用void *
意味着不再需要标题中的C ++内容。
#import <Cocoa/Cocoa.h>
@interface SyncController : NSObject {
void* playerDelegate; // should be cast as C++ PlaybackDelegate class.
...
}
@end
在Objective-C ++代码中,
// initialize
syncController.playerDelegate = new PlaybackDelegate();
// use the pointer
PlaybackDelegate *playbackDelegate = (PlaybackDelegate *)syncController.playerDelegate;
答案 3 :(得分:1)
我试图将C ++位捆绑成一个Obj-C类扩展,如此处所述,但没有太大成功。
如果你的目标是64位,那么类扩展方法应该相当简单。
以下内容相当于您发布的代码,但将所有C ++声明移到单独的标题中:
SyncController.h:
#import <Cocoa/Cocoa.h>
@interface SyncController : NSObject
- (void)scheduleNextFrame:(BOOL)prerolling;
- (void)writeNextAudioSamples;
@end
SyncController_CPP.h
#import "SyncController.h"
#include "DeckLinkAPI.h"
class PlaybackDelegate;
@interface SyncController() {
PlaybackDelegate* playerDelegate;
IDeckLink* deckLink;
IDeckLinkOutput* deckLinkOutput;
}
@end
class PlaybackDelegate ...
{
...
}
SyncController.mm
#import "SyncController_CPP.h"
@implementation SyncController
...
@end
PlaybackDelegate::PlaybackDelegate (SyncController* owner, IDeckLinkOutput* deckLinkOutput)
{
mController = owner;
mDeckLinkOutput = deckLinkOutput;
}
// etc..
需要访问SyncController
的任何其他ObjC类都将导入“SyncController.h”。任何其他ObjC ++类都可以导入“SyncController.h”或“SyncController_CPP.h”
答案 4 :(得分:1)
初始化
syncController.playerDelegate = new PlaybackDelegate();
// use the pointer
PlaybackDelegate *playbackDelegate = (PlaybackDelegate *)syncController.playerDelegate