如何使用从 Swift 代码调用的线程在 C++ 上创建异步调用函数?

Posted

技术标签:

【中文标题】如何使用从 Swift 代码调用的线程在 C++ 上创建异步调用函数?【英文标题】:How to make a async call function on C++ using threads called from Swift code? 【发布时间】:2019-02-20 16:17:17 【问题描述】:

我正在尝试使用 C++ 进行简单的异步调用。我的问题是我的代码执行同步并使用块函数。我想要一个异步且非阻塞的程序。

第一次,我用 C++ 写了一点代码来测试我的逻辑,所以程序在线程之前结束,所以这不起作用。但是在ios项目的Xcode上我可以不用main函数写C++代码,在Final Objective部分有详细说明。

#include <iostream>
#include <string>
#include <chrono>
#include <future>

using namespace std;

void call_from_async()

    std::this_thread::sleep_for(std::chrono::seconds(5));
    cout << "Async call" << endl;


int main(void) 
    printf("1\n");
    std::future<void> fut = std::async(std::launch::async, call_from_async);
    // std::async(std::launch::async,call_from_async);
    printf("2\n");
    return 0;

输出:

1
2

期望的输出:

1
2
Async Call

最终目标

我有一个 Swift 项目,我必须调用 C++ 异步函数。为此,我想从 Swift 调用一个 C++ 函数并传递一个指针函数以在进程完成时获取回调。为了开始这个项目,我只写了一点代码来调用 C++ 函数,并将工作留在后台,当工作完成后通过回调函数返回 Swift。在我想测试异步函数之前,我还没有创建回调函数。

Swift 代码

// ViewController.swift

import UIKit

class ViewController: UIViewController 

    override func viewDidLoad() 
        super.viewDidLoad()
        printFromCPP()
        print("1")
        call_async_function()
        print("2")
    


// Ex_iOS_CPP_Swift-Bridging-Header.h

#ifdef __cplusplus
extern "C" 
#endif

#include "Foo.h"

#ifdef __cplusplus

#endif

// Foo.h

#ifndef Foo_h
#define Foo_h

void printFromCPP();
void call_async_function();

#endif /* Foo_h */

// Foo.cpp

#include <iostream>
#include <future>
#include <unistd.h>
#include "Ex_iOS_CPP_Swift-Bridging-Header.h"

using namespace std;

void called_from_async() 
    sleep(3);
    cout << "Async call" << endl;


void call_async_function() 
//    std::future<void> fut = std::async(std::launch::async, called_from_async);
    std::future<void> result( std::async(called_from_async));


void printFromCPP() 
    cout << "Hello World from CPP" << endl;

输出

Hello World from CPP
1
Async call
2

期望的输出

Hello World from CPP
1
2
Async call

【问题讨论】:

你需要存储async返回的std::future否则会阻塞直到任务完成 你能帮我写出正确的形式这一行std::async(std::launch::async,call_from_async); ? 应该没问题。您的代码可以正确编译here。任何可以提供&lt;future&gt; 的编译器都应该支持std::async,因为它们是在同一个c++ 版本中引入的。所以我无法解释您遇到的错误,也无法重现它。 我使用的是macos,这显然行不通。当我提出这个问题时,我的代码编译正确 @FrançoisAndrieux 我尝试使用std::future 但没有解决,代码保持同步和阻塞。 【参考方案1】:

这就是使用Scapix Language Bridge 的方法:

C++

#include <thread>
#include <iostream>
#include <scapix/bridge/object.h>

class cpp_class : public scapix::bridge::object<cpp_class>

public:

    void async(std::function<void(std::string)> callback)
    
        std::thread([=]
            std::this_thread::sleep_for(std::chrono::seconds(3));
            std::cout << "cpp_class::async\n";
            callback("cpp_class::async -> success");
        ).detach();
    
;

斯威夫特

import UIKit

class ViewController: UIViewController 

    override func viewDidLoad() 
        super.viewDidLoad()

        let cpp = CppClass()

        cpp.async() 
            (result: String) in
            print("Swift: " + result)
        
    

打印出来:

cpp_class::async
Swift: cpp_class::async -> success

【讨论】:

以上是关于如何使用从 Swift 代码调用的线程在 C++ 上创建异步调用函数?的主要内容,如果未能解决你的问题,请参考以下文章

从 Swift 将文件作为参数传递给 C++ 方法

c++ 如何在构造函数中启动一个线程,从命名管道读取数据?

JNI 通过多线程从 C++ 调用 Java

boost::python - 如何从 C++ 在自己的线程中调用 python 函数?

C++如何运行多个可以随时调用的后台函数线程?

如何使用 p/invoke 终止从 C# 调用的 C++ 函数