无参函数调用
先写一个rust的lib项目生成动态库
1
2
3
4
5
6
7
8
9
10
11
12
13
| [package]
name = "embed"
version = "0.1.0"
authors = ["k <2589788697@qq.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
[lib]
name = "embed"
crate-type = ["dylib"]
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| use std::thread;
#[no_mangle]
fn process(){
let handles:Vec<_>=(0..=10).map(|_|{
thread::spawn(||{
let mut x = 0;
for _ in 0..5000000{
x += 1
}
x
})
}).collect();
for h in handles{
println!("thread finished with count={}",h.join().map_err(|_|"could not join a thread").unwrap());
}
}
|
- 编译
运行
cargo build --release
得到libembed.dylib
将文件按照如下放置
1
2
3
4
5
6
7
8
9
| ├── Cargo.lock
├── Cargo.toml
├── src
│ ├── a.out
│ ├── interface.h
│ ├── lib.rs
│ ├── libembed.dylib
│ ├── main.c
│ └── test.go
|
1
2
3
4
5
6
| #include "interface.h"
int main(){
process();
return 0;
}
|
- 编译运行C
gcc main.c -L. -lembed && ./a.out
PS:linux下编译gcc main.c -L. -lembed -Wl,-rpath=./
-Wl,-rpath=./
用于指定程序运行寻找库的路径
运行结果
1
2
3
4
5
6
7
8
9
10
11
| thread finished with count=5000000
thread finished with count=5000000
thread finished with count=5000000
thread finished with count=5000000
thread finished with count=5000000
thread finished with count=5000000
thread finished with count=5000000
thread finished with count=5000000
thread finished with count=5000000
thread finished with count=5000000
thread finished with count=5000000
|
1
2
3
4
5
6
7
8
9
10
11
| package main
/*
#cgo LDFLAGS: -L./ -lembed
#include "interface.h"
*/
import "C"
func main() {
C.process()
}
|
go run test.go
结果与C运行一致
有参函数调用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| #[repr(C)]
pub struct Test{
a:u32,
b:u32,
}
#[no_mangle]
pub extern "C" fn process(test:*const Test){
unsafe{
println!("{}",(*test).a);
println!("{}",(*test).b)
}
}
|
cargo build --release --out-dir . -Z unstable-options
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| struct Test
{
int a;
int b;
};
extern void process(struct Test *test);
int main(){
struct Test test = {3,4};
process(&test);
return 0;
}
|
gcc main.c -L. -lembed -Wl,-rpath=./ && ./a.out
output
1
2
3
4
5
6
| typedef struct Test
{
int a;
int b;
} Test;
void process(struct Test *test);
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| package main
/*
#cgo LDFLAGS: -L./ -lembed -Wl,-rpath=./
#include "interface.h" //非标准c头文件,所以用引号
typedef struct Test
{
int a;
int b;
} Test; #可以放但是不建议(建议放入interface.h)
*/
import "C"
func main() {
test := C.Test{a: 3, b: 4}
C.process(&test)
}
|
字符串指针返回
很多数据结构在跨语言调用,得在各个语言来回解析,比较麻烦,我们直接以json字符串传递解析可以极大的简化问题的处理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
| use std::thread;
use libc::c_int;
use libc::c_char;
use std::ffi::{CStr,CString};
use json;
#[no_mangle]
pub extern "C" fn process(a:c_int){
let handles:Vec<_>=(0..=10).map(|_|{
thread::spawn(||{
let mut x = 0;
for _ in 0..5000000{
x += 1
}
x
})
}).collect();
for h in handles{
println!("thread finished with count={}",h.join().map_err(|_|"could not join a thread").unwrap());
}
println!("{} have done",a)
}
#[no_mangle]
pub extern "C" fn json_parse(c_buf:*const c_char)-> *const c_char{
let c_str = unsafe { CStr::from_ptr(c_buf) }.to_str().unwrap();
let parsed = json::parse(c_str).unwrap();
println!("{}",parsed["a"]);
let data = r#"
{
"name": "John Doe",
"age": 43,
"phones": [
"+44 1234567",
"+44 2345678"
]
}"#;
CString::new(data).unwrap().into_raw()
}
|
1
2
3
4
5
6
7
8
9
10
| #include "interface.h"
#include <stdio.h>
int main(){
process(3);
const char *str = "{\"a\": 3}";
const char *ret_str = json_parse(str);
printf("%s\n",ret_str);
return 0;
}
|
1
2
| void process(int a);
const char * json_parse(const char *c_buf);
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| package main
/*
#cgo LDFLAGS: -L./ -lembed
#include "interface.h" //非标准c头文件,所以用引号
*/
import "C"
import "fmt"
func main() {
C.process(C.int(3))
ret_ptr := C.json_parse(C.CString(`{"a":3}`))
fmt.Println(C.GoString(ret_ptr))
}
|