2016-07-06 2 views
2

Я работаю над проектом xcode8 swift 3.0. Он должен получить доступ к библиотеке C++, для которой потребуется функция обратного вызова для асинхронной отправки данных обратно быстрому абоненту. Обратный вызов работает, если он вызван прямо внутри функции RegisterCallBack. Однако, если он выходит из строя, если вызывает его вне функции RegisterCallBack.вызов быстрой функции из C++ с EXC_BAD_ACCESS (...)

в моем быстром файле 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 
} 
... 
} 

// log print: Указатель функции RegisterCallBack 0x1300cd30

run_swiftfunc

указатель функции 0x1300cd30

тест FUNC в вид contriller

run_swiftfunc

указатель функции 0x1300cd30

(lldb) ----> EXC_BAD_ACCESS (код = ..

Адрес swiftfunc такой же, как и 0x1300 CD30. Как сохранить блок swiftfunc?

+0

Возможные дубликатом [Взаимодействуя с классами C++ от Swift] (HTTP: // StackOverflow. com/questions/35229149/interactiveing-with-c-classes-from-swift) – CodeBender

ответ

0

Заблокировать __strong в файле cpp.

// 
// 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 Runtime:

#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 
+0

добавить __strong и добавить закрытие: @convention (block)() -> Void = self.testfunc, все еще не работает. –

+0

пытается использовать Objective-C runtime, но «typeof» не был объявлен. –

+0

Обновлено. Я удалил 'typeof'. – Brandon

1

я узнал, что блок только стек, поэтому работает только в рамках этой функции. В итоге я использую Block_copy, чтобы избежать проблемы. Теперь я могу использовать асинхронную функцию обратного вызова для вызова быстрых функций в C++

// в моем файле 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(); 
    } 
... 
} 
Смежные вопросы