I'm trying to extend a piece of code that uses the SuperPowered audio library in an iOS application. In particular, I'm interested in the void playerEventCallback(void *clientData, SuperpoweredAdvancedAudioPlayerEvent event, void *value)callback, which gets passed a pointer to the managing SuperPowered object when the audio player is created:
SuperpoweredAdvancedAudioPlayer(void *clientData, SuperpoweredAdvancedAudioPlayerCallback callback, unsigned int sampleRate, unsigned char cachedPointCount, unsigned int internalBufferSizeSeconds = 2, unsigned int negativeSeconds = 0);
If I understand the code right, nothing prevents me from modifying this situation for my own purpose, passing, for example, a pointer to an object in an array, which would identify the player that is/was running, instead of the managing SuperPowered object.
Can I do that, or is there a consequence I should be aware of?
I ended up doing exactly that, passing an instance of a struct defined as follows:
struct AudioPlayerWithIndex {
int index;
SuperpoweredAdvancedAudioPlayer* player;
Superpowered* superpoweredInstance;
AudioPlayerWithIndex(int index, SuperpoweredAdvancedAudioPlayer* player, Superpowered* superpoweredInstance) : index(index), player(player), superpoweredInstance(superpoweredInstance) {}
};
Related
Just did a standard job interview is to calculate the volume of water in the histogram. On Monday this code worked, and still works on this site. After updating vala, an error is now displayed.
UPD: more easy example
> Algoritm.vala:2.5-2.16: error: struct `Algotitm.first' cannot be empty
> struct first {
> ^^^^^^^^^^^^ Algoritm.vala:6.5-6.17: error: struct `Algotitm.second' cannot be empty
> struct second {
When posting a question on Stack Overflow it is always good to post an example of the code that is a minimum, complete and verifiable example.
From the link you've provided it appears you have a struct with only members marked as static:
struct First {
static int data;
static int pos;
}
void main () {
}
Marking the fields as static means they aren't instance fields and so the struct is empty of fields. That's why you are getting the error message about the struct being empty. I'm not sure Vala should even allow marking struct fields as static, but it does make sense to allow methods in structs to be static.
You need to remove the static modifiers. This will work:
struct First {
int data;
int pos;
}
void main () {
}
Update
I'm guessing you are trying to write performance optimized code and you think static helps with that. static in Vala means there is no instance data to use. If you are using a data structure like a class or struct then it only makes sense to have instances of those. If you want something to remain unchanged during the running of your program use const in a namespace.
Using a struct may give you a slight performance boost if your are using a very large number in your program. structs created in Vala are allocated on the stack instead of the heap so may be slightly faster. If you are passing structs around you may want to consider [SimpleType] attribute. That means structs will be passed by value in C as well as Vala. Without the [SimpleType] they are copied and passed by reference at the C level, which appears as copy by value in Vala.
Structs in Vala can have initializers (similar to a constructor for a class) and methods. So what I can extract from your second pastebin you could write that as:
struct First {
int data;
int pos;
public First (int[] mass) {
data= 5;
pos = mass.length;
}
public int sas () {
return data + pos;
}
}
void main () {
int[] a = {1,3,0,1,2,3,2,1};
var b = First (a);
print (#"$(b.sas ())\n");
}
That is a follow on question though and should be asked as a second question on Stack Overflow. This is a public forum that follows a format that allows other people to learn from the question and answers.
This question already has answers here:
How do SEL and #selector work? [duplicate]
(2 answers)
Closed 8 years ago.
I've found that the SEL type has the next definition:
typedef struct objc_selector *SEL;
But I can't find how is objc_selector implemented.
Okay, if we have the next code
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
SEL mySelector = NSSelectorFromString(#"mySelector");
return 0;
}
, then mySelector is just a pointer. Following the address which it contains, we see the C-string, which can be presented like:
const char* mySelector = "mySelector";
But objc_selector is not a C-string, it is structure and it can contain something else. So I want to know how objc_selector structure is implemented.
This might help you:
Now this one is fun and interesting. SEL is the type of a "selector" which identifies the name of a method (not the implementation). So, for example, the methods -[Foo count] and -[Bar count] both share a selector, namely the selector "count". A SEL is a pointer to a struct objc_selector, but what the heck is an objc_selector? Well, it's defined differently depending on if you're using the GNU Objective-C runtime, or the NeXT Objective-C Runtime (like Mac OS X). Well, it ends up that Mac OS X maps SELs to simple C strings. For example, if we define a Foo class with a - (int)blah method, the code NSLog(#"SEL = %s", #selector(blah)); would output SEL = blah.
Taken from: here
I am working on a chess engine in C/Objective-C and I rewrote a large part of my engine in straight-c to improve the speed. My question is, I have about 3KB of tables I initialize in my C file that I don't want to reinitialize every time a function from this file is called. If this were a regular objective-c class I would create a shared instance. However, the core of my engine is in two .h and a .c files. Should I make all of the tables used by my engine static? Will they persist between multiple other files calling functions in my engine? Should I make a static struct to hold my tables? I'm not sure what the best approach is here. Thanks!
Example:
Test.h:
int getInt(int index);
Test.c:
static int integers[4] = {1,2,3,4};
int getInt(int index) { return integers[index]; }
Every time I call getInt from another file, will it reallocate 'integers'? Or will it reuse the same array? I want to prevent it from unnecessarily reallocating a bunch of static arrays.
Ok, what you did was accessor on a static variable...
A static is only initialized once, so it does get initialized only once per launch.
You can keep it this way, or change it to a global to access it without calling function.
This code could typically get inlined, so changing it to a global is more a matter of taste than performances.
Edit: short summary on allocations
static int array[] = {1, 2}; // Allocated and initialized once
int array2[] = {1, 2, 3}; // Allocated and initialized once
int function() {
int array3[] = {1, 2, 3}; // Allocated and initialized at every call of function();
static int *array4 = malloc(42); // Allocated and initialized once
int *toto = malloc(42); // Allocated at every call of function();
}
I'm currently playing with AudioQueue services, and I have a small problem.
The AudioQueue has a bunch of callbacks, each of which can carry a "user data", a pointer basically. I wish I could pass one of my objects as this pointer.
So what happens is that, on certain occasions, the AudioQueue is calling my callback in a way close to this:
static void HandleOutputBuffer (
void *aqData,
AudioQueueRef inAQ,
AudioQueueBufferRef inBuffer
) {
MyPlayerData *mpd = (MyPlayerData *)aqData;
...
}
This usually works good, but when my player reaches the end of the media, it is deallocated. But often times the callback HandleOutputBuffer is called after the MyPlayerData object is deallocated, resulting in a nice segfault.
I wish I could use a weak reference for this. Is there any way I could have an ARC void * pointer? Something that would be set to nil whenever the object is deallocated?
I'm currently looking at __weak, but I'm not sure this is the right tool to use...
ARC cannot manage a void * reference to an object and set it to NULL if the object is
deallocated.
You have two different options when creating the context pointer from the object pointer:
const void *context = (__bridge void *)mpd;
This is what you do now. In this case, you have to ensure that the object exists
as long as the audio queue uses it in the callback.
const void *context = (__bridge_retained void *)mpd;
This increases the retain count of the object, so that the object is "kept alive",
i.e. it will not be deallocated.
In this case, you have to release this reference eventually when it is no longer needed,
with CFRelease(context).
Reference: http://clang.llvm.org/docs/AutomaticReferenceCounting.html#bridged-casts
I'm using The Amazing Audio Engine to handle playback in syncing in an iOS app.
The framework requires you to use C functions as the call back (playbackTimingReceiver) which is called on the audio thread. You then need to message the main thread again using a C function (AEAudioControllerSendAsynchronousMessageToMainThread) to which you pass a handler (pageTurnHandler).
I'm not overly experienced working with C but as I understand it I'm passing a pointer in the message which needs to be dereferenced.
Which I can achieve successfully with the line:
PlaybackManager* receiver = *((PlaybackManager**)userInfo);
But only if I turn ARC off in the project for that file using the -fno-objc-arc flag in compiled sources on the projects target.
To my question, is it possible to achieve this with ARC turned on? If so what is the correct syntax?
Relevant code segment:
#pragma mark - Audio Timing Callback
-(AEAudioControllerTimingCallback)timingReceiverCallback
{
return playbackTimingReceiver;
}
static void playbackTimingReceiver(PlaybackManager* receiver,
AEAudioController *audioController,
const AudioTimeStamp *time,
UInt32 const frames,
AEAudioTimingContext context)
{
receiver->_hostTime = getUptimeInMilliseconds(time->mHostTime);
AEAudioControllerSendAsynchronousMessageToMainThread(audioController,
pageTurnHandler,
&audioController,
sizeof(id));
}
static void pageTurnHandler(AEAudioController *audioController, void *userInfo, int userInfoLength)
{
PlaybackManager* receiver = *((PlaybackManager**)userInfo);
NSLog(#"Receiver:%#", receiver);
}
PlaybackManager * receiver = (__bridge_transfer id)*(void **)userInfo;
should do the trick. This first casts the userInfo to a pointer-to-pointer, because it contains the address of the original object pointer. Dereference that to get the original pointer, and use __bridge_transfer with a type -- id or PlaybackManager will work -- to tell ARC that the dereferenced value is actually an object that it needs to take care of.
Without running the code there appear to be two errors:
1) You are passing the contents of audioController when it looks like you meant to pass the contents of receiver - so last two args to AEAudioControllerSendAsynchronousMessageToMainThread should be &receiver & sizeof(PlaykbackManager *)
2) You need a bridge cast to get the object reference back out
Something like:
static void playbackTimingReceiver(PlaybackManager* receiver,
AEAudioController *audioController,
const AudioTimeStamp *time,
UInt32 const frames,
AEAudioTimingContext context)
{
receiver->_hostTime = getUptimeInMilliseconds(time->mHostTime);
AEAudioControllerSendAsynchronousMessageToMainThread(audioController,
pageTurnHandler,
&receiver,
sizeof(PlaybackManager*));
}
static void pageTurnHandler(AEAudioController *audioController, void *userInfo, int userInfoLength)
{
PlaybackManager* receiver = (__bridge Playback *)*((PlaybackManager**)userInfo);
NSLog(#"Receiver:%#", receiver);
}
Note: when passing object references from the ARC controlled world to the C world you often transfer ownership on the way in - so ARC doesn't release the referenced object - and transfer ownership back on the way back out - so ARC resumes ownership management. However due to the nature of AEAudioControllerSendAsynchronousMessageToMainThread, where userInfo is passed by address and copied internally - hence the size argument, it is tricker to transfer ownership. Therefore the above code does not. This means you must make sure that whatever object receiver references stays alive by having another owner.
You can just tell ARC the type of storage you would like:
PlaybackManager *audioBufferPlayer = *(__weak PlaybackManager **)userInfo;
Just be sure to do necessary nil checks before accessing any properties or calling any methods.