【rust项目】c与rust相互调用及目录间文件相互引用

涉及问题

1)rust需要调用c生成的库(静态库和动态库)

2)c生成库时需要调用rust函数

3)同级目录下文件调用

4)主体代码调用builtins目录文件

5)builtins目录调用主体代码

6)builtins目录下文件生成库

7)生成多个bin文件

8)主体代码和builtins目录下文件重名(把其中一个文件名称换掉)

demo目录结构

请添加图片描述

lib目录:c静态库,

src目录: rust语言程序

variable目录:c动态库,

1 c生成库文件

1.1 生成静态库

使用命令:gcc -c xxx.c -o xxx.o

		ar -r libxxx.a xxx.o

1.2 生成动态库

使用命令: gcc -fPIC -shared xxx.c -o libxxx.so

在生成c动态库时需要调用rust中实现的函数,只需要在c文件中使用extern引入相应函数和定义,如下所示,aaaaa的实现在rust端。

1)rust代码

/* 供给c端代码使用,用于生成libxxx.a */
#[no_mangle]	//不加[no_mangle]在c调用时可能会出现找不到aaaaa的情况
pub fn aaaaa()
{
    println!("this is aaaaaa");
}

2)c代码

#include <stdio.h>

extern void aaaaa(void);

void builtins_variables_print()
{
    aaaaa();
    printf("this is builtins_variables function,");
}

2 c与rust间相互调用

2.1 c调用rust函数

参考1.2小节

2.2 rust调用C静态库

rust调用c静态库时需要再rust项目中添加build.rs文件,该文件的作用是在编译代码的时候可以链接到库,相当于给rustc 添加编译参数。

1)c中代码的实现 ->生成名为r2c的库(libr2c.a)

#include <stdio.h>
#include <string.h>

int add(int i1, int i2) {

    return i1+i2;

}

2)build.rs文件

extern crate dunce;

use std::{env, path::PathBuf};

fn main() {
    let library_name_r = "r2c";
    let root_r = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap());
    let library_dir_r = dunce::canonicalize(root_r.join("lib")).unwrap();
	
    //主要是下面这两句
    println!("cargo:rustc-link-lib=static={}", library_name_r);			//相当链接的库 
    println!("cargo:rustc-link-search=native={}", env::join_paths(&[library_dir_r]).unwrap().to_str().unwrap());		//库路径


}

static:库类型

3)xxx.rs中使用c静态库方式

/* 使用C库 */
#[link(name = "r2c", kind = "static")]		//链接的库
//c库中的函数
extern {
   fn add(i1: c_int, i2: c_int) -> c_int;
   fn replace(s: &mut [u8;3], d: &mut [u8;3]);
   fn add_v2(i1: c_int, i2:c_int, out: &mut c_int);
}
 
/* c库使用实现 */
pub fn add_w(i1: i32, i2: i32) -> i32 {

    unsafe {add(i1 as c_int, i2 as c_int)}		//一定要加unsafe,否则会报错

}

2.3 rust调用c动态库

同样需要build.rs文件。

1)c中代码的实现 ->生成名为builtins_variable的库(libbuiltins_variable.so)

#include <stdio.h>

extern void aaaaa(void);

void builtins_variables_print()
{
    aaaaa();
    printf("this is builtins_variables function,");
}

2)build.rs文件

extern crate dunce;
use std::{env, path::PathBuf};

fn main() {

    let root_v = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap());
    let library_dir_v = dunce::canonicalize(root_v.join("variable")).unwrap();
	
    //库文件路径,与静态链接的区别是没有加库名称
    println!("cargo:rustc-link-search=native={}", env::join_paths(&[library_dir_v]).unwrap().to_str().unwrap());
}

3)xxx.rs中使用c动态库方式

/* 使用c端动态库 */
#[link(name = "builtins_variables")]		//动态库只需要写动态库的名称
extern "C" {
    fn builtins_variables_print();
}

pub unsafe fn b_print()
{
    println!("this is src/b.rs");
    println!("使用c动态库");
    builtins_variables_print();     //实现位置:c动态库
    
}

3 rust项目中不同目录下文件的相互 调用

​ 文件相互引用的时候,需要再在src目录下添加lib.rs文件,lib.rs添加在src目录下时与和src同级目录时使用方式不同。本文选择在src目录下的方式,于src同级的没研究明白。(不清楚不使用lib可不可以)

好像所有文件的引用都可以使用include,当不同文件中有相同函数名称时貌似不能使用。使用inclued宏的时候引用那个文件中的哪些函数是不需要写的。

lib.rs内容

以下3中情况的lib.rs内容相同。

pub mod builtins{	//builtin中的内容添加得到下面
    pub mod ffi_wrapper;
    pub mod a;
    pub mod b;
}

3.1 同级目录

3.1.1 builtins目录下文件相互引用

a.rsb.rs都为builtins目录下文件

1) a.rs内容

pub fn a_print(){    //不加pub应该是引用不到
    println!("this is builtins/a");
}

2) b.rs内容

/* b.rs调用a.rs中函数 */
use crate::builtins::a::{a_print};		//lib.rs存放位置这不同,这个位置的引用方式应该不同

//include!(concat!("a.rs"));  //也可以使用include的方式,之前怎么没发现呢,直到写文档才想起来

pub fn b_print()
{
    a_print();    //使用a.rs
    println!("this is builtins/b");
}
3.1.2 src目录下文件相互引用

src目录下内容相互引用是用include!宏,使用方式为include!(concat!("xxx.rs"));

f.rs引用e.rs文件内容。f.rse.rs同在src目录下

1)e.rs内容

pub fn e_print()
{
    println!("this is e");
}

2)f.rs内容

include!(concat!("e.rs")); 
pub fn f_print()
{   
    println!("this is f");
    e_print();
}

3)main.rs引用同级目录

#![allow(
    mutable_transmutes,
    non_camel_case_types,
    non_snake_case,
    non_upper_case_globals,
    unused_assignments,
    unused_mut,
    unused_must_use
)]   //警告

/* 使用src/b.rs */
mod b;
use crate::b::{b_print};		//在builtins目录下的b.rs文件中也有一个b_print的函数,用这种方式可以区分引用的是哪个,下面的include的方式貌似不可以。一般也不会出现这种情况
// include!(concat!("./b.rs"));

fn main() {
    unsafe { b_print() };
}

3.2 子目录引用上层目录

这种情况也是使用include!的形式

buildints\b.rs使用src\f.rs中函数

1)buildints\b.rs内容

/* b.rs调用src/f.rs中函数 */
include!(concat!("../f.rs")); 

pub fn b_print()
{
    f_print();    //使用f.rs
    println!("this is builtins/b");
}

2) src\f.rs内容

include!(concat!("e.rs")); 
pub fn f_print()
{   
    println!("this is f");
    e_print();
}

3.3 上层目录引用子目录

src\c.rs引用builtins\b.rs中函数

1)builtins\b.rs内容

/* b.rs调用a.rs中函数 */
// use crate::builtins::a::{a_print};
include!(concat!("a.rs")); 

/* b.rs调用src/f.rs中函数 */
include!(concat!("../f.rs")); 

pub fn b_print()
{
    a_print();    //使用a.rs
    f_print();    //使用f.rs
    println!("this is builtins/b");
}

2)src\c.rs内容

/* c.rs调用builtins/b.rs中函数 下面两种方式都可以*/
// pub use builtins::builtins::b::{b_print}; 
include!(concat!("./builtins/b.rs")); 

pub fn c_print()
{
    b_print();
    println!("this is c");
}

4 creat生成bin和lib

一个creat只可以生成一个lib文件(lib的类型可以是多种);但是可以生成多个bin文件。只需要配置Cargo.toml文件即可。

1)Cargo.toml内容

[package]				# 包信息
name = "r2c"			# 名称
version = "0.1.0"		# 版本
authors = ["yxhl"]		# 作者
edition = "2018"

build = "./build.rs"  	# 编译配置文件

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

# 依赖
[dependencies]	
libc = "*"

# 编译依赖
[build_dependencies]
dunce = "1.0.0" 

# 生成的库信息
[lib]
name = "builtins"					# 库名称
path = "src/lib.rs"					# 生成库的文件
crate-type = ["staticlib","rlib"]	# 生成的库类型,静态库和rust库

# 生成的二进制,可以是多个,main函数自动会生成一个和package同名的bin文件
[[bin]]
name = "utshell"		# 二进制名称
path = "src/a.rs"		# 生成二进制使用的文件

bin文件也可以写在bin目录下吧

  • 21
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RustC语言相互调用过程,指针是一个重要的概念。Rust是一种较新的系统级编程语言,具备了内存安全和高性能的特性,而C语言作为一种传统的系统性语言,其指针的概念在Rust也可以得到支持和使用。 在Rust,可以使用`ffi`(Foreign Function Interface)功能来与C语言进行交互。这使得Rust可以使用C语言的函数和数据结构。在C语言,指针用于引用内存的数据地址。而在Rust,由于其内存管理的安全性,需要使用特定的语法和关键字来操作和使用指针。 在Rust,使用`&`和`*`两个符号来进行指针操作。使用`&`可以创建一个指向某个值的引用,并且由Rust自动处理内存的管理。而使用`*`可以通过解引用操作符来取得指针所指向的值。 当RustC语言进行相互调用时,指针在两者之的传递非常重要。在Rust调用C函数时,需要通过`*const`或`*mut`等类型来声明指针。同时,通过`unsafe`关键字来告诉编译器这是一个不安全的操作,需要手动去管理指针所指向的内存。 在C调用Rust函数时,需要考虑Rust的所有权(ownership)机制。Rust的所有权机制确保了内存的安全和有效的内存管理。当C语言调用Rust函数时,需要传递指针给Rust函数,并在合适的时候将指针的所有权返回给C语言。 总之,RustC语言相互调用,指针是连接两者的重要桥梁。在Rust,通过特定的语法和关键字进行指针操作,并通过`ffi`功能与C语言进行交互。指针的有效管理是确保内存安全的关键所在。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值