如何从另一个线程将(Rust)Actix-Web 服务器作为库启动

问题描述 投票:0回答:1

我想从 C++ 控制台应用程序启动简单的 actix-web 服务器作为概念证明。 这是我在 Rust 代码中的尝试:

lib.rs

use std::{io};

use actix_web::{get, middleware::Logger, App, HttpServer, Responder};
use actix_web_lab::{respond::Html};

#[no_mangle]
pub extern "C" fn API_Start_Server() {
    println!("Rust about to launch server.");
    actix_web::rt::spawn(async move {
        // Thread will be consumed until server is closed.
        let _ = start_server();
    });
    println!("Server has been launched, returning.");
}

#[actix_web::main]
async fn start_server() -> io::Result<()> {
    HttpServer::new(move || {
        App::new()
            .service(index)
            .wrap(Logger::default())
    })
    .bind(("127.0.0.1", 8080))?
    .workers(2)
    .run()
    .await
}

#[get("/")]
async fn index() -> impl Responder {
    Html(include_str!("../../Client-Side/index.html").to_string())
}

但显然我做错了什么,因为当我从我的 C++ 代码中调用

API_Start_Server
时:

服务器启动器.cpp

#include <iostream>
#include <windows.h> // Windows API header

// Function signature for initializing and starting the Actix server
typedef void (*StartServerFn)();

int main()
{
    std::wstring wsRelativePath = L"..\\..\\..\\..\\..\..\\..\\target\\release\\actix_server_library.dll";

    // Load the Rust shared library
    HINSTANCE handle = LoadLibrary(wsRelativePath.c_str());

    if (!handle) {
        std::cerr << "Error loading shared library: " << GetLastError() << std::endl;
        return 1;
    }

    // Get a function pointer to the Actix server's entry point
    StartServerFn startServer = (StartServerFn)GetProcAddress(handle, "API_Start_Server");

    if (!startServer) {
        std::cerr << "Error finding function symbol: " << GetLastError() << std::endl;
        FreeLibrary(handle);
        return 1;
    }

    try
    {
        // Call the Rust function to start the Actix server on a new thread
        startServer();
    }
    catch (std::exception ex)
    {
        std::cerr << ex.what();
    }

    // Continue with other tasks in the main thread
    // ...

    // Wait for the Actix server to finish (in a real application, you may use proper synchronization)
    std::cout << "Press Enter to exit..." << std::endl;
    std::cin.get();

    // Clean up and close the shared library
    FreeLibrary(handle);

    return 0;
}

抛出异常,在控制台日志中我可以看到以下消息:

Rust about to launch server.
thread '<unnamed>' panicked at '`spawn_local` called from outside of a `task::LocalSet`', src/Server-Side/Rust/lib.rs:10:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

我知道我可能没有通过生成另一个线程来正确调用服务器创建,并且我可能需要一些状态来存储服务器,但我对 Rust 和 actix 很陌生,找不到任何如何执行此操作的示例。如何从外部线程创建服务器,并在从 C++ 端加载 dll 的情况下使其保持活动状态?

rust interop actix-web
1个回答
0
投票

使用

actix_web::rt::spawn
生成一个 task(您不需要),并且它还需要在现有运行时(您没有)中运行。
#[actix_web::main]
属性已经通过创建自己的运行时将
async
函数转换为非异步函数。因此,要在后台运行它,您只需要
std::thread::spawn
:

#[no_mangle]
pub extern "C" fn API_Start_Server() {
    println!("Rust about to launch server.");
    std::thread::spawn(|| {
        // Thread will be consumed until server is closed.
        let _ = start_server();
    });
    println!("Server has been launched, returning.");
}
© www.soinside.com 2019 - 2024. All rights reserved.