絮絮叨叨

笔者最近做一个项目,跟一个写C的小伙一起开发。笔者原本是用Java写服务端接口的,那个小伙用C写客户端。客户端某个功能需要图片到服务端的Http接口上。

而写C的小伙目前对Http这块还不熟,加上C发起Http请求比较麻烦。于是笔者就想用Rust开发一个动态库链接库给C调用。在动态链接库公开一个函数,参数是Http的请求地址和图片,如果上传成功就返回1,失败就返回0。

Rust函数大致如下:

#[no_mangle]

pub extern "C" fn post_image(c_url: *const c_char, payload_ptr: *const payload_t) -> i32 {

// TODO

}

*const c_char用于接收来自C里面的字符串,在C里面对应的是const char *

*const payload_t是用来接收来自C的图片数据,在这里定应了一个Rust Struct

#[repr(C)]

pub struct payload_t {

data: *const u8,

len: c_int

}

这里的data表示接收一个来自C的指针,而len表示指针的长度。

下面来看整个扩展的编写过程。

开始写Rust代码

1、用cargo创建一个rust工程

cargo new mylib

cd mylib

2、在Cargo.toml文件中配置[lib]和[dependencies]

[lib]

name = "mylib"

crate-type = ["cdylib"]

path = "src/lib.rs"

[dependencies]

reqwest = {version = "0.10.0", features = ["blocking"] }

base64 = "0.11.0"

3、下面关键的步骤来了,编写lib.rs代码

use std::os::raw::{c_char, c_int};

use std::ffi::CStr;

use std::error::Error;

#[repr(C)]

pub struct payload_t {

data: *const u8,

len: c_int

}

#[no_mangle]

pub extern "C" fn post_image(c_url: *const c_char, payload_ptr: *const payload_t) -> i32 {

// 在这里开始一步步将c字符串转换成&str

let c_str: &CStr = unsafe {

CStr::from_ptr(c_url)

};

if let Err(err) = c_str.to_str() {

eprintln!("{}", err.description());

return 0;

}

let str_url = c_str.to_str().unwrap();

// 在这里开始将c传过来的文件,转换成&[u8]

let r_payload = unsafe {

*Box::from_raw(payload_ptr as *mut payload_t)

};

let bytes = unsafe {

std::slice::from_raw_parts(r_payload.data, r_payload.len as usize)

};

// 开始上传文件

if post(str_url, bytes) {

return 1;

}

return 0;

}

fn post(str_url: &str, payload: &[u8]) -> bool {

let client = reqwest::blocking::Client::new();

let body_base64 = base64::encode(payload);

if let Ok(res) = client.post(str_url).body(body_base64).send() {

let status = res.status();

println!("{:?}", res);

println!("{:?}", res.text());

if status == 201 {

return true;

}

};

return false;

}

在这里post函数中,把payload: &[u8]转为base64在上传的,实际不转也可以。主要得看接收文件的Http接口是如何做的。

用cbindgen生成头文件

1、安装cbindgen

cargo install --force cbindgen

2、在工程的根目录下编写cbindgen.toml文件

language = "C"

这里很简单,指定生成头文件的语言为C就可以了。这个文件为空也是可以的。

3、生成头文件

cbindgen --config cbindgen.toml --crate mylib --output mylib.h

编译动态链接库

cargo build

笔者用的是Mac系统,在target/debug目录下生成了libmylib.dylib文件,这个就是动态链接库了。接下来在这个目录下创建一个test.c文件来测试。

开始写C代码来测试

1、编写test.c

#include "mylib.h"

#include

int file_size(char * file_name)

{

FILE *fp = fopen(file_name, "rb");

int size;

if (fp == NULL)

return -1;

fseek(fp, 0, SEEK_END);

size = ftell(fp);

fclose(fp);

return size;

}

int main()

{

int size = 0;

const char *c_url = "http://localhost:8080/upload";

size = file_size("test.png");

FILE *fp;

char *buffer = (char*)malloc(sizeof(char)*size);

fp = fopen("test.png", "rb");

if (fp == NULL)

return 0;

fread(buffer, 1, size, fp);

fclose(fp);

payload_t payload;

payload_t *payload_ptr = malloc(sizeof(payload));

const uint8_t *buffer_ptr = (uint8_t *)buffer;

payload_ptr->data = buffer_ptr;

payload_ptr->len = size;

int32_t flag = post_image(c_url, payload_ptr);

if(flag == 1)

{

printf("%s\n", "上传成功");

}

else

{

printf("%s\n", "上传失败");

}

free(buffer);

buffer = NULL;

return 0;

}

这里是用C代码上传本地的一张test.png图片到服务端。测试时记得复制一张图片到C代码所在目录。

2、编译C,并运行

gcc test.c -L ./ -lmylib -o test

./test

mylib就是动态链接库的名称.

就这样结束了。

rust如何在木板上上传图片_C调用Rust动态链接库实现Http文件上传相关推荐

  1. 上传图片被防火墙拦截_Web安全:文件上传漏洞

    文章来源:计算机与网络安全 一般将文件上传归类为直接文件上传与间接文件上传.直接文件上传就是服务器根本没有做任何安全过滤,导致攻击者可以直接上传小马文件及大马文件(如ASP.ASPX.PHP.JSP及 ...

  2. rust如何在木板上上传图片_腐蚀rust游戏玩法方式详解

    在腐蚀这款游戏中玩家所有的物资都需要自己去寻找,不过很多时候遇到不怀好意的玩家时最好提高安全意识,及时躲避袭击,下面是游戏玩法发展方式详解. 游戏玩法方式详解 这里分两种发展方式 1.纯新手 首先需要 ...

  3. 服务器上传图片显示图片404,关于使用spring文件上传遇到的服务器中的图片访问不到报404的问题...

    中的enctype确实是"multipart/form-data",后来实在没办法了,他前面提到过找不到类,那会不会是还有jar没有引进去呢,后来发现错误信息里有IOUtils这个 ...

  4. 微信小程序开发之文件上传下载应用场景(附Demo源码)

    微信小程序开发之文件上传下载应用场景(附Demo源码),Demo为小相册应用,源码在附件中,本示例需要腾讯云支持. http://www.henkuai.com/forum.php?mod=viewt ...

  5. 文件上传、文件包含和目路遍历杂谈

    一.说明 文件上传.文件包含和目路遍历是<黑客防线>盛行的时代常谈的getshell手法,但到现在的安全书藉感觉就比较少提及或一笔带过.在谈的年代看不懂,在看得懂的年代又不谈了,概念感觉总 ...

  6. multipart/form-data与httpclient文件上传

    写在前面:本文讨论的内容都是基于java相关技术栈. 文件上传无论是在传统的基于html的web系统开发,还是目前主流的移动app开发,都是一个比较常见的功能需求.例如:web oa系统,可能会涉及到 ...

  7. django文件上传到服务器,django上传文件的三种方式

    Django文件上传需要考虑的重要事项 文件或图片一般通过表单进行.用户在前端点击文件上传,然后以POST方式将数据和文件提交到服务器.服务器在接收到POST请求后需要将其存储在服务器上的某个地方.D ...

  8. 实现HTTP协议Get、Post和文件上传功能——使用WinHttp接口实现

    在<使用WinHttp接口实现HTTP协议Get.Post和文件上传功能>一文中,我已经比较详细地讲解了如何使用WinHttp接口实现各种协议.在最近的代码梳理中,我觉得Post和文件上传 ...

  9. Struts 2的文件上传

    Struts 2并未提供自己的请求解析器,也就是说,Struts 2不会自己去处理multipart/form-data的请求,它需要调用其他上传框架来解析二进制请求数据.但Struts 2在原有的上 ...

最新文章

  1. github创建本地库后关联远程库
  2. swoole php配置文件,easyswoole自义命令加载自定义配置文件
  3. 物联网技术概论的课程编号_选课推荐 | 第5期:物联网技术概论
  4. 杯子 + Kronican
  5. 遵义大数据中心项目工程概况_中策大数据:8月建筑工程项目有哪些?建筑工程项目信息汇总...
  6. R语言基础篇-----画图
  7. csredis封装_ASP.NET Core 2.0下使用Redis——基于CSRedis实现
  8. 时间序列-ARIMA模型调参检验实战
  9. Excel函数实战技巧精粹(二)常用函数之VLOOKUP全解
  10. LCD12864(ST7565P)字符汉字显示(STM32F103)
  11. dom影像图形成数字地形图_数字地形图等高线怎么生成(海地软件地形图数字化高层数据层怎么选择,在哪里...)...
  12. cad卸载不干净_如何才能干净的卸载顽固软件?不给恶意软件留机会!
  13. 倾斜摄影当中模型精度和测绘当中的分辨率/比例尺是怎么回事?
  14. 下列属于计算机应用,计算机的应用领域可大致分为6个方面,下列选项中属于计算机应用领域的是...
  15. asa 防火墙拦截了https_思科ASA防火墙下抓包方法
  16. linux c语言俄罗斯方块,C语言俄罗斯方块游戏解析(图文+源码)
  17. 使用matlab进行人工神经网络拟合
  18. Mornsun B0505S-1WR3 隔离模块DC/DC
  19. 租赁合同到期后如何处理
  20. debian squeeze安装Broadcom网卡驱动全程

热门文章

  1. 使用正则表达式获取两个特定词之间的数据(Python代码)
  2. 随身WIFI的刷机(debian系统)
  3. 《Ruby》学习笔记
  4. 好佳居窗帘十大品牌 表露你性格的可能是窗帘
  5. vue 使用 gojs
  6. linux电脑鼠标点击没反应,linux – 鼠标点击无法在Ubuntu 16.04 LTS中运行
  7. C++实现自适应二值化
  8. 皖西学院2021对口高考成绩查询,2021年皖西学院高考录取结果什么时候出来及查询系统入口...
  9. 从技术创业到产品创业
  10. PNAS:勘探地球物理学论文