Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
@在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 - Fatal编程技术网

@在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]) }

@在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

我在将第4项翻译成Objective-C时遇到了很多麻烦,因为我不知道如何合成C数组。具体地说,这就是我目前的情况:

PlayerState.h
@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的。。。但我相信至少概念是一样的。以下是步骤概要:

  • 将变量声明为指针
  • 使用@private防止外部直接访问
  • 将属性声明为指针,指针将设置为指向传递给setter的任何数组
  • 编写或合成setter和getter方法。我对@synthesis的使用似乎使事情变得混乱,并导致内存泄漏,因此我将遵循“编写您自己的路径”
  • (我想这是以前文章中缺少的链接)因为您返回的是C数组,所以使用malloc分配内存。init方法可能是实现这一点的好地方,您可以使用dealloc或其他方法调用free(myBuffers),因为您的变量具有适当广泛的作用域
  • 我不知道@synthesis it会为您处理malloc'd变量,但其他人可能有我所缺乏的经验。因此,我只是在写二传手和传手。但请注意,我们仍然可以在接口中看到点语法和@property的普通外观

    以下是代码:

    在PlayerState.h中:

    @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])
    }