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

View File

@ -3,8 +3,6 @@ use std::{
ffi::{c_char, c_long, c_ulong, c_void, CString},
};
#[allow(dead_code)]
#[allow(non_snake_case)]
#[allow(non_camel_case_types)]
@ -60,31 +58,48 @@ mod lz4_ffi;
// #[allow(non_camel_case_types)]
// mod zstd_ffi;
mod others;
pub use others::HogeMoge;
// mod others;
// 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]
pub extern "C" fn other_1(hoge: HogeMoge){
println!("{}", hoge);
pub extern "C" fn other_2(_hoge: NfcCard) {}
#[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]
pub extern "C" fn nest_test(
_f: ::std::option::Option<
unsafe extern "C" fn(
pxFunc: *mut ::std::option::Option<
unsafe extern "C" fn(
arg2: ::std::os::raw::c_int,
),
>,
pxFunc: *mut ::std::option::Option<unsafe extern "C" fn(arg2: ::std::os::raw::c_int)>,
) -> ::std::os::raw::c_int,
>
>,
) {
}
#[allow(non_camel_case_types)]
pub type LONG_PTR = ::std::os::raw::c_longlong;
#[allow(non_camel_case_types)]

View File

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

View File

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

View File

@ -107,7 +107,12 @@ pub fn emit_csharp(
let mut method_list_string = String::new();
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(delegate_method) = build_method_delegate_if_required(
@ -165,7 +170,7 @@ pub fn emit_csharp(
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<_>>()
.join(", ");
@ -189,7 +194,7 @@ pub fn emit_csharp(
let mut structs_string = String::new();
for item in structs {
let name = &item.struct_name;
let name = escape_name(&item.struct_name);
let layout_kind = if item.is_union {
"Explicit"
} else {
@ -220,7 +225,7 @@ pub fn emit_csharp(
};
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 {
let mut digits = digits.clone();
if digits == "0" {

View File

@ -1,31 +1,30 @@
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)]
pub struct Parameter {
pub name: String,
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)]
pub struct FieldMember {
pub name: String,
@ -153,7 +152,7 @@ impl RustType {
.map(|x| {
format!(
"{}: {}",
x.escape_name(),
escape_name(x.name.as_str()),
x.rust_type.to_rust_string(type_path)
)
})
@ -184,7 +183,8 @@ impl RustType {
method_name: &String,
parameter_name: &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 {
// 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
@ -220,9 +220,12 @@ impl RustType {
"bool" => "bool",
"usize" => "nuint", // C# 9.0
"()" => "void",
_ => type_name, // as is
_ => {
temp_string = escape_name(type_name);
temp_string.as_str()
}
};
name
name.to_string()
}
// resolve alias
@ -233,7 +236,13 @@ impl RustType {
// if alias if Option, unwrap.
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 {
convert_type_name(use_type.type_name.as_str()).to_string()
};
@ -421,7 +430,7 @@ pub fn build_method_delegate_if_required(
method_name,
parameter_name,
);
format!("{} {}", cs, p.escape_name())
format!("{} {}", cs, escape_name(p.name.as_str()))
})
.collect::<Vec<_>>()
.join(", ");

View File

@ -12,8 +12,11 @@ namespace CsBindgen
{
const string __DllName = "csbindgen_tests";
[DllImport(__DllName, EntryPoint = "other_1", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void other_1(HogeMoge hoge);
[DllImport(__DllName, EntryPoint = "other_2", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
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)]
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)]
internal unsafe partial struct MyUnion
{
@ -176,12 +197,6 @@ namespace CsBindgen
C = 10,
}
internal enum HogeMoge : int
{
X = 0,
Y = 1,
}
}