I want to translate this code from Swift to Objective C:
typealias Completion = ([Media]?) -> Void
I have look over Stack Overflow posts, but I don't see the answer for this.
typedef void (^CompletionBlock) ( NSArray<Medial*>* _Nullable array);
typedef void (^CompletionBlock) (NSArray* array);
Related
I'm using C++Builder 10.4.2 and having a problem with qsort. I rarely use qsort so I might be making a clumsy mistake. Array 'buffer' is a 2D 'char' array with more than 26,000 rows of single words.
This is the call:
qsort((void *)buffer,wordcount,sizeof(buffer[1]),sort_function);
This is the compare function:
int TForm::sort_function(const void *a, const void *b)
{
return( strcmp((char *)a,(char *)b) );
}
This is the error message. Notice that it's complaining about sort_function for 4th argument:
search.h(46): candidate function not viable: no known conversion from 'int (__closure *)(const void *, const void *)' to 'int (*)(const void *, const void *) __attribute__((cdecl))'
What is 'int (__closure *)'? Is there a way to fix my compare function?
__closure is a Borland compiler extension for obtaining a pointer to a non-static class method, without regard to the type of class being used. This is most commonly used in VCL/FMX components, which allow you to assign event handlers from any class you want, which is not something that standard C++ typically allows you to do.
qsort() expects a C-style function pointer in the 4th parameter. You can't get such a pointer to a non-static class method.
To solve this, you need to use either:
a standalone function
a static class method
a non-capturing C++ lambda (C++11 or higher only)
Since your sort_function() does not need access to your TForm object, declaring sort_function() as static would be the simplest fix:
// .h
class TForm
{
...
private:
static int sort_function(const void *a, const void *b);
void doSomething();
...
};
// .cpp
int TForm::sort_function(const void *a, const void *b)
{
return strcmp((const char *)a, (const char *)b);
}
void TForm::doSomething()
{
...
qsort(buffer, wordcount, sizeof(buffer[1]), sort_function);
...
}
However, it really should be a standalone function instead since it really has no relation to your TForm class at all:
// .cpp
static int sort_function(const void *a, const void *b)
{
return strcmp((const char *)a, (const char *)b);
}
void TForm::doSomething()
{
...
qsort(buffer, wordcount, sizeof(buffer[1]), sort_function);
...
}
I am using SNMP++ library in my project and everything works fine. However, there is a method where I need to get callback in my .mm file. Now when I am creating a block and passing it to that function as parameter, it throws an error "No matching member function for call to 'get_bulk'". Here is the piece of code:
void(^callbackFunc)(int,Snmp*,Pdu&,SnmpTarget&,void*);
callbackFunc = ^(int i,Snmp* s,Pdu& p,SnmpTarget& t,void* v) {
};
snmp.get_bulk(pdu, *target, l_repeaters, l_repetitions,callbackFunc);
Also, here is the function signature for "get_bulk" function:
int Snmp::get_bulk(Pdu &pdu, // pdu to use
const SnmpTarget &target, // destination target
const int non_repeaters, // number of non repeaters
const int max_reps, // maximum number of repetitions
const snmp_callback callback,// callback to use
const void * callback_data) // callback data
{
pdu.set_type( sNMP_PDU_GETBULK_ASYNC);
return snmp_engine( pdu, non_repeaters, max_reps, target,
callback, callback_data);
}
What should I pass in 'callback' type?This is the typedef for SNMP_callback:
typedef void (*snmp_callback)(int reason, Snmp *session,
Pdu &pdu, SnmpTarget &target, void *data);
I am stuck on this for the past 4-5 hours now and I can't figure out how to resolve this.
Apple's blocks are not convertible to function pointers, as they also contain data (captured variables, etc.) and a reference counting mechanism. You will need to pass a free function, static C++ class member function, or a C++ non-capturing lambda as the callback.
The lambda is the closest syntactically to a block; only non-capturing lambdas are convertible to a function pointer, however, so you will need to do the capturing "by hand" by passing a pointer to a context struct or similar through the void* callback_data argument which presumably is passed through to the callback as void* data.
The lambda will look something like this:
snmp_callback callback =
[](int reason, Snmp *session, Pdu &pdu, SnmpTarget &target, void *data)
{
// context_struct_type* context = static_cast<context_struct_type*>(data);
};
I have a question about syntax of function parameter in Swift.
I want to get message through C based callback function from library, so I make a function with Objective-C as below:
void foo(char *arg) {
NSLog(#"%s", log);
}
Then, I register foo to MainController interface with Objective-C like this.
typedef void (*CB)(char *);
void addFoo(CB func);
...
addFoo(&foo);
The above code is a simplified representation, but it print log for library well.
Now, I have to change the language from Objective-C to Swift. Most of the source code has changed, but for the above function, the log is not output normally.
How can I change?
Please help.
I tried to convert directly. This is code.
typealias CB = (String) -> Void
func addCB(cd: CB) {
// ...
}
func foo(pa: String) {
// ...
}
var fooFuc: CB = foo(pa: )
addCB(cd: fooFuc)
I want to define a block similar to NSArray enumerateObjects:usingBlock
my block is as follows
typedef void (^MyBlock)(BOOL *);
and i want to invoke it in some method, so that the method would give me the BOOL value to stop
how do I continue from here ?
EDIT:
I want to do the following
BOOL replaceSomething;
[self someMethod:MyBlock(&replaceSomething)] <== this syntax is not correct
if(replaceSomething){
do something
}
-(void)someMethod:^void(BOOL *stop){
*stop = YES;
}
Here's a handy and an easy to remember site when dealing with blocks:
http://fuckingblocksyntax.com
What you're looking for exactly is the last part (using typedef):
typedef void (^ MyBlock)(id, BOOL);
MyBlock myBlock = ^(id myId, BOOL myBool) {...};
P.S. Note that BOOL is not an object, but a primitive type.
I am playing with Swift and noticed that Swift does not allow to create CFFunctionPointers. It can only pass around and reference existing ones.
As for example CoreAudio requires CFunctionPointer to certain callbacks therefore I cannot use pure Swift.
So I need to use some Objective-C trampoline or wrapper here that takes a Swift Closure as a parameter as well as the original callback prototype and then can be assigned to be the callback, but the actually action happens in Swift and not Objective-C.
How do I do this?
Some example code for such a wrapper would help me to understand how I can use Swift code from objective C for such purposes in a flexible way to work around Swift not being able to create CFunctionPointers.
Yes, I know I can just write stuff when needed in Objective-C. I want to do it in pure Swift as a learning exercise porting one of my apps to Swift (uses a lot of CoreAudio/CoreVideo framework).
I needed to define this callback:
typedef void (*MIDIReadProc) ( const MIDIPacketList *pktlist, void *readProcRefCon, void *srcConnRefCon );
and I wanted to use Objective-C as least as possible.
This was my approach:
MIDIReadProcCallback.h
#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioToolbox.h>
typedef void (^OnCallback)(const MIDIPacketList *packetList);
#interface MIDIReadProcCallback : NSObject
+ (void (*)(const MIDIPacketList *pktlist, void *readProcRefCon, void *srcConnRefCon))midiReadProc;
+ (void)setOnCallback:(OnCallback)onCallback;
#end
MIDIReadProcCallback.m
#import "MIDIReadProcCallback.h"
static OnCallback _onCallback = nil;
static void readProcCallback(const MIDIPacketList *pktlist, void *refCon, void *connRefCon) {
if (_onCallback) {
_onCallback(pktlist);
}
}
#implementation MIDIReadProcCallback
+ (void (*)(const MIDIPacketList *pktlist, void *readProcRefCon, void *srcConnRefCon))midiReadProc {
return readProcCallback;
}
+ (void)setOnCallback:(OnCallback)onCallback {
_onCallback = onCallback;
}
#end
Then you can register MIDIReadProcCallback.midiReadProc as callback and set handler MIDIReadProcCallback.setOnCallback({ (packetList: MIDIPacketList) in ... })
Well, you can create a function pointer.
var ump = UnsafeMutablePointer<((UnsafePointer<MIDIPacketList>, UnsafeMutablePointer<Void>, UnsafeMutablePointer<Void> ) -> Void)>.alloc(1)
ump.initialize(MyMIDIReadProc)
let cp = COpaquePointer(ump)
let fp = CFunctionPointer<((UnsafePointer<MIDIPacketList>, UnsafeMutablePointer<Void>, UnsafeMutablePointer<Void> ) -> Void)>(cp)
status = MIDIDestinationCreate(midiClient,
name,
fp,
etc.
It doesn't work though with Core MIDI.
thread #7: tid = 0x713b7, 0x7a1541f0, stop reason = EXC_BAD_ACCESS (code=2, address=0x7a1541f0)
frame #0: 0x7a1541f0
frame #1: 0x00159295 CoreMIDI`LocalMIDIReceiverList::HandleMIDIIn(void*, OpaqueMIDIEndpoint*, void*, MIDIPacketList const*) + 117
BTW., you cannot have a bridging header if your MIDI code is in a framework you're writing.