调用Rust DLL函数从C包装器中生成新线程,然后将主线程返回给C。

huangapple go评论59阅读模式
英文:

Call Rust DLL function to spawn new thread from C wrapper and return the main thread back to C

问题

C代码如下:

#include "main.h"
#include <stdio.h>
#include "addition.h"
#include <time.h>
#include <unistd.h>

extern void spawn_thread_and_get_back(); // Rust函数:
extern void keep_calling_rust_fn(); // Rust函数:

int main()
{
    spawn_thread_and_get_back(); // 这应该在Rust中生成一个带有无限循环的线程

    int sleep_seconds = 7;

    while(1){
        printf("调用Rust函数");

        keep_calling_rust_fn(); // 调用Rust函数
    }
}

以下是Rust库代码:

async fn counter() {
    loop {
        println!("Tokio每2秒调用我一次");
        // 休眠1秒
        sleep(Duration::from_secs(2)).await;
    }
}

#[tokio::main]
async fn runForever() {
    let counterTask = tokio::spawn(
        counter()
    );
    tokio::try_join!(counterTask);
}

use std::thread;

#[no_mangle]
pub unsafe extern "C" fn spawn_thread_and_get_back() {
    let handle = thread::spawn(move || {
        // 这里进行一些工作
        println!("尝试为Tokio运行时创建新线程");
        runForever();
    });
    handle.join().unwrap();
}

#[no_mangle]
pub unsafe extern "C" fn keep_calling_rust_fn() {
    println!("C包装每7秒调用我一次");
    someRandomPrintTask();
}

async fn printTask(task_number: u32) {
    println!("打印任务 {} -", task_number);
}

async fn someRandomPrintTask() {
    let printTask = tokio::spawn(
        printTask(10)
    );
    tokio::try_join!(printTask);
}

我注意到你的代码中有一些错误,我进行了修正。希望这可以帮助你解决问题。

英文:

I have a use case where C wrapper is loading the Rust DLL. Both C and Rust have infinate loop.

C code

#include &quot;main.h&quot;
#include &lt;stdio.h&gt;
#include &quot;addition.h&quot;
#include &lt;time.h&gt;
#include &lt;unistd.h&gt;

extern void spawn_thread_and_get_back(); // Rust function :
extern void keep_calling_rust_fn(); // Rust function :

int main()
{
    spawn_thread_and_get_back(); // This should spawn thread with infinite loop in rust

    int sleep_seconds = 7;
    
    
    while(1){
      
        printf(&quot;Calling rust function);

        keep_calling_rust_fn(); // Call rust function
    }
}

and here is the rust lib code


async fn counter() {
    loop {
        println!(&quot;I am getting called by Tokio every 2 seconds&quot;);
        // Sleep for 1 second
        sleep(Duration::from_secs(2)).await;
    }
}

#[tokio::main]
async fn runForever() {
    let counterTask = tokio::spawn(
        counter()
    );
    tokio::try_join!(counterTask);

}

use std::thread;

#[no_mangle]
pub unsafe extern &quot;C&quot; fn spawn_thread_and_get_back() {
    let handle = thread::spawn(move || {
        // some work here
        println!(&quot;Trying to create new thread for Tokio runtime&quot;);
        runForever();

    });
    handle.join();
}

#[no_mangle]
pub unsafe extern &quot;C&quot; fn keep_calling_rust_fn() {
    println!(&quot;I am getting called by C wrapper every 7 second&quot;);
    someRandomPrintTask();
}


async fn printTask(task_number: u32) {
    println!(&quot;Print task {} -&quot;, task_number);
}

async fn someRandomPrintTask() {
    let printTask = tokio::spawn(
        printTask(10)
    );
    tokio::try_join!(printTask);
}

The issue I am facing is once I call the spawn_thread_and_get_back() from C and never get the thread back to execute while loop in C

I would like to call the rust DLL from C and spawn seperate thread for rust. And the idea is the caller thread from C will get free once it initializes the rust forever loop thread.

答案1

得分: 0

感谢大家,在上面的评论中讨论后,这是可行的答案。我们只需要更改Rust代码:


async fn counter() {
    loop {
        println!("每隔2秒,Tokio就会调用我一次");
        // 等待1秒
        sleep(Duration::from_secs(2)).await;
    }
}

#[tokio::main]
async fn runForever() {
    let counterTask = tokio::spawn(
        counter()
    );
    tokio::try_join!(counterTask);

}

use std::thread;

#[no_mangle]
pub unsafe extern "C" fn spawn_thread_and_get_back() {
    let handle = thread::spawn(move || {
        // 在这里进行一些操作
        println!("尝试为Tokio运行时创建新线程");
        runForever();

    });
    

   `handle.join();` *** 更新 - 删除此行,因为它会阻塞主线程,等待handle完成 ***

}

#[no_mangle]
pub unsafe extern "C" fn keep_calling_rust_fn() {
    println!("每隔7秒,C包装器就会调用我一次");
    someRandomPrintTask();
}


async fn printTask(task_number: u32) {
    println!("打印任务 {} -", task_number);
}

#[tokio::main]  *** 更新 - 在此处添加了装饰器 *** 
async fn someRandomPrintTask() {
    let printTask = tokio::spawn(
        printTask(10)
    );
    tokio::try_join!(printTask);
}

英文:

Thanks everyone, After discussing in the comments above, here is the working answer. We just need to change Rust code


async fn counter() {
    loop {
        println!(&quot;I am getting called by Tokio every 2 seconds&quot;);
        // Sleep for 1 second
        sleep(Duration::from_secs(2)).await;
    }
}

#[tokio::main]
async fn runForever() {
    let counterTask = tokio::spawn(
        counter()
    );
    tokio::try_join!(counterTask);

}

use std::thread;

#[no_mangle]
pub unsafe extern &quot;C&quot; fn spawn_thread_and_get_back() {
    let handle = thread::spawn(move || {
        // some work here
        println!(&quot;Trying to create new thread for Tokio runtime&quot;);
        runForever();

    });
    

   `handle.join();` *** Update - Removed this as it was blocking the main thread as it was waiting for handle to finish ***

}

#[no_mangle]
pub unsafe extern &quot;C&quot; fn keep_calling_rust_fn() {
    println!(&quot;I am getting called by C wrapper every 7 second&quot;);
    someRandomPrintTask();
}


async fn printTask(task_number: u32) {
    println!(&quot;Print task {} -&quot;, task_number);
}

#[tokio::main]  *** Update - Added the decorater here ***
async fn someRandomPrintTask() {
    let printTask = tokio::spawn(
        printTask(10)
    );
    tokio::try_join!(printTask);
}

huangapple
  • 本文由 发表于 2023年6月1日 20:21:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/76381810.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定