Call variadic Objective-C function from Swift - objective-c

I have summarized the steps of the problem, I have a C function defined in Objective-C:
ObjC.h
#import <Foundation/Foundation.h>
void cuslog(NSString *format, ...);
#interface ObjC : NSObject
#end
ObjC.m
#import "ObjC.h"
#implementation ObjC
#end
void cuslog(NSString *format, ...)
{
// Implementation
}
I exposed it in Bridging-Header.h:
#import "ObjC.h"
// Also tried to put this line in bridging header
void cuslog(NSString *format, ...);
In Swift I intend to call the function like this:
cuslog("Some log")
But the error says:
"Use of unresolved identifier 'cuslog'"
What is the correct way to call the function in Swift?

According to the Swift devs, C variadic functions are not compatible with Swift variadics, so you won't be able to call your function directly.
The only workaround at this time is to write a non-variadic wrapper in C or Obj-C, and call that from Swift.

Related

Swift cannot pass class conforming to protocol as function parameter to a function residing in Objective-C file

Hi I'm new to Swift but experienced with Objective-C.
I have a project that uses both Swift and Objective-C files (bridging and all).
Say I have a protocol called "fooProtocol" and a class "foo" that implements it. I am trying to pass an object of type "fooProtocol" from the Swift file as a parameter to the function inside the Objective-C file.
here is the Objective-C function inside class "tester":
-(void)setWithFoo:(id<fooProtocol>*)_foo{
}
here is the Swift code:
var myObject:fooProtocol = foo.init()
var objcObject:tester = tester.init()
objcObject.setWithFoo(_foo: myObject)
It first says "Cannot convert value of type "fooProtocol" to expected argument type "AutoreleasingUnsafeMutablePointer (obviously because it needs to be passed by reference, so...)
I then tried casting the parameter to this:
tester.setWithFoo(_foo: AutoreleasingUnsafeMutablePointer<fooProtocol>(myObject))
Now the error reads: "Cannot invoke initializer for type 'AutoreleasingUnsafeMutablePointer with an argument list of type '(fooProtocol)'
I have tried many more permutations and variations but I simply cannot stop the compiler error. For such a simple procedure as passing a polymorphic variable to a function in Objective-C file that expects that protocol id, Swift has made it a nightmare.
...Any help would be appreciated, thanks!
=== EDIT ===
Here are the declarations for the classes, now starting properly with caps
In the "FooProtocol.h" file:
#protocol FooProtocol
#end
In the "Foo.h" file:
#import <Foundation/Foundation.h>
#import "FooProtocol.h"
#interface Foo : NSObject <FooProtocol>
#end
In the "Foo.m":
#import "Foo.h"
#implementation Foo
#end
The "FooProtocol.h" file:
#import <Foundation/Foundation.h>
#protocol FooProtocol
#end
The "Tester.h" file:
#import <Foundation/Foundation.h>
#import "FooProtocol.h"
#interface Tester : NSObject
-(void)setWithFoo:(id<FooProtocol>*)_foo;
#end
The "Tester.m" file:
#import "Tester.h"
#implementation Tester
-(void)setWithFoo:(id<FooProtocol>*)_foo{
//do something with _foo
}
#end
And again the Swift code that can't compile:
var myObject:FooProtocol = Foo.init()
var objcObject:Tester = Tester.init()
objcObject.setWithFoo(AutoreleasingUnsafeMutablePointer<FooProtocol>(myObject))
You probably don't mean to say this:
-(void)setWithFoo:(id<FooProtocol>*)_foo;
It is very unusual to see an id* in Objective-C. In fact, it's so unusual that in all my years of programming Cocoa, I have never seen one.
You probably mean this:
-(void)setWithFoo:(id<FooProtocol>)_foo;
And then you will be able to say, on the Swift side:
objcObject.setWithFoo(myObject)

Calling objective C from Swift error = Class does not have a member called

I'm trying to call an Objective-C class from Swift. So I enabled the bridging header option
Created the following files:
MyTest.h:
#import <Foundation/Foundation.h>
#interface MyTest : NSObject
+(void)sayHello;
#end
MyTest.m
#implementation MyTest
+(void)sayHello {
NSLog(#"Hello");
}
#end
at MyProject-Bridging-Header.hadded:
#import "MyTest.h"
Then when in a Swift file I call:
let test = MyTest()
test.sayHello()
The compiler complains in the second line:
MyTest does not have a member named 'sayHello'
What am I doing wrong?
Note: I have no experience with Objective-C.
You created a class method, not an instance method.
Try instead:
MyTest.sayHello()
Or change the objective-c function to:
-(void)sayHello
Note the - instead of the +. See this question and answers for further reading.

Using Methods Without Declaring them in the header

Recently I used an opaque pointer type in my code. I did this because I wanted to use c++ code in my obj c project without having to change every single file to .mm.
The way I use the c++ code is that I have a opaque pointer to my c++ code as a member of a .mm file. All the c++ is hidden in the implementation file.
In this class that contains my c++ I have a need to import an existing class "MyClass". I can import it fine in the implementation class but if I try to import it in the header I get c++ errors saying " ISO C++ forbids declaration of 'CARingBufferCPPWrapper' with no type".
I "can" just write the method in the .mm file and omit it from the header but I get a warning say that my .mm file may not respond to the method.
A lot of this is quite new to be so my terminology may be a little off. Let me know if I can clarify my question in any way.
TLDR: How can Class X Safely call a method in Class Y without the method being declared in Class Y header?
//My Header
#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioToolbox.h>
#define kBufferLength 5120
//#define "Myclass.h"
typedef struct ringbufferobj * RingBufferOBJ;
RingBufferOBJ newRingBufferOBJ();
#interface CARingBufferCPPWrapper : NSObject {
RingBufferOBJ ringbuffer;
NSThread *producerthread;
int duration;
}
#property (nonatomic, retain) NSThread *producerthread;
#property(nonatomic)int duration;
//-(void)myclassfunction(MyClass *)classref
#end
//My Implementation .mm
#import "CARingBufferCPPWrapper.h"
#import "CARingBuffer.h"
#import <AudioToolbox/AudioToolbox.h>
#import "MyClass.h"
struct ringbufferobj
{
CARingBuffer *ringbuffer;
AudioBufferList *inputbuffer;
Float64 firstInputSampleTime;
Float64 firstOutputSampleTime;
Float64 inToOutSampleTimeOffset;
BOOL producerthreadisrunning;
};
RingBufferOBJ newRingBufferOBJ(){
RingBufferOBJ ringbuffer=(RingBufferOBJ)malloc(sizeof(struct ringbufferobj));
return ringbuffer;
}
#implementation CARingBufferCPPWrapper
#synthesize producerthread;
#synthesize duration;
-(void)myclassfunction(MyClass *)classref
{
}
#end
I'm not quite sure what your question is as I couldn't find anything that actually asks anything. (I even Cmd+F'd for "?"). I'm assuming however, that you're asking what you can do to get rid of that warning?
-If a method is declared above the method it is called it, there should be no warning. ( methods are compiled in order). To get rid of such a warning, you'd have to forward declare the method signature. (This is conventionally in the header, but I don't think there's anything stopping you just doing it at the top of your .m)
-(void) methodA {
..do something
[self methodB]; //Warning here because the compiler has not yet seen methodB
}
-(void) method B {
..[self methodA]; //No warning, compiler knows what methodA is at this point.
}

How can I call a C function from Objective-C

I'm trying to figure out how to call a c function from an obj-c file. I've seen some good examples of how to do the opposite.
In the example below I have an objective c file. It contains a c function named setup.
I want to be able to create an instance of my obj-c file in the regular way and then call the setup function.
Header
#import <Foundation/Foundation.h>
void setup(int,float);
#interface Test : NSObject {
}
#end
Source
#import "Test.h"
#include <stdio.h>
#include <stdlib.h>
void setup(int val1,float val2)
{
//do something with values
}
#implementation Test
#end
View did load
Test *test =[Test alloc]init]
//this does not work
test.setup(6,1.4);
Just call setup(). As declared, is in no way tied to an object - it's just a regular C function.

how to return C++ pointer in objective-C++

I have the following objective-C++ header with the simple method to return this pointer.
#interface MyObj
{
MyCPPObj * cpp;
}
-(MyCPPObj *) getObj;
I have created the simple method
#implementation MyObj
-(MyCPPObj *) getObj
{
return cpp;
}
Everything seems to work until I actually try to use the object in another file
newObj = [createdMyObj getObj];
It complains: error: cannot convert 'objc_object*' to 'MyCPPObje *' in initialization.
It seems that the method is return an objective-c object, but I specifically requested a C++ pointer.
MyCPPObj is an honest C++ class:
class MyCPPObj
{
public:
int x;
}
How can I fix that?
On my 10.6.3 machine, the following combination worked without any problem: aho.h
#import <Foundation/Foundation.h>
class MyCPPObj{
};
#interface MyObj:NSObject
{
MyCPPObj * cpp;
}
-(MyCPPObj *) getObj;
#end
and aho.mm
#import <Foundation/Foundation.h>
#import "aho.h"
void foo(){
MyObj*objcObj=[[MyObj alloc] init];
MyCPPObj*cppObj=[objcObj getObj];
}
Two pitfalls you might have fallen into:
Unlike C++, a class in Objective-C which doesn't inherit from NSObject won't work. (Well, you can make it work, but you don't want that usually.) Note the line #interface MyObj:NSObject.
To use NSObject, do #import <Foundation/Foundation.h>
Don't forget to use the extension .mm for Objective-C++ files.
Most likely you have forgotten to #import the header file with the #interface into the .mm file where you use getObj.
The error states what happens, and JeremyP is right on the money. When you forget to include a header file with the prototypes of the selectors, the compiler assumes the selector returns an object of type id. Well id is a typedef to objc_object*, which is incompatible with your C++ class. To fix the error, you simply need to include your header file in the file where you called getObj.