Obj-C function declaration needs semi-colon? - objective-c

This is really simple but driving me nuts.
I am trying to implement a simple function in my Objective-C code. When I write this,
NSInteger Sort_Function(id id1, id id2, void *context) {
}
I get an error that a semi-colon was expected at the end of the declaration. However, I've seen this type of syntax in many, many examples. What could I possibly be doing wrong? If it matters, this is an iOS app and the function is nested in an if clause. Thanks in advance.

The function definition -- this snippet you posted -- is "nested in a if clause"? That's unfortunately illegal in C (and Obj-C by extension) -- all function declarations and definitions have to be at the top level of the file. Inside an #implementation section is also an option:
// Start of file
// Declaration or definition valid here
void my_func(void); // Declaration
void my_other_func(void);
void my_third_func(void);
void my_func(void) { // Definition
return;
}
#implementation MyClass
// Definition also valid here
void my_other_func(void) {
return;
}
- (void) myMethod {
if( YES ){
void my_third_func(void) { // Invalid here
return;
}
}
}
#end
Is it possible you're confusing the function syntax with block syntax?
// The caret indicates definition of a block, sort of an anonymous function
int (^myBlock)(int);
myBlock = ^int (int my_int) {
return my_int;
};

Related

Parallel for loop in c++/cli

Parallel.For(<your starting value >,<End criteria for loop>, delegate(int < your variable Name>)
{
// Your own code
}); 
Here above I am showing some sample code in C#. I want similar functionality in C++/CLI but I don't know how to use this expression: "delegate(int < your variable Name>)".
If you are using c++cli, then you should be able to use the same Parallel.For that you use in C# since System.Threading.Tasks.Parallel is a regular .Net Framework class
Example (untested, not even compiled):
ref class SomeClass
{
public:
static void Func(int index)
{
Console::WriteLine("Test {0}", index);
}
};
delegate void MyCallback(int index);
int main( )
{
MyCallback^ callback = gcnew MyCallback(SomeClass::Func);
Parallel.For(0, 9, callback);
}
Relevant: How to: Define and Use Delegates in C++/CLI

Void in Objective-C

I am learning Objective-C and I am wondering when people say that when you out void in a method it means that method returns nothing. What does that exactly mean? What would it "return" if it wasn't void? Please help.
void is exactly what you said, its just a word you use to let the compiler know that this function doesnt return anything, and you may omit the return statement in the function eg
- (void) myMethod {
//do something here
}
where as if a method has a return type, then you would get a compile error if you didnt return something of that type
- (BOOL) myMethod {
BOOL x = false;
//do something
return x;
}
so here we can see, in your words "What would it "return" if it wasn't void?" that it would return whatever you tell it to, the return type when you declare the method just needs to match what you are actually returning and thats all really.
note you can still return in a void function, but all it does is prematurely end the functions execution, eg
- (void) myMethod {
BOOL x = false;
if(x == false)
return;
x = true;
}
here we can see that the statement x = true will never execute, because it will go into the if statement and return, which will end the function (and not return anything)
It would return whatever it has been declared/written to.

Fails to write proper syntax for block that uses typedef

I have Objective-C code that I try to convert to Swift but failed.
typedef void (^ CDVAddressBookWorkerBlock)(
ABAddressBookRef addressBook,
CDVAddressBookAccessError* error
);
#interface CDVAddressBookHelper : NSObject
{}
- (void)createAddressBook:(CDVAddressBookWorkerBlock)workerBlock;
#end
And this is Objective-C implementation:
CDVAddressBookHelper* abHelper = [[CDVAddressBookHelper alloc] init];
[abHelper createAddressBook:
^(ABAddressBookRef addrBook, CDVAddressBookAccessError* errorCode)
{
/* ...*/
}
];
How to write it in Swift?
From documentation:
{(parameters) -> (return type) in expression statements}
This is a template xCode offers:
This is what I tried:
var abHelper:CDVAddressBookHelper = CDVAddressBookHelper()
abHelper.createAddressBook(
{(addrBook:ABAddressBookRef, errCode:CDVAddressBookAccessError) in
if addrBook == nil {
}
} )
Error:
Type 'ABAddressBook!' does not conform to protocol 'AnyObject'`
[EDIT]
Regards to: swift-closure-declaration-as-like-block-declaration post I tried to write typealias:
typealias CDVAddressBookWorkerBlock = (addrBook:ABAddressBookRef, errCode:CDVAddressBookAccessError) -> ()
What next?
How to make it work?
Thanks,
Check out the docs about how to work with Cocoa and Core Foundation.
This should work:
abHelper.createAddressBook() {
(addrBook:ABAddressBook?, errCode:CDVAddressBookAccessError!) in
if addrBook == nil {
}
}

C++/CLI: Passing C++ class ptr to unmanaged method

I've been given a third party C/C++ library (.dll, .lib, .exp and .h) that I need to use in our C# app.
ThirdPartyLibrary.h contains...
class AClass {
public:
typedef enum {
green = 7,
blue = 16
} Color;
virtual int GetData()=0;
virtual int DoWork(Color, char *)=0;
};
void * Func1(int, AClass **aClass);
In my C++/CLI code I have done this...
#include "ThirdPartyLibrary.h"
using namespace System;
using namespace System::Runtime::InteropServices;
namespace Wrapper {
public ref class MyBridgeClass
{
private:
AClass* pAClass;
public:
// C# code will call this method
void AMethod (int x)
{
int y = x+10;
Func1 (y, &(this->pAClass)); // <-- error!
}
}
}
I get a build error that reads...
cannot convert parameter 2 from 'cli::interior_ptr<Type>' to 'AClass **'
with
[
Type=AClass *
]
Cannot convert a managed type to an unmanaged type
Any ideas? Maybe I need #pragma manage/unmanged tags in my C++/CLI?
The reason you're getting that error is because of how managed memory works.
In your managed class, you've got a pointer defined. The address of that pointer is part of the managed object, and can change when the garbage collector runs. That's why you can't just pass &pAClass to the method, the GC can change what that address actually is.
There's a couple things you can do to fix this:
You could create an unmanaged helper class to hold the AClass* member. I'd do this if that pointer needs to stay valid beyond the invocation of this method, or if you have a lot of unmanaged pointers to hold.
struct UnmanagedHolder
{
AClass* pAClass;
};
public ref class MyBridgeClass
{
private:
// must create in constructor, delete in destructor and finalizer.
UnmanagedHolder* unmanaged;
public:
// C# code will call this method
void AMethod (int x)
{
int y = x+10;
Func1 (y, &(this->unmanaged->pAClass));
}
};
If you only need the pointer to be valid within AMethod, and the pointer doesn't need to remain valid after the call to Func1, then you can use a pin_ptr.
void AMethod (int x)
{
int y = x+10;
pin_ptr<AClass*> pin = &(this->pAClass);
Func1 (y, pin);
}

C++/CLI, "constant" reference to a tracking handle

I have spotted something like this in code:
void foo(IList<int>^ const & list ) { ... }
What does this ^ const& mean? I looked in the C++/CLI specification, but found no comments on making constant tracking references, nor the ^& combo.
Is this legal?
This code was probably written by a C++ programmer that used common C++ idiom to write C++/CLI. It is quite wrong, passing a reference to tracking handle is only possible if the handle is stored on the stack. It cannot work if the passed List<> reference is stored in a field of an object on the heap, the garbage collector can move it and make the pointer invalid. The compiler will catch it and generate an error. The ^ is already a reference, no additional reference is needed.
Without the reference, the const keyword doesn't make a lot of sense anymore either. Not that it ever did before, the CLR cannot enforce it. Not that this mattered much here, this code could not be called from any other .NET language. They won't generate a pointer to the tracking handle.
Just fix it, there's little point in keeping bad code like this:
void foo(IList<int>^ list ) { ... }
Example of code that shows that the reference cannot work:
using namespace System;
using namespace System::Collections::Generic;
ref class Test {
public:
IList<int>^ lst;
void foo(IList<int> const &list) {}
void wontcompile() {
foo(lst); // C3699
IList<int>^ okay;
foo(okay);
}
};
It's a reference which is constant to a tracking handle.
It allows you to pass the handle by reference instead of by value. Presumably the author thinks it's more efficient than copying the handle.
If the author meant to make the handle constant he should have used either of
Method(TestClass const ^ const & parameter)
Method(TestClass const^ parameter)
Or alternatively
Method(TestClass const^& parameter) - but the caller must const up the handle first
with
TestClass const^ constHandle = nonConstHandle
An example of each:
// test.cpp : Defines the entry point for the console application.
#include "stdafx.h"
ref class TestClass
{
public:
void setA(int value)
{
a = value;
}
TestClass() :
a(10)
{
}
private:
int a;
};
class TakesHandle
{
public:
void methodX1(TestClass const ^ const & parameter)
{
// Un-commenting below causes compiler error
// parameter->setA(11);
}
void methodX2(TestClass const^ parameter)
{
// Un-commenting below causes compiler error
// parameter->setA(11);
}
void methodX3(TestClass const^& parameter)
{
// Un-commenting below causes compiler error
// parameter->setA(11);
}
};
int _tmain(int argc, _TCHAR* argv[])
{
TakesHandle takes;
TestClass ^ test1 = gcnew TestClass();
// compiles
takes.methodX1(test1);
// compiles
takes.methodX2(test1);
TestClass const ^ constHandle = test1;
takes.methodX3(constHandle);
return 0;
}