ready 1.4.0

This commit is contained in:
neuecc 2023-03-17 17:46:32 +09:00
parent f163a32e0c
commit 4d900612c8
8 changed files with 149 additions and 95 deletions

View File

@ -26,7 +26,7 @@ Install on `Cargo.toml` as `build-dependencies` and set up `bindgen::Builder` on
```toml ```toml
[build-dependencies] [build-dependencies]
csbindgen = "1.3.0" csbindgen = "1.4.0"
``` ```
### Rust to C#. ### Rust to C#.
@ -192,6 +192,15 @@ namespace {csharp_namespace}
`csharp_dll_name_if` is optional. If specified, `#if` allows two DllName to be specified, which is useful if the name must be `__Internal` at iOS build. `csharp_dll_name_if` is optional. If specified, `#if` allows two DllName to be specified, which is useful if the name must be `__Internal` at iOS build.
`input_extern_file` allows mulitple call, if you need to add dependent struct, use this.
```rust
csbindgen::Builder::default()
.input_extern_file("src/lib.rs")
.input_extern_file("src/struct_modules.rs")
.generate_csharp_file("../dotnet-sandbox/NativeMethods.cs");
```
### Unity Callback ### Unity Callback
`csharp_use_function_pointer` configures how generate function pointer. The default is to generate a `delegate*`, but Unity does not support it; setting it to `false` will generate a `Func/Action` that can be used with `MonoPInvokeCallback`. `csharp_use_function_pointer` configures how generate function pointer. The default is to generate a `delegate*`, but Unity does not support it; setting it to `false` will generate a `Func/Action` that can be used with `MonoPInvokeCallback`.

View File

@ -32,10 +32,10 @@ fn main() -> Result<(), Box<dyn Error>> {
// .write_to_file("src/quiche.rs")?; // .write_to_file("src/quiche.rs")?;
bindgen::Builder::default() // bindgen::Builder::default()
.header("c/sqlite3/sqlite3.h") // .header("c/sqlite3/sqlite3.h")
.generate()? // .generate()?
.write_to_file("src/sqlite3.rs")?; // .write_to_file("src/sqlite3.rs")?;
// bindgen::Builder::default() // bindgen::Builder::default()
// .header("c/bullet3/PhysicsClientC_API.h") // .header("c/bullet3/PhysicsClientC_API.h")
@ -66,21 +66,21 @@ fn main() -> Result<(), Box<dyn Error>> {
.unwrap(); .unwrap();
csbindgen::Builder::default() // csbindgen::Builder::default()
.input_bindgen_file("src/sqlite3.rs") // .input_bindgen_file("src/sqlite3.rs")
.method_filter(|x| x.starts_with("sqlite3_")) // .method_filter(|x| x.starts_with("sqlite3_"))
.rust_method_prefix("csbindgen_") // .rust_method_prefix("csbindgen_")
.rust_file_header("use super::sqlite3::*;") // .rust_file_header("use super::sqlite3::*;")
// .rust_method_type_path("sqlite3") // // .rust_method_type_path("sqlite3")
.csharp_class_name("LibSqlite3") // .csharp_class_name("LibSqlite3")
.csharp_namespace("CsBindgen") // .csharp_namespace("CsBindgen")
.csharp_dll_name("csbindgen_tests") // .csharp_dll_name("csbindgen_tests")
.csharp_dll_name_if("UNITY_IOS && !UNITY_EDITOR", "__Internal") // .csharp_dll_name_if("UNITY_IOS && !UNITY_EDITOR", "__Internal")
.csharp_entry_point_prefix("csbindgen_") // .csharp_entry_point_prefix("csbindgen_")
.csharp_method_prefix("") // .csharp_method_prefix("")
.csharp_class_accessibility("public") // .csharp_class_accessibility("public")
.generate_to_file("src/sqlite3_ffi.rs", "../dotnet-sandbox/sqlite3_bindgen.cs") // .generate_to_file("src/sqlite3_ffi.rs", "../dotnet-sandbox/sqlite3_bindgen.cs")
.unwrap(); // .unwrap();
csbindgen::Builder::default() csbindgen::Builder::default()
.input_extern_file("src/lib.rs") .input_extern_file("src/lib.rs")
@ -92,29 +92,29 @@ fn main() -> Result<(), Box<dyn Error>> {
.generate_csharp_file("../dotnet-sandbox/NativeMethods.cs") .generate_csharp_file("../dotnet-sandbox/NativeMethods.cs")
.unwrap(); .unwrap();
csbindgen::Builder::new() // csbindgen::Builder::new()
.input_bindgen_file("src/zstd.rs") // .input_bindgen_file("src/zstd.rs")
.method_filter(|x| x.starts_with("ZSTD_")) // .method_filter(|x| x.starts_with("ZSTD_"))
.rust_file_header("use super::zstd::*;") // .rust_file_header("use super::zstd::*;")
.csharp_class_name("LibZstd") // .csharp_class_name("LibZstd")
.csharp_dll_name("libzsd") // .csharp_dll_name("libzsd")
.generate_to_file("src/zstd_ffi.rs", "../dotnet-sandbox/zstd_bindgen.cs")?; // .generate_to_file("src/zstd_ffi.rs", "../dotnet-sandbox/zstd_bindgen.cs")?;
csbindgen::Builder::new() // csbindgen::Builder::new()
.input_bindgen_file("src/quiche.rs") // .input_bindgen_file("src/quiche.rs")
.method_filter(|x| x.starts_with("quiche_")) // .method_filter(|x| x.starts_with("quiche_"))
.rust_file_header("use super::quiche::*;") // .rust_file_header("use super::quiche::*;")
.csharp_class_name("LibQuiche") // .csharp_class_name("LibQuiche")
.csharp_dll_name("libquiche") // .csharp_dll_name("libquiche")
.generate_to_file("src/quiche_ffi.rs", "../dotnet-sandbox/quiche_bindgen.cs")?; // .generate_to_file("src/quiche_ffi.rs", "../dotnet-sandbox/quiche_bindgen.cs")?;
csbindgen::Builder::new() // csbindgen::Builder::new()
.input_bindgen_file("src/bullet3.rs") // .input_bindgen_file("src/bullet3.rs")
.method_filter(|x| x.starts_with("b3")) // .method_filter(|x| x.starts_with("b3"))
.rust_file_header("use super::bullet3::*;") // .rust_file_header("use super::bullet3::*;")
.csharp_class_name("LibBullet3") // .csharp_class_name("LibBullet3")
.csharp_dll_name("libbullet3") // .csharp_dll_name("libbullet3")
.generate_to_file("src/bullet3_ffi.rs", "../dotnet-sandbox/bullet3_bindgen.cs")?; // .generate_to_file("src/bullet3_ffi.rs", "../dotnet-sandbox/bullet3_bindgen.cs")?;
Ok(()) Ok(())
} }

View File

@ -3,8 +3,6 @@ use std::{
ffi::{c_char, c_long, c_ulong, c_void, CString}, ffi::{c_char, c_long, c_ulong, c_void, CString},
}; };
#[allow(dead_code)] #[allow(dead_code)]
#[allow(non_snake_case)] #[allow(non_snake_case)]
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
@ -60,31 +58,48 @@ mod lz4_ffi;
// #[allow(non_camel_case_types)] // #[allow(non_camel_case_types)]
// mod zstd_ffi; // mod zstd_ffi;
mod others; // mod others;
pub use others::HogeMoge; // pub use others::HogeMoge;
// #[no_mangle]
// pub extern "C" fn other_1(hoge: HogeMoge) {
// println!("{:?}", hoge);
// }
#[repr(C)]
pub struct NfcCard {
pub delegate: unsafe extern "C" fn(ByteArray) -> ByteArray
}
#[no_mangle] #[no_mangle]
pub extern "C" fn other_1(hoge: HogeMoge){ pub extern "C" fn other_2(_hoge: NfcCard) {}
println!("{}", hoge);
#[repr(C)]
pub struct ByteArray {
pub i: i32,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct event {
pub a: i32
}
#[no_mangle]
pub extern "C" fn event(event: event ) {
println!("{:?}", event);
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn nest_test( pub extern "C" fn nest_test(
_f: ::std::option::Option< _f: ::std::option::Option<
unsafe extern "C" fn( unsafe extern "C" fn(
pxFunc: *mut ::std::option::Option< pxFunc: *mut ::std::option::Option<unsafe extern "C" fn(arg2: ::std::os::raw::c_int)>,
unsafe extern "C" fn(
arg2: ::std::os::raw::c_int,
),
>,
) -> ::std::os::raw::c_int, ) -> ::std::os::raw::c_int,
> >,
) { ) {
} }
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
pub type LONG_PTR = ::std::os::raw::c_longlong; pub type LONG_PTR = ::std::os::raw::c_longlong;
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]

View File

@ -6,4 +6,5 @@
pub enum HogeMoge{ pub enum HogeMoge{
X = 0, X = 0,
Y = 1, Y = 1,
event = 2
} }

View File

@ -1,6 +1,6 @@
[package] [package]
name = "csbindgen" name = "csbindgen"
version = "1.3.0" version = "1.4.0"
edition = "2021" edition = "2021"
authors = [ authors = [
"Yoshifumi Kawai <ils@neue.cc>", "Yoshifumi Kawai <ils@neue.cc>",

View File

@ -107,7 +107,12 @@ pub fn emit_csharp(
let mut method_list_string = String::new(); let mut method_list_string = String::new();
for item in methods { for item in methods {
let method_name = &item.method_name; let mut method_name = &item.method_name;
let method_name_temp: String;
if method_prefix.is_empty() {
method_name_temp = escape_name(method_name);
method_name = &method_name_temp;
}
if let Some(x) = &item.return_type { if let Some(x) = &item.return_type {
if let Some(delegate_method) = build_method_delegate_if_required( if let Some(delegate_method) = build_method_delegate_if_required(
@ -165,7 +170,7 @@ pub fn emit_csharp(
type_name = "[MarshalAs(UnmanagedType.U1)] bool".to_string(); type_name = "[MarshalAs(UnmanagedType.U1)] bool".to_string();
} }
format!("{} {}", type_name, p.escape_name()) format!("{} {}", type_name, escape_name(p.name.as_str()))
}) })
.collect::<Vec<_>>() .collect::<Vec<_>>()
.join(", "); .join(", ");
@ -189,7 +194,7 @@ pub fn emit_csharp(
let mut structs_string = String::new(); let mut structs_string = String::new();
for item in structs { for item in structs {
let name = &item.struct_name; let name = escape_name(&item.struct_name);
let layout_kind = if item.is_union { let layout_kind = if item.is_union {
"Explicit" "Explicit"
} else { } else {
@ -220,7 +225,7 @@ pub fn emit_csharp(
}; };
structs_string structs_string
.push_str(format!(" {}public {} {}", attr, type_name, field.name).as_str()); .push_str(format!(" {}public {} {}", attr, type_name, escape_name(field.name.as_str())).as_str());
if let TypeKind::FixedArray(digits, _) = &field.rust_type.type_kind { if let TypeKind::FixedArray(digits, _) = &field.rust_type.type_kind {
let mut digits = digits.clone(); let mut digits = digits.clone();
if digits == "0" { if digits == "0" {

View File

@ -1,31 +1,30 @@
use crate::{alias_map::AliasMap, builder::BindgenOptions}; use crate::{alias_map::AliasMap, builder::BindgenOptions};
pub fn escape_name(str: &str) -> String {
match str {
// C# keywords: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/
"abstract" | "as" | "base" | "bool" | "break" | "byte" | "case" | "catch" | "char"
| "checked" | "class" | "const" | "continue" | "decimal" | "default" | "delegate"
| "do" | "double" | "else" | "enum" | "event" | "explicit" | "extern" | "false"
| "finally" | "fixed" | "float" | "for" | "foreach" | "goto" | "if" | "implicit" | "in"
| "int" | "interface" | "internal" | "is" | "lock" | "long" | "namespace" | "new"
| "null" | "object" | "operator" | "out" | "override" | "params" | "private"
| "protected" | "public" | "readonly" | "ref" | "return" | "sbyte" | "sealed" | "short"
| "sizeof" | "stackalloc" | "static" | "string" | "struct" | "switch" | "this"
| "throw" | "true" | "try" | "typeof" | "uint" | "ulong" | "unchecked" | "unsafe"
| "ushort" | "using" | "virtual" | "void" | "volatile" | "while" => {
"@".to_string() + str
}
x => x.to_string(),
}
}
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Parameter { pub struct Parameter {
pub name: String, pub name: String,
pub rust_type: RustType, pub rust_type: RustType,
} }
impl Parameter {
pub fn escape_name(&self) -> String {
match self.name.as_str() {
// C# keywords: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/
"abstract" | "as" | "base" | "bool" | "break" | "byte" | "case" | "catch" | "char"
| "checked" | "class" | "const" | "continue" | "decimal" | "default" | "delegate"
| "do" | "double" | "else" | "enum" | "event" | "explicit" | "extern" | "false"
| "finally" | "fixed" | "float" | "for" | "foreach" | "goto" | "if" | "implicit"
| "in" | "int" | "interface" | "internal" | "is" | "lock" | "long" | "namespace"
| "new" | "null" | "object" | "operator" | "out" | "override" | "params"
| "private" | "protected" | "public" | "readonly" | "ref" | "return" | "sbyte"
| "sealed" | "short" | "sizeof" | "stackalloc" | "static" | "string" | "struct"
| "switch" | "this" | "throw" | "true" | "try" | "typeof" | "uint" | "ulong"
| "unchecked" | "unsafe" | "ushort" | "using" | "virtual" | "void" | "volatile"
| "while" => "@".to_string() + self.name.as_str(),
x => x.to_string(),
}
}
}
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct FieldMember { pub struct FieldMember {
pub name: String, pub name: String,
@ -153,7 +152,7 @@ impl RustType {
.map(|x| { .map(|x| {
format!( format!(
"{}: {}", "{}: {}",
x.escape_name(), escape_name(x.name.as_str()),
x.rust_type.to_rust_string(type_path) x.rust_type.to_rust_string(type_path)
) )
}) })
@ -184,7 +183,8 @@ impl RustType {
method_name: &String, method_name: &String,
parameter_name: &String, parameter_name: &String,
) -> String { ) -> String {
fn convert_type_name(type_name: &str) -> &str { fn convert_type_name(type_name: &str) -> String {
let temp_string: String;
let name = match type_name { let name = match type_name {
// std::os::raw https://doc.rust-lang.org/std/os/raw/index.html // std::os::raw https://doc.rust-lang.org/std/os/raw/index.html
// std::ffi::raw https://doc.rust-lang.org/core/ffi/index.html // std::ffi::raw https://doc.rust-lang.org/core/ffi/index.html
@ -220,9 +220,12 @@ impl RustType {
"bool" => "bool", "bool" => "bool",
"usize" => "nuint", // C# 9.0 "usize" => "nuint", // C# 9.0
"()" => "void", "()" => "void",
_ => type_name, // as is _ => {
temp_string = escape_name(type_name);
temp_string.as_str()
}
}; };
name name.to_string()
} }
// resolve alias // resolve alias
@ -233,7 +236,13 @@ impl RustType {
// if alias if Option, unwrap. // if alias if Option, unwrap.
let type_csharp_string = if use_alias { let type_csharp_string = if use_alias {
use_type.to_csharp_string(options, alias_map, emit_from_struct, method_name, parameter_name) use_type.to_csharp_string(
options,
alias_map,
emit_from_struct,
method_name,
parameter_name,
)
} else { } else {
convert_type_name(use_type.type_name.as_str()).to_string() convert_type_name(use_type.type_name.as_str()).to_string()
}; };
@ -421,7 +430,7 @@ pub fn build_method_delegate_if_required(
method_name, method_name,
parameter_name, parameter_name,
); );
format!("{} {}", cs, p.escape_name()) format!("{} {}", cs, escape_name(p.name.as_str()))
}) })
.collect::<Vec<_>>() .collect::<Vec<_>>()
.join(", "); .join(", ");

View File

@ -12,8 +12,11 @@ namespace CsBindgen
{ {
const string __DllName = "csbindgen_tests"; const string __DllName = "csbindgen_tests";
[DllImport(__DllName, EntryPoint = "other_1", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [DllImport(__DllName, EntryPoint = "other_2", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void other_1(HogeMoge hoge); public static extern void other_2(NfcCard _hoge);
[DllImport(__DllName, EntryPoint = "@event", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void @event(@event @event);
[DllImport(__DllName, EntryPoint = "nest_test", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [DllImport(__DllName, EntryPoint = "nest_test", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void nest_test(delegate* unmanaged[Cdecl]<delegate* unmanaged[Cdecl]<int, void>*, int> _f); public static extern void nest_test(delegate* unmanaged[Cdecl]<delegate* unmanaged[Cdecl]<int, void>*, int> _f);
@ -130,6 +133,24 @@ namespace CsBindgen
} }
[StructLayout(LayoutKind.Sequential)]
internal unsafe partial struct NfcCard
{
public delegate* unmanaged[Cdecl]<ByteArray, ByteArray> @delegate;
}
[StructLayout(LayoutKind.Sequential)]
internal unsafe partial struct ByteArray
{
public int i;
}
[StructLayout(LayoutKind.Sequential)]
internal unsafe partial struct @event
{
public int a;
}
[StructLayout(LayoutKind.Explicit)] [StructLayout(LayoutKind.Explicit)]
internal unsafe partial struct MyUnion internal unsafe partial struct MyUnion
{ {
@ -176,12 +197,6 @@ namespace CsBindgen
C = 10, C = 10,
} }
internal enum HogeMoge : int
{
X = 0,
Y = 1,
}
} }