首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何使回调函数指针从C++指向Swift?

如何使回调函数指针从C++指向Swift?
EN

Stack Overflow用户
提问于 2018-12-07 06:18:48
回答 1查看 1.5K关注 0票数 2

有很多教程可以在网络上做到这一点,但没有一个是清晰和客观的,因为我更喜欢展示我的案例。

我正在开发一个iOS应用程序,它使用一个C应用程序接口来连接到一个服务web,它有回调函数,我的任务很简单,我必须在Swift代码上用C代码生成事件。为此,我尝试了一些方法,目前我尝试的方法如下。

方案

我有三个文件:wrapper.cppBridging-Header.hViewController.swift

Briding-Header.h上,我声明了一个函数的指针。

Bridging-Header.h

void callback_t(void(*f)(unsigned char*));

wrapper.cpp上,我编写了连接到web并使用回调函数的代码。因此,这是在断开连接时获取连接状态的回调方法。

wrapper.cpp

void callback_web_disconnected(unsigned char *c) {
    printf("Disconnected %s",c);
    // Here I want invoke a method to Swift code
    callback_t(r); // But this not works
}

这不是编译,错误消息:Use of undeclared identifier 'callback_t'

如果我尝试写:void callback_frame(unsigned char*);,就会出现linker command failed with exit code 1错误。

ViewController.swift

func callback_t(_ f: ((UnsafeMutablePointer<UInt8>?) -> Void)!) {
        print("ARRIVED ON VIEWCONTROLLER!")
        // Here I want get the error code (unsigned char*) passed as parameter
    }

我无法在wrapper.cpp上导入Bridging-Header.h文件,因为这会导致很多冲突。

EN

回答 1

Stack Overflow用户

发布于 2018-12-07 07:34:34

首先,callback_t不是标识符。我在typedef anywhere上看不到它..其次,您需要以某种方式告诉C++回调是您的swift函数。为此,我将其作为参数传递给C++函数,类似于我们在Objective-C和Swift中的方法。否则,您需要将回调存储在某个全局变量中,并让C++访问它。

使用将回调作为参数传递的第一种方法:

首先,在C++头文件(Foo.h)中我做到了(不要删除ifdef内容..当导入到Swift时,编译器使用C链接,但是当编译C++端时,它会被破坏,所以为了使它使用C链接,我们extern "C"代码):

#ifndef Foo_hpp
#define Foo_hpp

#include <stdio.h>

#ifdef __cplusplus
extern "C" {
#endif

    typedef void(*callback_t)(const char *);
    void callback_web_disconnected(callback_t);

#ifdef __cplusplus
} // extern "C"
#endif

#endif /* Foo_hpp */

然后在实现文件(Foo.cpp)中我这样做了:

#include "Foo.h"
#include <thread>
#include <iostream>

#ifdef __cplusplus
extern "C" {
#endif

    void callback_web_disconnected(callback_t callback)
    {
        std::thread t = std::thread([callback] {
            std::this_thread::sleep_for(std::chrono::seconds(2));

            if (callback)
            {
                callback("Hello World");
            }
        });

        t.detach();
    }

#ifdef __cplusplus
} // extern "C"
#endif

然后在ViewController.swift中我做到了:

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        callback_web_disconnected({
            if let ptr = $0 {
                let str = String(cString: ptr)
                print(str)
            }
        })
    }
}

它工作得很好。2秒后,从C++调用Swift代码。

使用第二种方法将回调存储在全局变量中(我不喜欢这种方法,但我们就不谈这个问题了)..

Foo.h中,我做到了:

#ifndef Foo_hpp
#define Foo_hpp

#include <stdio.h>

#ifdef __cplusplus
extern "C" {
#endif

    typedef void(*callback_t)(const char *);
    callback_t globalCallback; //Declare a global variable..

    void callback_web_disconnected();

#ifdef __cplusplus
} // extern "C"
#endif

#endif /* Foo_hpp */

Foo.cpp中,我做到了:

#include "Foo.h"
#include <thread>
#include <iostream>

#ifdef __cplusplus
extern "C" {
#endif

    void callback_web_disconnected()
    {
        std::thread t = std::thread([] {
            std::this_thread::sleep_for(std::chrono::seconds(2));

            if (globalCallback)
            {
                globalCallback("Hello World");
            }
        });

        t.detach();
    }

#ifdef __cplusplus
} // extern "C"
#endif

ViewController.swift中,我做到了:

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        //Set the globalCallback variable to some block or function we want to be called..

        globalCallback = {
            if let ptr = $0 {
                let str = String(cString: ptr)
                print(str)
            }
        }

        //Trigger our test.. I guess your C++ code will be doing this anyway and it'll call the globalCallback.. but for the sake of this example, I've done it here..
        callback_web_disconnected()
    }
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53660553

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档