I am working with a C program to try and use it in my iOS application with as little modification as possible. The C program performs a lot of calculations on a set of inputs.
On the iOS side, I am using the following code to create a thread to run the calculations, and also to have a mechanism to report when it is complete (currently, it updates a UILabel os "testLabel" when complete):
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
char *testChar = startProgram( nx, ny, nz ); // this is where I call the C program
dispatch_async(dispatch_get_main_queue(), ^{
NSString *tempString = [[NSString alloc]initWithCString: testChar ];
testLabel.text = tempString;
[tempString release];
});
});
This seems to work, I get my results, and my UI stays responsive.
However, I am wanting to communicate from the C routine back to the UI while the calculations are going on in order to get status as well as to pass some data back incrementally.
So my C program would be something like this:
char* startProgram( int nx, int ny, int nz )
{
setupEverything(); // this is just pseudo code for clarity
for( int i = 0; i < nz; i++ )
{
doMajorCalculations();
reportBackToUI( someResults ); // This is what I would LIKE to do
}
}
I saw a thread on here about passing "self", but I don't think the "self" if passed above would be my class "self". In addition, I tried that and got an error on the C-side of things, saying that it did not recognize the type "id". I changed the type of "id" to the class name, and it told me the parameter was wrong.
Any ideas on the best way to implement this?
Thank you for your help.
declare a global c void*
void* sipUACObj;
And assign it the objective-c class object in your class initializer
sipUACObj = self;
Now whenever you need to invoke something from C function do the following,
ObjcClass *obj = (ObjcClass*) sipUACObj;
[obj someMethod:arg1 Arg2:arg2];
This will call the corresponding objective-C function and you can invoke ur main UI thread in that function.
You could create a singleton class and assign it to the void pointer in its initialization and then do the needful in ur C function.
Maybe what you want is to have a block as a callback for reporting back partial results to the caller. Something like this:
char* startProgram( int nx, int ny, int nz, void(^reportBackToUI)(int) )
{
setupEverything(); // this is just pseudo code for clarity
for( int i = 0; i < nz; i++ )
{
doMajorCalculations();
reportBackToUI( someResults ); // This is what I would LIKE to do
}
}
Then the client could call startProgram using something like:
return startProgram(42, 12, 20, ^(int someResults) {
dispatch_async(dispatch_get_main_queue(), ^{
// Update UI in some way.
});
});
This way your code will have no dependency on what or how the client do and uses the progress callback for. Also it is nice dependency injection.
If using blocks is not possible (model code might need to be pure C to work on other platforms?) then you can switch the block for a function pointer.
Related
Suppose I have a need for multiple block "calls", for instance a loop in which the block is passed to a another function in each iteration. Do I need to make a new block instance each time I call the function (like Example 1) or can I make one block instance that is called each time (like Example 2)?
//Example 1:
while(true){
void (^block)(NSString* test)=^(NSString* test){
//do something
};
[self callWithBlock: block];
}
//Example 2
void (^block)(NSString* test)=^(NSString* test){
//do something
};
while(true){
[self callWithBlock: block];
}
It compiles and runs fine the second way, but I suspect that any concurrency issues may not be immediately obvious.
You can call blocks as often as you want. But you need to be careful about the context that is captured by the block.
If you have any values that are captured by your block, keep in mind, that unless when specifying them as __block variables, they will be copied.
So for example, this code:
int anInteger = 42;
void (^testBlock)(void) = ^{
NSLog(#"Integer is: %i", anInteger);
};
anInteger = 84;
testBlock();
will print 42, not 84.
If you declare anInteger as __block int anInteger = 42, the storage will be shared and the code will print 84.
So, if you have code that is something like:
int foo = 42;
void (^block)(void) = ^{
NSLog(#"%i", foo);
}
while (true) {
block();
foo++;
}
the behavior will be different from
int foo = 42;
while (true) {
void (^block)(void) = ^{
NSLog(#"%i", foo);
}
block();
foo++;
}
This will also apply to pointers and NSObject variables, when you reassign the variable that holds the pointer or object.
To find out more, have a look at Working with Blocks from the Apple developer documentation.
I cannot seem to solve this problem, im not sure what it is at this point but the tread error wont go away. I cant seem to find what im doing wrong.
This code may be a handful to read (sorry) but its very simple. I'am basically invoking a function from main and passing an array of function values, from there im passing two fractions at a time to a method so it find the LCM(least common multiple) using the denominators and return the value. But a thread error seems to be occurring at the call to the findLCM method from function at the point of where the method is declared.
#interface Fraction: NSObject
#property int numerator, denominator;
-(Fraction *)findLCM:(Fraction *)fraction withXFractions:(int)Xfraction;
#implementation Fraction
-(Fraction *)findLCM:(Fraction *)fraction withXFractions:(int)Xfraction{
int lcmOfFraction = 0;
int a, b;
a = fraction.denominator;
b = self.denominator;
int max =(a>b) ? a : b; // get max value out of the two denominators.
for (int i = 0; i < Xfraction; i++) {
while(1) /* Always true. */
{
if(max%a==0 && max%b==0)
{ lcmOfFraction = max;
break; /* while loop terminates. */
}
++max;
}
}
Fraction *lcmDenominator = [Fraction new];
[lcmDenominator setTo:0 over:max]; //passing just LCM (denominator of 2 fractions)
return lcmDenominator;
}
Fraction *addFraction(Fraction **arrayOfFractions, int arraySize) {
Fraction *LCM = [[Fraction alloc] init];
int lcmOfFractions = 0;
[LCM setTo:0 over:1];
for (int i = 0; i <= arraySize; i++) {
LCM = [LCM findLCM:arrayOfFractions[i] withXFractions:4];
//^gets the LCM (the common denominator)
}
return LCM;
}
int main () {
#autoreleasepool {
[frac1 setTo:2 over:12]; [frac2 setTo:2 over:4];
[frac3 setTo:6 over:8]; [frac4 setTo:8 over:3];
Fraction __autoreleasing *arrayOfFractions[4] = {frac1, frac2, frac3, frac4 };
Fraction *LCMFraction = addFraction(arrayOfFractions, 4);
//common LCM return
}
}
You create no threads in this code. When asking a question like this you should clearly explain what the error is, and what you have tried to find its source. People may then be able to help you.
Some hints/suggestions:
use breakpoints to stop your code during execution to allow you to examine the values of your variables
pay close attention to indexing operations, you are using a C array and those do not do bounds checking
ask whether using a C array here, rather than an NSArray is your best choice. Note there is nothing wrong with using C arrays when appropriate.
__autoreleasing probably doesn't mean what you think it does, it is rare to see this used explicitly in user code.
If you have a specific question when you've got further ask a new question on SO, somebody will probably be able to help you out.
HTH
Is it possible to implement something like a Smalltalk-style whileTrue: method in Objective-C using blocks? Specifically, instead of:
int count = 0;
while (count < 10)
{
NSLog(count);
count++;
}
I'd like to be able to do (via a wrapper on the bool primitive called OOBoolean) something like...
__block int count = 0;
[[OOBoolean booleanWithBool: count < 10] whileTrueDo: ^() {
NSLog(count);
count++;
}];
I'm having trouble understanding how this would be implemented though...
Here you have a couple of ideas,
Assuming your bool wrapper implements boolValue, a naive implementation could be:
-(void) whileTrueDo:(void (^)(void)) block{
while ([self boolValue]) {
block();
}
}
In order for the wrapper to change its bool value after each iteration, the block must be able to actually change the variable that is used to calculate the boolean condition. So, in your case, by setting the __block type modifier to count, and increasing count in each block execution, you should be able to make it work.
The problem is, if you create your wrapper by sending the evaluated condition, as you stated in your question, you wont be able to change its bool value in each iteration. So, I would change the way the wrapper is created and the whileTrueDo: naive implementation so the boolean wrapper uses an evaluation block.
__block int count = 0;
OOBooleanBlock evaluationBlock = ^BOOL{
return count < 10;
};
[[OOBoolean booleanWithBlock:evaluationBlock] whileTrueDo: ^() {
NSLog(count);
count++;
}];
//In OOBoolean
+(OOBoolean*) booleanWithBlock:(OOBooleanBlock) evaluationBlock{
//Instantiate, set the evaluationBlock ivar and return the ooboolean object.
}
-(void) whileTrueDo:(void (^)(void)) block{
while (self.evaluationBlock()) {
block();
}
}
Remember to use the __block type modifier, otherwise you will enter in an infinite loop.
I haven't tested this, I hope this helps you though.
Cheers
I've started using blocks, and one of the first things I encountered is an inability to set values which are captured by the closure. This is fine, I've been using C/C++ a long time. I'll just use pointers!
MyObject* bestObj = nil;
float bestDist= 10000.f;
MyObject **pBestObj = &bestObj;
float* pBestDist = &bestDist;
[self testObjects:class block:^(MyObject* obj){
CGRect r = [obj boundingBox];
// position is captured from outside this code sample
if( CGRectContainsPoint( r, position ) )
{
float dist = GetDistance( obj, position );
if(dist < bestDist)
{
*pBestDist = dist;
*pBestObj = obj;
}
}
}];
return bestObj;
My question is, is this safe? I assume that as long as my pointer points to something that hasn't gone out of scope and that still exists, that it should work. But I'm also assuming that things that take blocks don't ever, say, run them in parallel. I know my code doesn't, but I don't know about, say, using a block with an NSArray enumerateObjectsUsingBlock call.
The 'right' way to do this would be to mark those original variables as block mutable, __block
I created a new function to log every method from a class in runtime.
The problem that I have is in this line :
id value = va_arg(stackFrame, id);
Doesn't convert the type of object inside the arguments.
Any idea on what I'm doing wrong? Is there another way to do this?
void DebugArguments ( id self, SEL _cmd,...)
{
id receiver = self;
SEL receiverSelector = _cmd;
va_list stackFrame;
va_start(stackFrame, _cmd);
NSMethodSignature *signature
= [receiver methodSignatureForSelector:receiverSelector];
NSUInteger count = [signature numberOfArguments];
NSUInteger index = 2;
for (; index < count; index++)
{
id value = va_arg(stackFrame, id);
if (!value)
{
NSLog(#"Arguments: %#",value);
}
}
va_end(stackFrame);
}
I call the function InitDebug from a class like this : -
(void)MyTest:(NSString *)string {
InitDebug(self, _cmd); } I hope
to log the Argument string from the
method MyTest.
In the future, it is helpful to show all the code.
In any case, you can't do that; when you call InitDebug(...), you are pushing a new frame onto the stack and va_arg() will decode in the context of that frame, not the surrounding frame. Nor can you "go up the stack" and start grubbing about in the arguments of the calling frame as there is no guarantee that the calling frame is even preserved at that point.
If you really want to do something like this, you would probably want to subclass NSProxy and use it is a proxy between the caller and whatever object you want to log. You could then leverage the built-in forwarding mechanism of Objective-C to muck about with the arguments.