Open hanabi1224 opened 5 years ago
👍
include/pinyin.h
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
struct PinYinList {
size_t len;
char** ptr;
};
struct PinYinListGroup {
size_t len;
struct PinYinList* ptr;
};
// 普通风格,不带声调(默认风格)。如: `pin yin`
uint8_t NORMAL_STYLE = 0;
// 声调风格1,拼音声调在韵母第一个字母上。如: `pīn yīn`
uint8_t TONE_STYLE = 1;
// 声调风格2,即拼音声调在各个拼音之后,用数字 [0-4] 进行表示。如: `pi1n yi1n`
uint8_t TONE2_STYLE = 2;
// 声母风格,只返回各个拼音的声母部分。如: 中国 的拼音 `zh g`
uint8_t INITIALS_STYLE = 3;
// 首字母风格,只返回拼音的首字母部分。如: `p y`
uint8_t FIRST_LETTER_STYLE = 4;
/// 韵母风格1,只返回各个拼音的韵母部分,不带声调。如: `ong uo`
uint8_t FINALS_STYLE = 5;
// 韵母风格2,带声调,声调在韵母第一个字母上。如: `ōng uó`
uint8_t FINALS_TONE_STYLE = 6;
// 韵母风格2,带声调,声调在各个拼音之后,用数字 [0-4] 进行表示。如: `o1ng uo2`
uint8_t FINALS_TONE2_STYLE = 7;
void pinyin_free(struct PinYinListGroup list) {
for (size_t i=0; i<list.len; i++) {
struct PinYinList pinyin_list = *(list.ptr + i);
for (size_t idx=0; idx<pinyin_list.len; idx++) {
char* ptr = *(pinyin_list.ptr + idx);
free(ptr);
}
free(pinyin_list.ptr);
}
free(list.ptr);
}
struct PinYinListGroup pinyin_query(unsigned char* input, uint8_t style, bool heteronym);
src/cffi.rs
use crate::{ Args, Style, pinyin, };
use std::ffi::{ CStr, CString, };
#[derive(Debug)]
#[repr(C)]
pub struct PinYinList {
pub len: libc::size_t,
pub ptr: *mut *mut libc::c_char,
}
#[derive(Debug)]
#[repr(C)]
pub struct PinYinListGroup {
pub len: libc::size_t,
pub ptr: *mut *mut PinYinList,
}
impl PinYinListGroup {
pub fn empty() -> PinYinListGroup {
let len = 0;
let ptr = std::ptr::null_mut();
PinYinListGroup { len, ptr, }
}
pub fn as_ptr(&mut self) -> *const PinYinListGroup {
self
}
pub fn as_mut_ptr(&mut self) -> *mut PinYinListGroup {
self
}
}
#[no_mangle]
pub extern "C" fn pinyin_query(input: *const libc::c_char,
style: Style,
heteronym: bool) -> PinYinListGroup {
let args = Args { style: style, heteronym: heteronym, };
unsafe { CStr::from_ptr(input) }.to_str()
.ok()
.map(|s| {
let mut result =
pinyin(s, &args)
.iter()
.map(|elems| {
let len = elems.len();
let mut items = elems.iter()
.map(|elem| CString::new(elem.as_str()).unwrap().into_raw() )
.collect::<Vec<*mut libc::c_char>>();
let ptr = items.as_mut_ptr();
std::mem::forget(items);
PinYinList { len, ptr, }
})
.collect::<Vec<PinYinList>>();
let len = result.len();
let ptr = result.as_mut_ptr();
std::mem::forget(result);
PinYinListGroup { len, ptr: ptr as _, }
})
.unwrap_or(PinYinListGroup::empty())
}
example/cquery.c
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include "pinyin.h"
//
// cargo build
// cc main.c -L ./target/debug/ -l pinyin -o main
// ./main
void query() {
unsigned char* input = (unsigned char*)"扒手扒手扒手扒手扒手扒";
uint8_t style = NORMAL_STYLE;
bool heteronym = true;
struct PinYinListGroup list = pinyin_query(input, style, heteronym);
printf("Input: %s\n", input);
printf("Params: { style: %d, heteronym: %s }\n", style, heteronym ? "true" : "false");
printf("Output:\n");
for (size_t i=0; i<list.len; i++) {
struct PinYinList pinyin_list = *(list.ptr + i);
printf(" ");
for (size_t idx=0; idx<pinyin_list.len; idx++) {
char* ptr = *(pinyin_list.ptr + idx);
printf("%s, ", ptr);
}
printf("\n");
}
pinyin_free(list);
}
int main(int argc, char const *argv[]) {
for (int i = 0; i < 10; ++i) {
query();
}
printf("DONE.\n");
return 0;
}
仅供参考 :)
@hanabi1224
我提个建议,就是 C 函数前面最好能加上一个统一的命名空间(如 pinyin_xxx
) :)
https://github.com/mozillazg/rust-pinyin/issues/26