Skip to content

Commit b5f917a

Browse files
committed
Add C get_string from rust example
1 parent bb9f701 commit b5f917a

File tree

3 files changed

+29
-4
lines changed

3 files changed

+29
-4
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
.idea
33
.DS_Store
44
Cargo.lock
5+
*.out

c_call_rust_lib/main.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,20 @@
1+
#include <stdio.h>
12
void p();
23
void hello(const char *str);
4+
char *repeat_hi(int times);
5+
void free_cstr(const char *str);
36

47
/*
5-
static link: gcc main.c ../target/debug/libc_call_rust_lib.a
6-
dynamic link: gcc main.c -Isrc -L ../target/debug/ -lc_call_rust_lib
8+
static link:
9+
gcc main.c ../target/debug/libc_call_rust_lib.a
10+
dynamic link:
11+
gcc main.c -Isrc -L ../target/debug/ -lc_call_rust_lib
712
*/
813
int main() {
914
p();
1015
hello("rust");
16+
char* str = repeat_hi(3);
17+
printf("%s", str);
18+
free_cstr(str);
1119
return 0;
1220
}

c_call_rust_lib/src/lib.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use std::os::raw::{c_char, c_int};
2-
use std::ffi::CStr;
2+
use std::ffi::{CStr, CString};
33

44
#[no_mangle]
55
pub extern "C" fn p() {
@@ -8,11 +8,27 @@ pub extern "C" fn p() {
88

99
#[no_mangle]
1010
pub extern "C" fn hello(name: *const c_char) {
11+
assert!(!name.is_null());
1112
let c_str = unsafe {
1213
CStr::from_ptr(name)
1314
};
1415
println!("hello {:?}", c_str);
1516
}
1617

1718
#[no_mangle]
18-
pub extern "C" fn repeat_hi()
19+
pub extern "C" fn repeat_hi(times: c_int) -> *mut c_char {
20+
let mut res = String::new();
21+
res.extend(std::iter::repeat("hi").take(times as usize));
22+
CString::new(res).unwrap().into_raw()
23+
}
24+
25+
#[no_mangle]
26+
pub extern "C" fn free_cstr(str: *mut c_char) {
27+
// Rust的CStr交给C语言管理后,由于用的是堆内存,C语言并不会自动释放,所以还需要提供一个API去释放堆内存
28+
if str.is_null() {
29+
return;
30+
}
31+
unsafe {
32+
CString::from_raw(str);
33+
};
34+
}

0 commit comments

Comments
 (0)