我正在研究xcode8 swift 3.0项目。它需要访问一个C ++库,它需要一个回调函数来异步地将数据发送回swift调用者。 如果在RegisterCallBack函数内调用它,则回调会起作用。 但是,如果它在RegisterCallBack函数之外调用它会崩溃。
在我的swift文件ViewController.swift
中override func viewDidLoad() {
super.viewDidLoad()
var closure: () -> Void = testfunc;
RegisterCallBack(closure)
run_swiftfunc()
}
func testfunc(){
print("test func in view contriller ");
}
....
//在我的wrapper.h文件中
...
void run_swiftfunc();
void RegisterCallBack(void (^closure)());
...
//在我的wrapper.cpp文件中
extern "C" {
typedef void (^callbackfunc)();
callbackfunc swiftFunc;
void RegisterCallBack(void (^closure)()){
swiftFunc = closure;
printf("function pointer 0x%x \n", (void*) swiftFunc);
swiftFunc(); //works well
}
void run_swiftfunc(){
printf("function pointer 0x%x \n", (void*) swiftFunc);
swiftFunc(); // fail, EXC_BAD_ACCESS
}
...
}
//日志打印: RegisterCallBack函数指针0x1300cd30
run_swiftfunc
函数指针0x1300cd30
在视图控制器中测试func
run_swiftfunc
函数指针0x1300cd30
(lldb)----> EXC_BAD_ACCESS(code = ..
swiftfunc地址相同都是0x1300cd30。如何保存swiftfunc块?
答案 0 :(得分:1)
我发现块只是堆栈,所以只能在函数范围内工作。我最终使用Block_copy来避免这个问题。 现在我可以使用异步回调函数来调用c ++中的swift函数
//在我的wrapper.cpp文件中
#include <Block.h>
extern "C" {
typedef void (^callbackfunc)();
callbackfunc swiftFunc;
void RegisterCallBack(void (^closure)()){
swiftFunc = Block_copy(closure);
printf("function pointer 0x%x \n", (void*) swiftFunc);
swiftFunc(); //works well
}
void run_swiftfunc(){
printf("function pointer 0x%x \n", (void*) swiftFunc);
swiftFunc();
}
...
}
答案 1 :(得分:0)
在cpp文件中创建闭包__strong
。
//
// TestCallbacks.h
// XIO
//
// Created by Brandon T on 2016-07-06.
// Copyright © 2016 XIO. All rights reserved.
//
#ifndef TestCallbacks_h
#define TestCallbacks_h
#ifdef __cplusplus
extern "C" {
#endif
void run_swiftfunc();
void RegisterCallBack(void (^closure)());
#ifdef __cplusplus
}
#endif
#endif /* TestCallbacks_h */
//
// TestCallbacks.mm
// XIO
//
// Created by Brandon T on 2016-07-06.
// Copyright © 2016 XIO. All rights reserved.
//
#include "TestCallbacks.h"
#include <cstdio>
#ifdef __cplusplus
extern "C" {
#endif
typedef void (^callbackfunc)();
__strong callbackfunc swiftFunc;
void RegisterCallBack(void (^closure)()) {
swiftFunc = closure;
printf("function pointer %p \n", (void*) swiftFunc);
swiftFunc();
}
void run_swiftfunc() {
printf("function pointer %p \n", (void*) swiftFunc);
swiftFunc();
swiftFunc = nil;
}
#ifdef __cplusplus
}
#endif
然后我在桥接标题中包含TestCallbacks.h
..
然后我快速地做:
override func viewDidLoad() {
super.viewDidLoad()
let closure: @convention(block) () -> Void = self.testfunc
RegisterCallBack(closure)
run_swiftfunc()
}
func testfunc(){
print("test func in view contriller ");
}
我建议你在使用完毕后,为了以防万一,你的参考文献都是零。
另一个选择是使用Objective-C运行时:
#include "TestCallbacks.h"
#include <cstdio>
#import <objc/runtime.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef void(*callback)(id, SEL)
callback swiftCallback;
void RegisterCallBack(void (^closure)()) {
swiftCallback = (callback)imp_implementationWithBlock(closure);
printf("function pointer %p \n", (void *) swiftCallback);
swiftCallback(nil, nil);
}
void run_swiftfunc() {
printf("function pointer %p \n", (void *) swiftCallback);
swiftCallback(nil, nil);
imp_removeBlock((IMP)swiftCallback);
}
#ifdef __cplusplus
}
#endif