@在Objective-C2.0中合成C结构数组 我试图在Mac OS X API(音频队列服务)中遵循C++接口的教程,但是在COCOA(实际上,只是基础)应用程序(实际上,只是一个工具)。它的结构如下所示: static const int kNumberBuffers = 3; // 1 struct AQPlayerState { AudioStreamBasicDescription mDataFormat; // 2 AudioQueueRef mQueue; // 3 AudioQueueBufferRef mBuffers[kNumberBuffers]; // 4 AudioFileID mAudioFile; // 5 UInt32 bufferByteSize; // 6 SInt64 mCurrentPacket; // 7 UInt32 mNumPacketsToRead; // 8 AudioStreamPacketDescription *mPacketDescs; // 9 bool mIsRunning; // 10 }; -(void)methodOfOtherClass { PlayerState * playerState = [[PlayerState alloc] init]; AudioQueueBufferRef abc[3] = //something [playerState setMyBuffers:(AudioQueueBufferRef*)abc]; DLog(@"I'm in OtherClass and playerState.myBuffers returns %@, %@, %@", playerState.myBuffers[0],playerState.myBuffers[1],playerState.myBuffers[2]) abc[1] = 6.22; // reassigning one of the values in our local variable playerState.myBuffers = (GLfloat*)abc; //call the setter again, with dot syntax this time if you like DLog(@"I'm in OtherClass and playerState.myBuffers returns %@, %@, %@", playerState.myBuffers[0],playerState.myBuffers[1],playerState.myBuffers[2]) [playerState setMyBuffersA:yourStructA B:yourStructB C:yourStructC]; DLog(@"I'm in OtherClass and playerState.myBuffers returns %@, %@, %@", playerState.myBuffers[0],playerState.myBuffers[1],playerState.myBuffers[2]) }
我在将第4项翻译成Objective-C时遇到了很多麻烦,因为我不知道如何合成C数组。具体地说,这就是我目前的情况: PlayerState.h@在Objective-C2.0中合成C结构数组 我试图在Mac OS X API(音频队列服务)中遵循C++接口的教程,但是在COCOA(实际上,只是基础)应用程序(实际上,只是一个工具)。它的结构如下所示: static const int kNumberBuffers = 3; // 1 struct AQPlayerState { AudioStreamBasicDescription mDataFormat; // 2 AudioQueueRef mQueue; // 3 AudioQueueBufferRef mBuffers[kNumberBuffers]; // 4 AudioFileID mAudioFile; // 5 UInt32 bufferByteSize; // 6 SInt64 mCurrentPacket; // 7 UInt32 mNumPacketsToRead; // 8 AudioStreamPacketDescription *mPacketDescs; // 9 bool mIsRunning; // 10 }; -(void)methodOfOtherClass { PlayerState * playerState = [[PlayerState alloc] init]; AudioQueueBufferRef abc[3] = //something [playerState setMyBuffers:(AudioQueueBufferRef*)abc]; DLog(@"I'm in OtherClass and playerState.myBuffers returns %@, %@, %@", playerState.myBuffers[0],playerState.myBuffers[1],playerState.myBuffers[2]) abc[1] = 6.22; // reassigning one of the values in our local variable playerState.myBuffers = (GLfloat*)abc; //call the setter again, with dot syntax this time if you like DLog(@"I'm in OtherClass and playerState.myBuffers returns %@, %@, %@", playerState.myBuffers[0],playerState.myBuffers[1],playerState.myBuffers[2]) [playerState setMyBuffersA:yourStructA B:yourStructB C:yourStructC]; DLog(@"I'm in OtherClass and playerState.myBuffers returns %@, %@, %@", playerState.myBuffers[0],playerState.myBuffers[1],playerState.myBuffers[2]) },c,objective-c,cocoa,macos,C,Objective C,Cocoa,Macos,我在将第4项翻译成Objective-C时遇到了很多麻烦,因为我不知道如何合成C数组。具体地说,这就是我目前的情况: PlayerState.h @synthesis buffers编译失败,如下所示:“错误:合成属性'buffers'的名称必须与兼容的ivar相同,或者必须显式命名ivar” 这显然是因为相应的ivar被命名为\u buffers,而不是buffers——但这是必要的,因为我不能将属性定义为数组(我可以吗?@property(assign)*AudioQueueBufferRe
@synthesis buffers
编译失败,如下所示:“错误:合成属性'buffers'的名称必须与兼容的ivar相同,或者必须显式命名ivar”
这显然是因为相应的ivar被命名为\u buffers
,而不是buffers
——但这是必要的,因为我不能将属性定义为数组(我可以吗?@property(assign)*AudioQueueBufferRef buffers
是语法错误)
我如何将ivar定义为一个AudioQueueBufferRef
结构的数组,或者合成属性,使其引用\u buffers
数组?编辑:指出C中的数组与指针不同。(详情请参见)。这可以解释您看到的错误,并且会使我发布的代码出错
在这个问题的背景下,链接到中的建议a,我已经复制了:
// PlayerState.h:
@interface PlayerState : NSObject
{
AudioQueueBufferRef _buffers[3];
}
@property(readonly) AudioQueueBufferRef * buffers;
这将允许您访问
缓冲区
,就像它是指向AuidoQueueBufferRef
对象数组的指针一样。这里的问题如下:
为什么要将结构转换为Objective-C对象?Objective-C是C的一个严格的超集,因此您可以使用Objective-C的给定结构 [EDIT]针对您的评论,编译器正在抱怨
mBuffers
声明,因为有关于静态数组大小的规则。C中的规则比C++中的规则要严格一些。作为一个简单的解决方法,只需更改线路即可
static const int kNumberBuffers = 3;
进入
然后结构应该正确编译(当然,前提是您包含了定义所有正确数据类型的必要头,例如AudioStreamBasicDescription
,等等)
@synthesis buffers
编译失败,如下所示:“错误:合成属性'buffers'的名称必须与兼容的ivar相同,或者必须显式命名ivar”
尝试:
您可以有三个缓冲区IVAR(buffer0、buffer1、buffer2),也可以将其设置为指向AudioQueueBufferRef的指针,并分别分配内存以容纳这三个AudioQueueBufferRef。如果需要可变数量的缓冲区,也可以使用NSArray或NSData 但回到更大的上下文,您可能不需要跟踪AudioQueueBufferRef。如果将所有三个缓冲区排队,则会在音频队列回调中得到指向它们的指针 我有一些音频代码记录和播放音频,它调用AudioQueueAllocateBuffer()和audioQueueBuffer(),然后几乎忘记了缓冲区 如果您试图为AudioQueue编写Cocoa包装器,请不要这样做
编辑:但要回答您最初的问题:不能将数组作为属性,因为它不是“纯Ol”数据类型。请参阅Xcode中Objective-C2.0文档中的“声明的属性”,这是:我正在为OpenGL应用程序做类似的事情,因为这是一个有用的问题(而且很久没有答案),所以我想转换我的解决方案。请注意,使用NSArray可能不那么费力……但如果您需要改进性能和/或使用基本C(或GL或类似的非对象)类型,这应该会有所帮助。另外,如果我做了一些在OSX中不起作用的事情,请原谅,因为我的代码实际上是针对iPhone的。。。但我相信至少概念是一样的。以下是步骤概要:
@interface PlayerState : NSObject {
AudioStreamBasicDescription dataFormat;
AudioQueueRef queue;
@private
AudioQueueBufferRef *myBuffers;
// [...]
@property(assign) AudioStreamBasicDescription dataFormat;
@property(assign) AudioQueueRef queue;
@property(assign) AudioQueueBufferRef *myBuffers;
这将为您提供一个指针和一个属性,后者相当于指针所指示内存的访问器方法。我们将编写自己的访问器,并为指针分配内存,并为指针提供指向的内容
现在在PlayerState.m中:
-(id)init
{
if (self = [super init]) {
myBuffers = (AudioQueueBufferRef*)malloc(sizeof(AudioQueueBufferRef) * 3);
/* memory is allocated. Free it elsewhere. Note that "Leaks" will
probably falsely flag this, but you can test it in Object Allocations
and see that it is clearly released. */
}
return self;
}
// return an array of structs
-(AudioQueueBufferRef*)myBuffers
{
// you can check for values, etc here, but basically it all comes down to:
return myBuffers;
}
// the setter; there are several ways to write it, depending on what your objective
-(void)setMyBuffers:(AudioQueueBufferRef*)abc
{
int i = 3;
while (i > 0) {
i--;
myBuffers[i] = abc[i];
}
//another possible implementation, not tested
//free(myBuffers);
//myBuffers = NULL;
//myBuffers = xyz;
}
// if you want to set individual attributes, you can have another method like:
-(void)setMyBuffersA:(AudioQueueBufferRef)a B:(AudioQueueBufferRef)b C:(AudioQueueBufferRef)c
{
myBuffers[0] = a;
myBuffers[1] = b;
myBuffers[2] = c;
}
现在您可以从另一个类调用这些函数,如下所示:
static const int kNumberBuffers = 3; // 1
struct AQPlayerState {
AudioStreamBasicDescription mDataFormat; // 2
AudioQueueRef mQueue; // 3
AudioQueueBufferRef mBuffers[kNumberBuffers]; // 4
AudioFileID mAudioFile; // 5
UInt32 bufferByteSize; // 6
SInt64 mCurrentPacket; // 7
UInt32 mNumPacketsToRead; // 8
AudioStreamPacketDescription *mPacketDescs; // 9
bool mIsRunning; // 10
};
-(void)methodOfOtherClass
{
PlayerState * playerState = [[PlayerState alloc] init];
AudioQueueBufferRef abc[3] = //something
[playerState setMyBuffers:(AudioQueueBufferRef*)abc];
DLog(@"I'm in OtherClass and playerState.myBuffers returns %@, %@, %@", playerState.myBuffers[0],playerState.myBuffers[1],playerState.myBuffers[2])
abc[1] = 6.22; // reassigning one of the values in our local variable
playerState.myBuffers = (GLfloat*)abc; //call the setter again, with dot syntax this time if you like
DLog(@"I'm in OtherClass and playerState.myBuffers returns %@, %@, %@", playerState.myBuffers[0],playerState.myBuffers[1],playerState.myBuffers[2])
[playerState setMyBuffersA:yourStructA B:yourStructB C:yourStructC];
DLog(@"I'm in OtherClass and playerState.myBuffers returns %@, %@, %@", playerState.myBuffers[0],playerState.myBuffers[1],playerState.myBuffers[2])
}
这对我使用iPhone操作系统和我的openGL类型(承认有点不同)测试没问题。然而,我认为它也会对你有用。您可能需要调整某些内容,或者我在复制和粘贴原始代码时引入了一个小的打字错误。另外,如果您喜欢在编写代码时像我一样记录东西,那么记录缓冲区结构的某些成员可能会更有用,这样可以查看所存在的内容和应该存在的内容
另外,如果您习惯于在使用NSLog包装器编写代码时打印对象,即:DLog(@“array is%@”,myNSarray)
您将获得<
@interface PlayerState : NSObject {
AudioStreamBasicDescription dataFormat;
AudioQueueRef queue;
@private
AudioQueueBufferRef *myBuffers;
// [...]
@property(assign) AudioStreamBasicDescription dataFormat;
@property(assign) AudioQueueRef queue;
@property(assign) AudioQueueBufferRef *myBuffers;
-(id)init
{
if (self = [super init]) {
myBuffers = (AudioQueueBufferRef*)malloc(sizeof(AudioQueueBufferRef) * 3);
/* memory is allocated. Free it elsewhere. Note that "Leaks" will
probably falsely flag this, but you can test it in Object Allocations
and see that it is clearly released. */
}
return self;
}
// return an array of structs
-(AudioQueueBufferRef*)myBuffers
{
// you can check for values, etc here, but basically it all comes down to:
return myBuffers;
}
// the setter; there are several ways to write it, depending on what your objective
-(void)setMyBuffers:(AudioQueueBufferRef*)abc
{
int i = 3;
while (i > 0) {
i--;
myBuffers[i] = abc[i];
}
//another possible implementation, not tested
//free(myBuffers);
//myBuffers = NULL;
//myBuffers = xyz;
}
// if you want to set individual attributes, you can have another method like:
-(void)setMyBuffersA:(AudioQueueBufferRef)a B:(AudioQueueBufferRef)b C:(AudioQueueBufferRef)c
{
myBuffers[0] = a;
myBuffers[1] = b;
myBuffers[2] = c;
}
-(void)methodOfOtherClass
{
PlayerState * playerState = [[PlayerState alloc] init];
AudioQueueBufferRef abc[3] = //something
[playerState setMyBuffers:(AudioQueueBufferRef*)abc];
DLog(@"I'm in OtherClass and playerState.myBuffers returns %@, %@, %@", playerState.myBuffers[0],playerState.myBuffers[1],playerState.myBuffers[2])
abc[1] = 6.22; // reassigning one of the values in our local variable
playerState.myBuffers = (GLfloat*)abc; //call the setter again, with dot syntax this time if you like
DLog(@"I'm in OtherClass and playerState.myBuffers returns %@, %@, %@", playerState.myBuffers[0],playerState.myBuffers[1],playerState.myBuffers[2])
[playerState setMyBuffersA:yourStructA B:yourStructB C:yourStructC];
DLog(@"I'm in OtherClass and playerState.myBuffers returns %@, %@, %@", playerState.myBuffers[0],playerState.myBuffers[1],playerState.myBuffers[2])
}