C ++与Rust的接口-返回CString恐慌 [英] Interfacing C++ with Rust - returning CString panics

查看:398
本文介绍了C ++与Rust的接口-返回CString恐慌的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图从C ++调用用Rust编写的一些函数。到目前为止,我已经相当成功,但是在运行时与 CString 相关的恐慌仍然有一个小问题。

I am trying to call some functions written in Rust from C++. So far I've been quite successful but I still have one little problem with a CString-related panic during runtime.

函数 hello 应该采用输入字符串,将其与其他字符串连接起来并返回乘积。

The function hello is supposed to take an input string, concatenate it with some other string and return the product.

这是我的 fun.rs

use std::ffi::CString;

#[no_mangle]
pub extern "C" fn add(a: i32, b: i32) -> i32 {
    a + b
}

#[no_mangle]
pub extern "C" fn hello(cs: CString) -> CString {
    let slice = cs.to_str().unwrap();
    let mut s = "Hello, ".to_string();
    s = s + slice;

    CString::new(&s[..]).unwrap() // runtime error
    // CString::new(cs).unwrap()  // empty string if no borrow
    // cs                         // works if no borrow, but this is not what I meant
}

这是 main.cpp

#include <iostream>
using namespace std;

extern "C" {
  int add(int a, int b);
  const char* hello(const char*x);
}

int main()
{
  int a, b;
  cin >> a >> b;
  cout << add(a,b) << ";" << hello("Pawel") << std::endl;
  return 0;
}

makefile

rust:
        rustc --crate-type=staticlib -C panic=abort fun.rs

cpp:
        g++ -c main.cpp

link:
        g++ main.o -L . libfun.a -o main -lpthread -ldl -lgcc_s -lc -lm -lrt -lutil

命令运行可执行文件:

$ make rust
$ make cpp
$ make link
$ ./main
1 2

可执行输出:

1 2
thread '<unnamed>' panicked at 'index 18446744073709551615 out of range for slice of length 0', ../src/libcore/slice.rs:549
note: Run with `RUST_BACKTRACE=1` for a backtrace..

回溯:

stack backtrace:
   1:           0x435d4f - std::sys::backtrace::tracing::imp::write::h46e546df6e4e4fe6
   2:           0x44405b - std::panicking::default_hook::_$u7b$$u7b$closure$u7d$$u7d$::h077deeda8b799591
   3:           0x443c8f - std::panicking::default_hook::heb8b6fd640571a4f
   4:           0x4099fe - std::panicking::rust_panic_with_hook::hd7b83626099d3416
   5:           0x4442a1 - std::panicking::begin_panic::h941ea76fc945d925
   6:           0x40b74a - std::panicking::begin_panic_fmt::h30280d4dd3f149f5
   7:           0x44423e - rust_begin_unwind
   8:           0x451d8f - core::panicking::panic_fmt::h2d3cc8234dde51b4
   9:           0x452073 - core::slice::slice_index_len_fail::ha4faf37254d75f20
  10:           0x40e903 - std::ffi::c_str::CStr::to_str::ha9642252376bab15
  11:           0x4048e0 - hello
  12:           0x40476f - main
  13:     0x7f78ff688f44 - __libc_start_main
  14:           0x404678 - <unknown>
  15:                0x0 - <unknown>

为什么Rust会惊慌?

Any ideas why Rust is panicking?

推荐答案

Rust的 CString 与C的 const char * 不兼容。这是标准库中 CString 的定义:

Rust's CString is not compatible with C's const char *. Here's the definition of CString from the standard library:

pub struct CString {
    inner: Box<[u8]>,
}

Box< [u8]> 类型是 fat指针,即包含指向切片项和切片长度的指针的元组作为使用

This Box<[u8]> type is a fat pointer, i.e. a tuple that contains a pointer to the slice's items and the length of the slice as a usize.

您应该做的是使Rust函数采用 * const c_char 参数,然后调用 CStr :: from_ptr ,以该指针作为获取 CStr 值。

What you should do instead is make your Rust function take a *const c_char argument and then call CStr::from_ptr with that pointer as the argument to obtain a CStr value.

对于返回值,存在一些问题:您的函数分配一个新字符串,然后返回指向该字符串的指针。同样,您应该返回 * const c_char ,可以通过调用 CString :: into_raw 在连接的 CString 值。但是为了避免内存泄漏,您还必须提供一个Rust函数,该函数将取回 hello 返回的指针并调用 CString :: from_raw 上,它将重新创建 CString 。然后, CString 的析构函数将运行,释放内存。

As for the return value, there's a bit of a problem: your function allocates a new string and then returns a pointer to it. Again, you should return a *const c_char, which you can do by calling CString::into_raw on your concatenated CString value. But to avoid memory leaks, you must also provide a Rust function that will take back a pointer returned by hello and call CString::from_raw on it, which will recreate the CString. The CString's destructor will then run, freeing the memory.

这篇关于C ++与Rust的接口-返回CString恐慌的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆