refactoring one

This commit is contained in:
neuecc 2023-02-27 19:44:03 +09:00
parent 4ac772ad22
commit 4189fd72fd
13 changed files with 729 additions and 2959 deletions

View File

@ -3,8 +3,13 @@ name = "csbindgen-tests"
version = "0.1.0"
edition = "2021"
# [[bin]]
# name = "csbindgen-test-app"
# path = "src/main.rs"
[lib]
crate-type = ["cdylib"]
path = "src/lib.rs"
[dependencies]
csbindgen = { path = "../csbindgen" }

View File

@ -1,10 +1,9 @@
#![feature(core_intrinsics)]
fn main() {
let bindings = bindgen::Builder::default()
.header("c/lz4/lz4.h")
.header("c/lz4/lz4hc.h")
.header("c/lz4/lz4frame.h")
.header("c/lz4/xxhash.h")
//.header("c/lz4/lz4hc.h")
//.header("c/lz4/lz4frame.h")
//.header("c/lz4/xxhash.h")
.generate()
.expect("Unable to generate bindings");
@ -12,12 +11,11 @@ fn main() {
.write_to_file("src/lz4/mod.rs")
.expect("Couldn't write bindings!");
cc::Build::new().file("c/lz4/lz4.c").compile("lz4");
cc::Build::new().file("c/lz4/lz4.c").compile("csharp_lz4");
// TODO:write test
csbindgen::run(
"src/lz4/mod.rs",
"src/ffi.rs",
"../dotnet-sandbox/bindgen.cs",
)
csbindgen::Builder::new()
.input_bindgen_file("src/lz4/mod.cs")
.rust_method_prefix("csbindgen_")
.generate_to_file("src/ffi.rs", "../dotnet-sandbox/bindgen.cs")
.unwrap();
}

View File

@ -0,0 +1,23 @@
use std::env;
#[allow(dead_code)]
#[allow(non_snake_case)]
#[allow(non_camel_case_types)]
#[allow(non_upper_case_globals)]
mod lz4;
fn main() {
let path = env::current_dir().unwrap();
println!("starting dir: {}", path.display());
unsafe {
let num = lz4::LZ4_versionNumber();
println!("lz4 num: {}", num);
}
csbindgen::run(
"csbindgen-tests/src/lz4/mod.rs",
"csbindgen-tests/src/ffi.rs",
"dotnet-sandbox/bindgen.cs",
);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +0,0 @@
use std::env;
fn main() {
let path = env::current_dir().unwrap();
println!("starting dir: {}", path.display());
csbindgen::run(
"csbindgen-tests/src/lz4/mod.rs",
"csbindgen-tests/src/ffi.rs",
"dotnet-sandbox/bindgen.cs",
);
}

128
csbindgen/src/builder.rs Normal file
View File

@ -0,0 +1,128 @@
use std::{
error::Error,
fs::{File, OpenOptions},
io::{self, Write},
path::Path,
};
use crate::generate;
pub struct Builder {
options: BindgenOptions,
}
pub struct BindgenOptions {
pub input_bindgen_file: String,
/// add original extern call type prefix to rust wrapper,
/// `return {rust_method_type_path}::foo()`
pub rust_method_type_path: String,
/// add method prefix to rust wrapper,
/// `pub extern "C" fn {rust_method_prefix}foo()`
pub rust_method_prefix: String,
/// add file header string to rust wrapper,
/// `mod lz4;`, `use super::lz4;`
pub rust_file_header: String,
/// configure C# file namespace(default is `CsBindgen`),
/// "namespace {csharp_namespace}"
pub csharp_namespace: String,
/// configure C# class name(default is `NativeMethods`),
/// `public static unsafe partial class {csharp_class_name}`
pub csharp_class_name: String,
/// configure C# load dll name,
/// `[DllImport({csharp_dll_name})]`
pub csharp_dll_name: String,
/// configure C# calling method name prefix,
/// `public static extern void {csharp_method_prefix}foo()`
pub csharp_method_prefix: String,
/// configure c_long to {csharp_c_long_convert} type,
/// default is `Int32`.
pub csharp_c_long_convert: String,
/// configure c_long to {csharp_c_long_convert} type,
/// default is `UInt32`.
pub csharp_c_ulong_convert: String,
}
impl Builder {
pub fn new() -> Self {
Self {
options: BindgenOptions {
input_bindgen_file: "".to_string(),
rust_method_type_path: "".to_string(),
rust_method_prefix: "".to_string(),
rust_file_header: "".to_string(),
csharp_namespace: "CsBindgen".to_string(),
csharp_class_name: "NativeMethods".to_string(),
csharp_dll_name: "".to_string(),
csharp_method_prefix: "".to_string(),
csharp_c_long_convert: "Int32".to_string(),
csharp_c_ulong_convert: "UInt32".to_string(),
},
}
}
/// Change an input .rs file(such as generated from bindgen) to generate binding.
pub fn input_bindgen_file<T: Into<String>>(mut self, input_bindgen_file: T) -> Builder {
self.options.input_bindgen_file = input_bindgen_file.into();
self
}
// TODO:method chain methods...
/// add method prefix to rust wrapper,
/// `pub extern "C" fn {rust_method_prefix}foo()`
pub fn rust_method_prefix<T: Into<String>>(mut self, rust_method_prefix: T) -> Builder {
self.options.rust_method_prefix = rust_method_prefix.into();
self
}
// pub fn generate_csharp_file<T: AsRef<Path>>(&self, csharp_output_path: T) -> io::Result<()> {
// let mut file = OpenOptions::new()
// .write(true)
// .truncate(true)
// .create(true)
// .open(csharp_output_path.as_ref())?;
// let code = self.generate();
// file.write_all(code.as_bytes())?;
// file.flush()?;
// Ok(())
// }
pub fn generate_to_file<P: AsRef<Path>>(
&self,
rust_output_path: P,
csharp_output_path: P,
) -> Result<(), Box<dyn Error>> {
let mut rust_file = make_file(rust_output_path)?;
let mut csharp_file = make_file(csharp_output_path)?;
let (rust, csharp) = generate(&self.options)?;
rust_file.write_all(rust.as_bytes())?;
rust_file.flush()?;
csharp_file.write_all(csharp.as_bytes())?;
csharp_file.flush()?;
Ok(())
}
}
fn make_file<P: AsRef<Path>>(path: P) -> io::Result<File> {
let file = OpenOptions::new()
.write(true)
.truncate(true)
.create(true)
.open(path)?;
Ok(file)
}

186
csbindgen/src/emitter.rs Normal file
View File

@ -0,0 +1,186 @@
use std::collections::HashMap;
use crate::builder::BindgenOptions;
use crate::type_meta::*;
use crate::util::*;
pub fn emit_rust_method(list: &Vec<ExternMethod>, options: &BindgenOptions) -> String {
// configure
let method_type_path = &options.rust_method_type_path;
let method_prefix = &options.rust_method_prefix;
let file_header = &options.rust_file_header;
let mut methods_string = String::new();
for item in list {
let method_name = item.method_name.as_str();
let parameters = item
.parameters
.iter()
.map(|p| {
format!(
" {}: {}",
p.name,
p.rust_type.to_string(method_type_path)
)
})
.collect::<Vec<_>>()
.join(",\n");
let return_line = match &item.return_type {
None => "".to_string(),
Some(v) => format!(" -> {}", v.to_string(method_type_path)),
};
let parameter_only_names = item
.parameters
.iter()
.map(|p| format!(" {}", p.name))
.collect::<Vec<_>>()
.join(",\n");
let template = format!(
"
#[no_mangle]
pub extern \"C\" fn {method_prefix}{method_name}(
{parameters}
){return_line}
{{
unsafe {{
return {method_type_path}{method_name}(
{parameter_only_names}
)
}}
}}
"
);
methods_string.push_str(template.as_str());
}
let result = format!(
"// auto-generated via csbindgen
#[allow(unused)]
use ::std::os::raw::*;
{file_header}
{methods_string}
"
);
return result;
}
pub fn emit_csharp(
methods: &Vec<ExternMethod>,
aliases: &HashMap<String, RustType>,
structs: &Vec<RustStruct>,
options: &BindgenOptions
) -> String {
// configure
let namespace = &options.csharp_namespace;
let class_name = &options.csharp_class_name;
let dll_name = &options.csharp_dll_name;
let method_prefix = &options.csharp_method_prefix;
let mut method_list_string = String::new();
for item in methods {
let method_name = &item.method_name;
let return_type = match &item.return_type {
Some(x) => x.to_csharp_string(&options),
None => "void".to_string(),
};
let parameters = item
.parameters
.iter()
.map(|p| format!("{} {}", p.rust_type.to_csharp_string(&options), p.name))
.collect::<Vec<_>>()
.join(", ");
method_list_string.push_str_ln(
" [DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]",
);
method_list_string.push_str_ln(
format!(" public static extern {return_type} {method_prefix}{method_name}({parameters});").as_str(),
);
method_list_string.push_str("\n");
}
let mut alias_string = String::new();
let mut aliases: Vec<_> = aliases.iter().collect();
aliases.sort_by_key(|x| x.0);
for (name, rust_type) in aliases {
alias_string.push_str_ln(
format!(" using {} = {};", name, rust_type.to_csharp_string(&options)).as_str(),
);
}
let mut structs_string = String::new();
for item in structs {
let name = &item.struct_name;
let layout_kind = if item.is_union {
"Explicit"
} else {
"Sequential"
};
structs_string
.push_str_ln(format!(" [StructLayout(LayoutKind.{layout_kind})]").as_str());
structs_string.push_str_ln(format!(" public unsafe struct {name}").as_str());
structs_string.push_str_ln(" {");
for field in &item.fields {
if item.is_union {
structs_string.push_str_ln(" [FieldOffset(0)]");
}
structs_string.push_str(
format!(
" public {} {}",
field.rust_type.to_csharp_string(&options),
field.name
)
.as_str(),
);
if field.rust_type.is_fixed_array {
let mut digits = field.rust_type.fixed_array_digits.clone();
if digits == "0" {
digits = "1".to_string(); // 0 fixed array is not allowed in C#
};
structs_string.push_str(format!("[{}]", digits).as_str());
}
structs_string.push_str_ln(";");
}
structs_string.push_str_ln(" }");
structs_string.push_str("\n");
}
// TODO: for Unity, `__Intern`.
let result = format!(
"// <auto-generated>
// This code is generated via csbindgen.
// DON'T CHANGE THIS DIRECTLY.
// </auto-generated>
using System;
using System.Runtime.InteropServices;
namespace {namespace}
{{
{alias_string}
public static unsafe partial class {class_name}
{{
const string __DllName = \"{dll_name}\";
{method_list_string}
}}
{structs_string}
}}
"
);
return result;
}

View File

@ -1,17 +1,20 @@
use std::{
collections::{HashMap, HashSet},
fmt::Display,
fs::{self, File},
io::Write,
};
mod builder;
mod emitter;
mod parser;
mod type_meta;
mod util;
use syn::{ForeignItem, Item, Pat, ReturnType};
pub use builder::Builder;
// mod lz4;
use builder::BindgenOptions;
use emitter::*;
use parser::*;
use std::{collections::HashSet, error::Error};
pub fn run(rs_path: &str, output_path: &str, csharp_output_path: &str) {
let file_content = fs::read_to_string(rs_path).unwrap();
let file_ast = syn::parse_file(file_content.as_str()).unwrap();
pub(crate) fn generate(options: &BindgenOptions) -> Result<(String, String), Box<dyn Error>> {
let path = &options.input_bindgen_file;
let file_content = std::fs::read_to_string(path)?;
let file_ast = syn::parse_file(file_content.as_str())?;
let methods = collect_method(&file_ast);
let aliases = collect_type_alias(&file_ast);
@ -39,551 +42,11 @@ pub fn run(rs_path: &str, output_path: &str, csharp_output_path: &str) {
let structs = reduce_struct(&structs, &using_types);
let vecs = emit_rust_method(&methods);
// TODO: filter methods
//if !(t.method_name.starts_with("_") || t.method_name == "") {
let mut file = File::create(output_path).unwrap();
{
// TODO:modify here
// TODO:modify here
file.write_all("#[allow(unused)]\n".as_bytes()).unwrap();
file.write_all("use ::std::os::raw::*;\n".as_bytes())
.unwrap();
file.write_all("use super::lz4;\n\n".as_bytes()).unwrap();
for str in vecs {
file.write_all(str.as_bytes()).unwrap();
}
let rust = emit_rust_method(&methods, &options);
let csharp = emit_csharp(&methods, &aliases, &structs, &options);
file.flush().unwrap();
}
let csharp = emit_csharp(&methods, &aliases, &structs);
let mut file = File::create(csharp_output_path).unwrap();
file.write_all(csharp.as_bytes()).unwrap();
file.flush().unwrap();
}
fn collect_method(ast: &syn::File) -> Vec<ExternMethod> {
let mut list: Vec<ExternMethod> = Vec::new();
for item in ast.items.iter() {
if let Item::ForeignMod(m) = item {
for item in m.items.iter() {
if let ForeignItem::Fn(m) = item {
let method_name = m.sig.ident.to_string();
let mut parameters: Vec<Parameter> = Vec::new();
let mut retrun_type: Option<RustType> = None;
// argument
for arg in m.sig.inputs.iter() {
if let syn::FnArg::Typed(t) = arg {
let mut parameter_name: String = "".to_string();
if let Pat::Ident(ident) = &*t.pat {
parameter_name = ident.ident.to_string();
}
let rust_type = parse_type(&t.ty);
parameters.push(Parameter {
name: parameter_name,
rust_type: rust_type,
});
}
}
// return
if let ReturnType::Type(_, b) = &m.sig.output {
let rust_type = parse_type(&b);
if rust_type.type_name == "" {
continue;
}
retrun_type = Some(rust_type);
}
let t = ExternMethod {
method_name: method_name.clone(),
parameters: parameters,
return_type: retrun_type,
};
list.push(t.clone());
}
}
}
}
return list;
}
fn collect_type_alias(ast: &syn::File) -> Vec<(String, RustType)> {
let mut result = Vec::new();
for item in ast.items.iter() {
if let Item::Type(t) = item {
let name = t.ident.to_string();
let alias = parse_type(&t.ty);
// pointer can not use alias.
if !alias.is_pointer || !alias.is_pointer_pointer {
result.push((name, alias));
}
}
}
return result;
}
fn collect_struct(ast: &syn::File) -> Vec<RustStruct> {
// collect union or struct
let mut result = Vec::new();
for item in ast.items.iter() {
if let Item::Union(t) = item {
let name = t.ident.to_string();
let fields = collect_fields(&t.fields);
result.push(RustStruct {
struct_name: name,
fields: fields,
is_union: true,
});
} else if let Item::Struct(t) = item {
if let syn::Fields::Named(f) = &t.fields {
let name = t.ident.to_string();
let fields = collect_fields(&f);
result.push(RustStruct {
struct_name: name,
fields: fields,
is_union: false,
});
};
}
}
return result;
}
fn collect_fields(fields: &syn::FieldsNamed) -> Vec<FieldMember> {
let mut result = Vec::new();
for field in &fields.named {
if let Some(x) = &field.ident {
let t = parse_type(&field.ty);
result.push(FieldMember {
name: x.to_string(),
rust_type: t,
});
}
}
return result;
}
fn reduce_type_alias(
aliases: &Vec<(String, RustType)>,
using_types: &HashSet<String>,
) -> HashMap<String, RustType> {
let mut map = HashMap::new();
for (name, rust_type) in aliases {
if using_types.contains(name) {
map.insert(name.clone(), rust_type.clone());
}
}
for (name, rust_type) in aliases {
let pointed = map.get(rust_type.type_name.as_str());
if let Some(x) = pointed {
map.insert(name.to_string(), x.clone());
}
}
return map;
}
fn reduce_struct(structs: &Vec<RustStruct>, using_types: &HashSet<String>) -> Vec<RustStruct> {
let mut result = Vec::new();
for item in structs {
if using_types.contains(&item.struct_name) {
result.push(item.clone());
}
}
return result;
}
fn parse_type(t: &syn::Type) -> RustType {
let mut has_star = false;
let mut has_star_star = false;
let mut has_const = false;
let mut has_mut = false;
let mut digits: String = "".to_string();
let name = match t {
syn::Type::Ptr(t) => {
has_star = true;
has_const = t.const_token.is_some();
has_mut = t.mutability.is_some();
if let syn::Type::Path(path) = &*t.elem {
path.path.segments.last().unwrap().ident.to_string()
} else if let syn::Type::Ptr(t) = &*t.elem {
has_star = false;
has_star_star = true;
if let syn::Type::Path(path) = &*t.elem {
path.path.segments.last().unwrap().ident.to_string()
} else {
"".to_string()
}
} else {
"".to_string()
}
}
syn::Type::Path(t) => t.path.segments.last().unwrap().ident.to_string(),
syn::Type::Array(t) => {
if let syn::Expr::Lit(x) = &t.len {
if let syn::Lit::Int(x) = &x.lit {
digits = x.base10_digits().to_string();
}
};
parse_type(&t.elem).type_name // maybe ok, only retrieve type_name
}
_ => "".to_string(),
};
return RustType {
is_const: has_const,
is_mut: has_mut,
is_pointer: has_star,
is_pointer_pointer: has_star_star,
is_fixed_array: (digits != ""),
type_name: name,
fixed_array_digits: digits,
};
}
// TODO:rewrite
fn emit_rust_method(list: &Vec<ExternMethod>) -> Vec<String> {
let mod_name = "lz4";
let mut result = Vec::new();
for item in list {
let method_name = item.method_name.as_str();
let parameters = item.parameters.iter().map(|p| {
let mut sb = p.name.to_string();
sb.push_str(": ");
sb.push_str(p.rust_type.to_string(mod_name).as_str());
sb
});
let parameter_only_names = item.parameters.iter().map(|p| p.name.as_str());
let return_line = match &item.return_type {
None => "".to_string(),
Some(v) => {
let mut sb = " -> ".to_string();
sb.push_str(v.to_string(mod_name).as_str());
sb
}
};
let mut sb = String::new();
sb.push_str("#[no_mangle]\n");
sb.push_str(format!("pub extern \"C\" fn csbindgen_{method_name}(\n").as_str());
for parameter in parameters {
sb.push_str(" ");
sb.push_str(parameter.as_str());
sb.push_str(",\n");
}
sb.push_str(")");
if return_line != "" {
sb.push_str(return_line.as_str());
}
sb.push_str("\n");
sb.push_str("{\n");
sb.push_str(" unsafe {\n");
sb.push_str(format!(" return {mod_name}::{method_name}(\n").as_str());
for p in parameter_only_names {
sb.push_str(" ");
sb.push_str(p);
sb.push_str(",\n");
}
sb.push_str(" )\n");
sb.push_str(" }\n");
sb.push_str_ln("}\n");
result.push(sb);
}
return result;
}
fn emit_csharp(
methods: &Vec<ExternMethod>,
aliases: &HashMap<String, RustType>,
structs: &Vec<RustStruct>,
) -> String {
// TODO: options
let namespace = "Csbindgen";
let class_name = "NativeMethods";
let dll_name = "csbindgen_tests";
let method_prefix = "csbindgen_";
let mut method_list_string = String::new();
for item in methods {
let method_name = &item.method_name;
let return_type = match &item.return_type {
Some(x) => x.to_csharp_string(),
None => "void".to_string(),
};
let parameters = item
.parameters
.iter()
.map(|p| format!("{} {}", p.rust_type.to_csharp_string(), p.name))
.collect::<Vec<_>>()
.join(", ");
method_list_string.push_str_ln(
" [DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]",
);
method_list_string.push_str_ln(
format!(" public static extern {return_type} {method_prefix}{method_name}({parameters});").as_str(),
);
method_list_string.push_str("\n");
}
let mut alias_string = String::new();
let mut aliases: Vec<_> = aliases.iter().collect();
aliases.sort_by_key(|x| x.0);
for (name, rust_type) in aliases {
alias_string.push_str_ln(
format!(" using {} = {};", name, rust_type.to_csharp_string()).as_str(),
);
}
let mut structs_string = String::new();
for item in structs {
let name = &item.struct_name;
let layout_kind = if item.is_union {
"Explicit"
} else {
"Sequential"
};
structs_string
.push_str_ln(format!(" [StructLayout(LayoutKind.{layout_kind})]").as_str());
structs_string.push_str_ln(format!(" public unsafe struct {name}").as_str());
structs_string.push_str_ln(" {");
for field in &item.fields {
if item.is_union {
structs_string.push_str_ln(" [FieldOffset(0)]");
}
structs_string.push_str(
format!(
" public {} {}",
field.rust_type.to_csharp_string(),
field.name
)
.as_str(),
);
if field.rust_type.is_fixed_array {
let mut digits = field.rust_type.fixed_array_digits.clone();
if digits == "0" {
digits = "1".to_string(); // 0 fixed array is not allowed in C#
};
structs_string.push_str(format!("[{}]", digits).as_str());
}
structs_string.push_str_ln(";");
}
structs_string.push_str_ln(" }");
structs_string.push_str("\n");
}
let result = format!(
"// <auto-generated>
// This code is generated via csbindgen.
// DON'T CHANGE THIS DIRECTLY.
// </auto-generated>
using System;
using System.Runtime.InteropServices;
namespace {namespace}
{{
{alias_string}
public static unsafe partial class {class_name}
{{
const string __DllName = \"{dll_name}\";
{method_list_string}
}}
{structs_string}
}}
"
);
return result;
}
trait PushStrLn {
fn push_str_ln(&mut self, string: &str);
}
impl PushStrLn for String {
fn push_str_ln(&mut self, string: &str) {
self.push_str(string);
self.push('\n');
}
}
#[derive(Clone, Debug)]
pub struct Parameter {
pub name: String,
pub rust_type: RustType,
}
#[derive(Clone, Debug)]
pub struct FieldMember {
pub name: String,
pub rust_type: RustType,
}
#[derive(Clone, Debug)]
pub struct ExternMethod {
pub method_name: String,
pub parameters: Vec<Parameter>,
pub return_type: Option<RustType>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct RustType {
pub type_name: String,
pub is_pointer: bool,
pub is_pointer_pointer: bool,
pub is_const: bool,
pub is_mut: bool,
pub is_fixed_array: bool,
pub fixed_array_digits: String,
}
#[derive(Clone, Debug)]
pub struct RustStruct {
pub struct_name: String,
pub fields: Vec<FieldMember>,
pub is_union: bool,
}
impl RustType {
pub fn to_string(&self, mod_prefix: &str) -> String {
let mut sb = String::new();
if self.is_pointer || self.is_pointer_pointer {
sb.push_str("*");
}
if self.is_const {
sb.push_str("const");
}
if self.is_mut {
sb.push_str("mut");
}
if self.is_pointer_pointer {
if self.is_const {
sb.push_str(" *const");
} else {
sb.push_str(" *mut");
}
}
sb.push_str(" ");
if self.is_fixed_array {
sb.push_str("[");
sb.push_str(self.type_name.as_str());
sb.push_str("; ");
sb.push_str(self.fixed_array_digits.as_str());
sb.push_str("]");
} else {
if !self.type_name.starts_with("c_")
&& !(self.type_name == "usize" || self.type_name == "isize")
{
sb.push_str(mod_prefix);
sb.push_str("::");
}
sb.push_str(self.type_name.as_str());
}
sb
}
pub fn to_csharp_string(&self) -> String {
fn convert_type_name(type_name: &str) -> &str {
let name = match type_name {
// std::os::raw https://doc.rust-lang.org/std/os/raw/index.html
"c_char" => "Byte",
"c_schar" => "SByte",
"c_uchar" => "Byte",
"c_short" => "Int16",
"c_ushort" => "UInt16",
"c_int" => "Int32",
"c_uint" => "UInt32",
"c_long" => "Int32", // int? long? nint? TODO:configure
"c_ulong" => "UInt32", // uint? ulong? nuint? TODO:configure
"c_longlong" => "Int64",
"c_ulonglong" => "UInt64",
"c_float" => "Float",
"c_double" => "Double",
"c_void" => "void",
// rust primitives
"i8" => "SByte",
"i16" => "Int16",
"i32" => "Int32",
"i64" => "Int64",
"i128" => "Int128", // .NET 7
"isize" => "IntPtr",
"u8" => "Byte",
"u16" => "UInt16",
"u32" => "UInt32",
"u64" => "UInt64",
"u128" => "UInt128", // .NET 7
"f32" => "Float",
"f64" => "Double",
"bool" => "Boolean",
"usize" => "UIntPtr",
"()" => "void", // if type is parameter, can't use in C#
_ => type_name, // as is
};
name
}
let mut sb = String::new();
if self.is_fixed_array {
sb.push_str("fixed ");
sb.push_str(convert_type_name(self.type_name.as_str()));
} else {
sb.push_str(convert_type_name(self.type_name.as_str()));
if self.is_pointer {
sb.push_str("*");
}
if self.is_pointer_pointer {
sb.push_str("**");
}
}
sb
}
}
impl Display for RustType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.to_string(""))
}
return Ok((rust, csharp));
}

203
csbindgen/src/parser.rs Normal file
View File

@ -0,0 +1,203 @@
use std::collections::{HashSet, HashMap};
use crate::type_meta::*;
use syn::{ForeignItem, Item, Pat, ReturnType};
pub fn collect_method(ast: &syn::File) -> Vec<ExternMethod> {
let mut list: Vec<ExternMethod> = Vec::new();
for item in ast.items.iter() {
if let Item::ForeignMod(m) = item {
for item in m.items.iter() {
if let ForeignItem::Fn(m) = item {
let method_name = m.sig.ident.to_string();
let mut parameters: Vec<Parameter> = Vec::new();
let mut retrun_type: Option<RustType> = None;
// argument
for arg in m.sig.inputs.iter() {
if let syn::FnArg::Typed(t) = arg {
let mut parameter_name: String = "".to_string();
if let Pat::Ident(ident) = &*t.pat {
parameter_name = ident.ident.to_string();
}
let rust_type = parse_type(&t.ty);
parameters.push(Parameter {
name: parameter_name,
rust_type: rust_type,
});
}
}
// return
if let ReturnType::Type(_, b) = &m.sig.output {
let rust_type = parse_type(&b);
if rust_type.type_name == "" {
continue;
}
retrun_type = Some(rust_type);
}
let t = ExternMethod {
method_name: method_name.clone(),
parameters: parameters,
return_type: retrun_type,
};
list.push(t.clone());
}
}
}
}
return list;
}
pub fn collect_type_alias(ast: &syn::File) -> Vec<(String, RustType)> {
let mut result = Vec::new();
for item in ast.items.iter() {
if let Item::Type(t) = item {
let name = t.ident.to_string();
let alias = parse_type(&t.ty);
// pointer can not use alias.
if !alias.is_pointer || !alias.is_pointer_pointer {
result.push((name, alias));
}
}
}
return result;
}
pub fn collect_struct(ast: &syn::File) -> Vec<RustStruct> {
// collect union or struct
let mut result = Vec::new();
for item in ast.items.iter() {
if let Item::Union(t) = item {
let name = t.ident.to_string();
let fields = collect_fields(&t.fields);
result.push(RustStruct {
struct_name: name,
fields: fields,
is_union: true,
});
} else if let Item::Struct(t) = item {
if let syn::Fields::Named(f) = &t.fields {
let name = t.ident.to_string();
let fields = collect_fields(&f);
result.push(RustStruct {
struct_name: name,
fields: fields,
is_union: false,
});
};
}
}
return result;
}
fn collect_fields(fields: &syn::FieldsNamed) -> Vec<FieldMember> {
let mut result = Vec::new();
for field in &fields.named {
if let Some(x) = &field.ident {
let t = parse_type(&field.ty);
result.push(FieldMember {
name: x.to_string(),
rust_type: t,
});
}
}
return result;
}
pub fn reduce_type_alias(
aliases: &Vec<(String, RustType)>,
using_types: &HashSet<String>,
) -> HashMap<String, RustType> {
let mut map = HashMap::new();
for (name, rust_type) in aliases {
if using_types.contains(name) {
map.insert(name.clone(), rust_type.clone());
}
}
for (name, rust_type) in aliases {
let pointed = map.get(rust_type.type_name.as_str());
if let Some(x) = pointed {
map.insert(name.to_string(), x.clone());
}
}
return map;
}
pub fn reduce_struct(structs: &Vec<RustStruct>, using_types: &HashSet<String>) -> Vec<RustStruct> {
let mut result = Vec::new();
for item in structs {
if using_types.contains(&item.struct_name) {
result.push(item.clone());
}
}
return result;
}
fn parse_type(t: &syn::Type) -> RustType {
let mut has_star = false;
let mut has_star_star = false;
let mut has_const = false;
let mut has_mut = false;
let mut digits: String = "".to_string();
let name = match t {
syn::Type::Ptr(t) => {
has_star = true;
has_const = t.const_token.is_some();
has_mut = t.mutability.is_some();
if let syn::Type::Path(path) = &*t.elem {
path.path.segments.last().unwrap().ident.to_string()
} else if let syn::Type::Ptr(t) = &*t.elem {
has_star = false;
has_star_star = true;
if let syn::Type::Path(path) = &*t.elem {
path.path.segments.last().unwrap().ident.to_string()
} else {
"".to_string()
}
} else {
"".to_string()
}
}
syn::Type::Path(t) => t.path.segments.last().unwrap().ident.to_string(),
syn::Type::Array(t) => {
if let syn::Expr::Lit(x) = &t.len {
if let syn::Lit::Int(x) = &x.lit {
digits = x.base10_digits().to_string();
}
};
parse_type(&t.elem).type_name // maybe ok, only retrieve type_name
}
_ => "".to_string(),
};
return RustType {
is_const: has_const,
is_mut: has_mut,
is_pointer: has_star,
is_pointer_pointer: has_star_star,
is_fixed_array: (digits != ""),
type_name: name,
fixed_array_digits: digits,
};
}

146
csbindgen/src/type_meta.rs Normal file
View File

@ -0,0 +1,146 @@
use crate::builder::BindgenOptions;
#[derive(Clone, Debug)]
pub struct Parameter {
pub name: String,
pub rust_type: RustType,
}
#[derive(Clone, Debug)]
pub struct FieldMember {
pub name: String,
pub rust_type: RustType,
}
#[derive(Clone, Debug)]
pub struct ExternMethod {
pub method_name: String,
pub parameters: Vec<Parameter>,
pub return_type: Option<RustType>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct RustType {
pub type_name: String,
pub is_pointer: bool,
pub is_pointer_pointer: bool,
pub is_const: bool,
pub is_mut: bool,
pub is_fixed_array: bool,
pub fixed_array_digits: String,
}
#[derive(Clone, Debug)]
pub struct RustStruct {
pub struct_name: String,
pub fields: Vec<FieldMember>,
pub is_union: bool,
}
impl RustType {
pub fn to_string(&self, type_path: &str) -> String {
let mut sb = String::new();
if self.is_pointer || self.is_pointer_pointer {
sb.push_str("*");
}
if self.is_const {
sb.push_str("const");
}
if self.is_mut {
sb.push_str("mut");
}
if self.is_pointer_pointer {
if self.is_const {
sb.push_str(" *const");
} else {
sb.push_str(" *mut");
}
}
sb.push_str(" ");
if self.is_fixed_array {
sb.push_str("[");
sb.push_str(self.type_name.as_str());
sb.push_str("; ");
sb.push_str(self.fixed_array_digits.as_str());
sb.push_str("]");
} else {
if !self.type_name.starts_with("c_")
&& !(self.type_name == "usize" || self.type_name == "isize")
&& !(type_path == "")
{
sb.push_str(type_path);
sb.push_str("::");
}
sb.push_str(self.type_name.as_str());
}
sb
}
pub fn to_csharp_string(&self, options: &BindgenOptions) -> String {
fn convert_type_name(type_name: &str, options: &BindgenOptions) -> String {
let name = match type_name {
// std::os::raw https://doc.rust-lang.org/std/os/raw/index.html
"c_char" => "Byte",
"c_schar" => "SByte",
"c_uchar" => "Byte",
"c_short" => "Int16",
"c_ushort" => "UInt16",
"c_int" => "Int32",
"c_uint" => "UInt32",
"c_long" => &options.csharp_c_long_convert,
"c_ulong" => &options.csharp_c_ulong_convert,
"c_longlong" => "Int64",
"c_ulonglong" => "UInt64",
"c_float" => "Float",
"c_double" => "Double",
"c_void" => "void",
// rust primitives
"i8" => "SByte",
"i16" => "Int16",
"i32" => "Int32",
"i64" => "Int64",
"i128" => "Int128", // .NET 7
"isize" => "IntPtr",
"u8" => "Byte",
"u16" => "UInt16",
"u32" => "UInt32",
"u64" => "UInt64",
"u128" => "UInt128", // .NET 7
"f32" => "Float",
"f64" => "Double",
"bool" => "Boolean",
"usize" => "UIntPtr",
"()" => "void", // if type is parameter, can't use in C#
_ => type_name, // as is
};
name.to_string()
}
let mut sb = String::new();
if self.is_fixed_array {
sb.push_str("fixed ");
sb.push_str(convert_type_name(self.type_name.as_str(), &options).as_str());
} else {
sb.push_str(convert_type_name(self.type_name.as_str(), &options).as_str());
if self.is_pointer {
sb.push_str("*");
}
if self.is_pointer_pointer {
sb.push_str("**");
}
}
sb
}
}
impl std::fmt::Display for RustType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.to_string(""))
}
}

10
csbindgen/src/util.rs Normal file
View File

@ -0,0 +1,10 @@
pub trait PushStrLn {
fn push_str_ln(&mut self, string: &str);
}
impl PushStrLn for String {
fn push_str_ln(&mut self, string: &str) {
self.push_str(string);
self.push('\n');
}
}

View File

@ -7,28 +7,10 @@ using System.Runtime.InteropServices;
namespace Csbindgen
{
using LZ4F_blockChecksum_t = Int32;
using LZ4F_blockMode_t = Int32;
using LZ4F_blockSizeID_t = Int32;
using LZ4F_cctx = LZ4F_cctx_s;
using LZ4F_compressionContext_t = LZ4F_cctx_s;
using LZ4F_contentChecksum_t = Int32;
using LZ4F_dctx = LZ4F_dctx_s;
using LZ4F_decompressionContext_t = LZ4F_dctx_s;
using LZ4F_errorCode_t = UIntPtr;
using LZ4F_frameType_t = Int32;
using LZ4_byte = Byte;
using LZ4_i8 = SByte;
using LZ4_streamDecode_t = LZ4_streamDecode_u;
using LZ4_streamHC_t = LZ4_streamHC_u;
using LZ4_stream_t = LZ4_stream_u;
using LZ4_u16 = UInt16;
using LZ4_u32 = UInt32;
using XXH32_hash_t = UInt32;
using XXH32_state_t = XXH32_state_s;
using XXH64_hash_t = UInt64;
using XXH64_state_t = XXH64_state_s;
using XXH_errorcode = Int32;
public static unsafe partial class NativeMethods
@ -170,210 +152,6 @@ namespace Csbindgen
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern void csbindgen_LZ4_resetStream(LZ4_stream_t* streamPtr);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern Int32 csbindgen_LZ4_compress_HC(Byte* src, Byte* dst, Int32 srcSize, Int32 dstCapacity, Int32 compressionLevel);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern Int32 csbindgen_LZ4_sizeofStateHC();
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern Int32 csbindgen_LZ4_compress_HC_extStateHC(void* stateHC, Byte* src, Byte* dst, Int32 srcSize, Int32 maxDstSize, Int32 compressionLevel);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern Int32 csbindgen_LZ4_compress_HC_destSize(void* stateHC, Byte* src, Byte* dst, Int32* srcSizePtr, Int32 targetDstSize, Int32 compressionLevel);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern LZ4_streamHC_t* csbindgen_LZ4_createStreamHC();
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern Int32 csbindgen_LZ4_freeStreamHC(LZ4_streamHC_t* streamHCPtr);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern void csbindgen_LZ4_resetStreamHC_fast(LZ4_streamHC_t* streamHCPtr, Int32 compressionLevel);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern Int32 csbindgen_LZ4_loadDictHC(LZ4_streamHC_t* streamHCPtr, Byte* dictionary, Int32 dictSize);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern Int32 csbindgen_LZ4_compress_HC_continue(LZ4_streamHC_t* streamHCPtr, Byte* src, Byte* dst, Int32 srcSize, Int32 maxDstSize);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern Int32 csbindgen_LZ4_compress_HC_continue_destSize(LZ4_streamHC_t* LZ4_streamHCPtr, Byte* src, Byte* dst, Int32* srcSizePtr, Int32 targetDstSize);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern Int32 csbindgen_LZ4_saveDictHC(LZ4_streamHC_t* streamHCPtr, Byte* safeBuffer, Int32 maxDictSize);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern LZ4_streamHC_t* csbindgen_LZ4_initStreamHC(void* buffer, UIntPtr size);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern Int32 csbindgen_LZ4_compressHC(Byte* source, Byte* dest, Int32 inputSize);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern Int32 csbindgen_LZ4_compressHC_limitedOutput(Byte* source, Byte* dest, Int32 inputSize, Int32 maxOutputSize);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern Int32 csbindgen_LZ4_compressHC2(Byte* source, Byte* dest, Int32 inputSize, Int32 compressionLevel);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern Int32 csbindgen_LZ4_compressHC2_limitedOutput(Byte* source, Byte* dest, Int32 inputSize, Int32 maxOutputSize, Int32 compressionLevel);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern Int32 csbindgen_LZ4_compressHC_withStateHC(void* state, Byte* source, Byte* dest, Int32 inputSize);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern Int32 csbindgen_LZ4_compressHC_limitedOutput_withStateHC(void* state, Byte* source, Byte* dest, Int32 inputSize, Int32 maxOutputSize);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern Int32 csbindgen_LZ4_compressHC2_withStateHC(void* state, Byte* source, Byte* dest, Int32 inputSize, Int32 compressionLevel);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern Int32 csbindgen_LZ4_compressHC2_limitedOutput_withStateHC(void* state, Byte* source, Byte* dest, Int32 inputSize, Int32 maxOutputSize, Int32 compressionLevel);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern Int32 csbindgen_LZ4_compressHC_continue(LZ4_streamHC_t* LZ4_streamHCPtr, Byte* source, Byte* dest, Int32 inputSize);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern Int32 csbindgen_LZ4_compressHC_limitedOutput_continue(LZ4_streamHC_t* LZ4_streamHCPtr, Byte* source, Byte* dest, Int32 inputSize, Int32 maxOutputSize);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern void* csbindgen_LZ4_createHC(Byte* inputBuffer);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern Int32 csbindgen_LZ4_freeHC(void* LZ4HC_Data);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern Byte* csbindgen_LZ4_slideInputBufferHC(void* LZ4HC_Data);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern Int32 csbindgen_LZ4_compressHC2_continue(void* LZ4HC_Data, Byte* source, Byte* dest, Int32 inputSize, Int32 compressionLevel);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern Int32 csbindgen_LZ4_compressHC2_limitedOutput_continue(void* LZ4HC_Data, Byte* source, Byte* dest, Int32 inputSize, Int32 maxOutputSize, Int32 compressionLevel);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern Int32 csbindgen_LZ4_sizeofStreamStateHC();
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern Int32 csbindgen_LZ4_resetStreamStateHC(void* state, Byte* inputBuffer);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern void csbindgen_LZ4_resetStreamHC(LZ4_streamHC_t* streamHCPtr, Int32 compressionLevel);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern UInt32 csbindgen_LZ4F_isError(LZ4F_errorCode_t code);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern Byte* csbindgen_LZ4F_getErrorName(LZ4F_errorCode_t code);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern Int32 csbindgen_LZ4F_compressionLevel_max();
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern UIntPtr csbindgen_LZ4F_compressFrameBound(UIntPtr srcSize, LZ4F_preferences_t* preferencesPtr);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern UIntPtr csbindgen_LZ4F_compressFrame(void* dstBuffer, UIntPtr dstCapacity, void* srcBuffer, UIntPtr srcSize, LZ4F_preferences_t* preferencesPtr);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern UInt32 csbindgen_LZ4F_getVersion();
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern LZ4F_errorCode_t csbindgen_LZ4F_createCompressionContext(LZ4F_cctx** cctxPtr, UInt32 version);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern LZ4F_errorCode_t csbindgen_LZ4F_freeCompressionContext(LZ4F_cctx* cctx);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern UIntPtr csbindgen_LZ4F_compressBegin(LZ4F_cctx* cctx, void* dstBuffer, UIntPtr dstCapacity, LZ4F_preferences_t* prefsPtr);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern UIntPtr csbindgen_LZ4F_compressBound(UIntPtr srcSize, LZ4F_preferences_t* prefsPtr);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern UIntPtr csbindgen_LZ4F_compressUpdate(LZ4F_cctx* cctx, void* dstBuffer, UIntPtr dstCapacity, void* srcBuffer, UIntPtr srcSize, LZ4F_compressOptions_t* cOptPtr);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern UIntPtr csbindgen_LZ4F_flush(LZ4F_cctx* cctx, void* dstBuffer, UIntPtr dstCapacity, LZ4F_compressOptions_t* cOptPtr);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern UIntPtr csbindgen_LZ4F_compressEnd(LZ4F_cctx* cctx, void* dstBuffer, UIntPtr dstCapacity, LZ4F_compressOptions_t* cOptPtr);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern LZ4F_errorCode_t csbindgen_LZ4F_createDecompressionContext(LZ4F_dctx** dctxPtr, UInt32 version);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern LZ4F_errorCode_t csbindgen_LZ4F_freeDecompressionContext(LZ4F_dctx* dctx);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern UIntPtr csbindgen_LZ4F_headerSize(void* src, UIntPtr srcSize);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern UIntPtr csbindgen_LZ4F_getFrameInfo(LZ4F_dctx* dctx, LZ4F_frameInfo_t* frameInfoPtr, void* srcBuffer, UIntPtr* srcSizePtr);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern UIntPtr csbindgen_LZ4F_decompress(LZ4F_dctx* dctx, void* dstBuffer, UIntPtr* dstSizePtr, void* srcBuffer, UIntPtr* srcSizePtr, LZ4F_decompressOptions_t* dOptPtr);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern void csbindgen_LZ4F_resetDecompressionContext(LZ4F_dctx* dctx);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern UInt32 csbindgen_XXH_versionNumber();
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern XXH32_hash_t csbindgen_XXH32(void* input, UIntPtr length, UInt32 seed);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern XXH32_state_t* csbindgen_XXH32_createState();
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern XXH_errorcode csbindgen_XXH32_freeState(XXH32_state_t* statePtr);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern void csbindgen_XXH32_copyState(XXH32_state_t* dst_state, XXH32_state_t* src_state);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern XXH_errorcode csbindgen_XXH32_reset(XXH32_state_t* statePtr, UInt32 seed);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern XXH_errorcode csbindgen_XXH32_update(XXH32_state_t* statePtr, void* input, UIntPtr length);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern XXH32_hash_t csbindgen_XXH32_digest(XXH32_state_t* statePtr);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern void csbindgen_XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern XXH32_hash_t csbindgen_XXH32_hashFromCanonical(XXH32_canonical_t* src);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern XXH64_hash_t csbindgen_XXH64(void* input, UIntPtr length, UInt64 seed);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern XXH64_state_t* csbindgen_XXH64_createState();
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern XXH_errorcode csbindgen_XXH64_freeState(XXH64_state_t* statePtr);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern void csbindgen_XXH64_copyState(XXH64_state_t* dst_state, XXH64_state_t* src_state);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern XXH_errorcode csbindgen_XXH64_reset(XXH64_state_t* statePtr, UInt64 seed);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern XXH_errorcode csbindgen_XXH64_update(XXH64_state_t* statePtr, void* input, UIntPtr length);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern XXH64_hash_t csbindgen_XXH64_digest(XXH64_state_t* statePtr);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern void csbindgen_XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash);
[DllImport(__DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern XXH64_hash_t csbindgen_XXH64_hashFromCanonical(XXH64_canonical_t* src);
}
@ -415,106 +193,6 @@ namespace Csbindgen
public LZ4_streamDecode_t_internal internal_donotuse;
}
[StructLayout(LayoutKind.Sequential)]
public unsafe struct LZ4HC_CCtx_internal
{
public fixed LZ4_u32 hashTable[32768];
public fixed LZ4_u16 chainTable[65536];
public LZ4_byte* end;
public LZ4_byte* prefixStart;
public LZ4_byte* dictStart;
public LZ4_u32 dictLimit;
public LZ4_u32 lowLimit;
public LZ4_u32 nextToUpdate;
public Int16 compressionLevel;
public LZ4_i8 favorDecSpeed;
public LZ4_i8 dirty;
public LZ4HC_CCtx_internal* dictCtx;
}
[StructLayout(LayoutKind.Explicit)]
public unsafe struct LZ4_streamHC_u
{
[FieldOffset(0)]
public fixed Byte minStateSize[262200];
[FieldOffset(0)]
public LZ4HC_CCtx_internal internal_donotuse;
}
[StructLayout(LayoutKind.Sequential)]
public unsafe struct LZ4F_frameInfo_t
{
public LZ4F_blockSizeID_t blockSizeID;
public LZ4F_blockMode_t blockMode;
public LZ4F_contentChecksum_t contentChecksumFlag;
public LZ4F_frameType_t frameType;
public UInt64 contentSize;
public UInt32 dictID;
public LZ4F_blockChecksum_t blockChecksumFlag;
}
[StructLayout(LayoutKind.Sequential)]
public unsafe struct LZ4F_preferences_t
{
public LZ4F_frameInfo_t frameInfo;
public Int32 compressionLevel;
public UInt32 autoFlush;
public UInt32 favorDecSpeed;
public fixed UInt32 reserved[3];
}
[StructLayout(LayoutKind.Sequential)]
public unsafe struct LZ4F_cctx_s
{
public fixed Byte _unused[1];
}
[StructLayout(LayoutKind.Sequential)]
public unsafe struct LZ4F_compressOptions_t
{
public UInt32 stableSrc;
public fixed UInt32 reserved[3];
}
[StructLayout(LayoutKind.Sequential)]
public unsafe struct LZ4F_dctx_s
{
public fixed Byte _unused[1];
}
[StructLayout(LayoutKind.Sequential)]
public unsafe struct LZ4F_decompressOptions_t
{
public UInt32 stableDst;
public UInt32 skipChecksums;
public UInt32 reserved1;
public UInt32 reserved0;
}
[StructLayout(LayoutKind.Sequential)]
public unsafe struct XXH32_state_s
{
public fixed Byte _unused[1];
}
[StructLayout(LayoutKind.Sequential)]
public unsafe struct XXH32_canonical_t
{
public fixed Byte digest[4];
}
[StructLayout(LayoutKind.Sequential)]
public unsafe struct XXH64_state_s
{
public fixed Byte _unused[1];
}
[StructLayout(LayoutKind.Sequential)]
public unsafe struct XXH64_canonical_t
{
public fixed Byte digest[8];
}
}