Merge pull request #12 from Cysharp/fix-pointer-pointer

Fix pointer pointer
This commit is contained in:
Yoshifumi Kawai 2023-03-08 18:42:12 +09:00 committed by GitHub
commit 5e2911a2dc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 656 additions and 500 deletions

View File

@ -224,7 +224,7 @@ csbindgen::Builder::default()
.input_bindgen_file("src/lz4.rs") // required .input_bindgen_file("src/lz4.rs") // required
.method_filter(|x| { x.starts_with("LZ4") } ) // optional, default: |x| !x.starts_with('_') .method_filter(|x| { x.starts_with("LZ4") } ) // optional, default: |x| !x.starts_with('_')
.rust_method_prefix("csbindgen_") // optional, default: "csbindgen_" .rust_method_prefix("csbindgen_") // optional, default: "csbindgen_"
.rust_file_header("use super::lz4;") // optional, default: "" .rust_file_header("use super::lz4::*;") // optional, default: ""
.rust_method_type_path("lz4") // optional, default: "" .rust_method_type_path("lz4") // optional, default: ""
.csharp_dll_name("lz4") // required .csharp_dll_name("lz4") // required
.csharp_class_name("NativeMethods") // optional, default: NativeMethods .csharp_class_name("NativeMethods") // optional, default: NativeMethods
@ -369,6 +369,8 @@ Rust types will map these C# types.
| `*const T` | `T*` | | `*const T` | `T*` |
| `*mut *mut T` | `T**` | | `*mut *mut T` | `T**` |
| `*const *const T` | `T**` | | `*const *const T` | `T**` |
| `*mut *const T` | `T**` |
| `*const *mut T` | `T**` |
csbindgen is designed to return primitives that do not cause marshalling. It is better to convert from pointers to Span yourself than to do the conversion implicitly and in a black box. This is a recent trend, such as the addition of [DisableRuntimeMarshalling](https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.disableruntimemarshallingattribute) from .NET 7. csbindgen is designed to return primitives that do not cause marshalling. It is better to convert from pointers to Span yourself than to do the conversion implicitly and in a black box. This is a recent trend, such as the addition of [DisableRuntimeMarshalling](https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.disableruntimemarshallingattribute) from .NET 7.
@ -814,7 +816,53 @@ finally
} }
``` ```
C# to Rust would be a bit simpler to send, just pass byte* and length. In Rust, use `std::slice::from_raw_parts` to create slice. Again, the important thing is that memory allocated in Rust must release in Rust and memory allocated in C# must release in C#. C# to Rust would be a bit simpler to send, just pass byte* and length. In Rust, use `std::slice::from_raw_parts` to create slice.
```rust
#[no_mangle]
pub unsafe extern "C" fn csharp_to_rust_string(utf16_str: *const u16, utf16_len: i32) {
let slice = std::slice::from_raw_parts(utf16_str, utf16_len as usize);
let str = String::from_utf16(slice).unwrap();
println!("{}", str);
}
#[no_mangle]
pub unsafe extern "C" fn csharp_to_rust_utf8(utf8_str: *const u8, utf8_len: i32) {
let slice = std::slice::from_raw_parts(utf8_str, utf8_len as usize);
let str = String::from_utf8_unchecked(slice.to_vec());
println!("{}", str);
}
#[no_mangle]
pub unsafe extern "C" fn csharp_to_rust_bytes(bytes: *const u8, len: i32) {
let slice = std::slice::from_raw_parts(bytes, len as usize);
let vec = slice.to_vec();
println!("{:?}", vec);
}
```
```csharp
var str = "foobarbaz:あいうえお"; // JPN(Unicode)
fixed (char* p = str)
{
NativeMethods.csharp_to_rust_string((ushort*)p, str.Length);
}
var str2 = Encoding.UTF8.GetBytes("あいうえお:foobarbaz");
fixed (byte* p = str2)
{
NativeMethods.csharp_to_rust_utf8(p, str2.Length);
}
var bytes = new byte[] { 1, 10, 100, 255 };
fixed (byte* p = bytes)
{
NativeMethods.csharp_to_rust_bytes(p, bytes.Length);
}
```
Again, the important thing is that memory allocated in Rust must release in Rust and memory allocated in C# must release in C#.
Build Tracing Build Tracing
--- ---

View File

@ -61,16 +61,17 @@ fn main() -> Result<(), Box<dyn Error>> {
csbindgen::Builder::default() csbindgen::Builder::default()
.input_extern_file("src/lib.rs") .input_extern_file("src/lib.rs")
.csharp_class_name("LibRust") .csharp_class_name("NativeMethods")
.csharp_dll_name("csbindgen_tests") .csharp_dll_name("csbindgen_tests")
.csharp_use_function_pointer(true) .csharp_use_function_pointer(true)
.generate_csharp_file("../dotnet-sandbox/method_call.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_method_prefix("csbindgen_zstd_") // .rust_method_prefix("csbindgen_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")?;
@ -78,6 +79,7 @@ fn main() -> Result<(), Box<dyn Error>> {
// 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_method_prefix("csbindgen_quiche_") // .rust_method_prefix("csbindgen_quiche_")
// .csharp_class_name("LibQuiche") // .csharp_class_name("LibQuiche")
// .csharp_dll_name("libquiche") // .csharp_dll_name("libquiche")
@ -86,7 +88,9 @@ fn main() -> Result<(), Box<dyn Error>> {
// 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_method_prefix("csbindgen_bullet3_") // .rust_method_prefix("csbindgen_bullet3_")
// .csharp_entry_point_prefix("csbindgen_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")?;

View File

@ -3,7 +3,7 @@
#[allow(unused)] #[allow(unused)]
use ::std::os::raw::*; use ::std::os::raw::*;
use super::bullet3::*;
#[no_mangle] #[no_mangle]
@ -246,10 +246,10 @@ pub unsafe extern "C" fn csbindgen_bullet3_b3GetStatusActualState(
bodyUniqueId: *mut c_int, bodyUniqueId: *mut c_int,
numDegreeOfFreedomQ: *mut c_int, numDegreeOfFreedomQ: *mut c_int,
numDegreeOfFreedomU: *mut c_int, numDegreeOfFreedomU: *mut c_int,
rootLocalInertialFrame: *mut *mut f64, rootLocalInertialFrame: *mut *const f64,
actualStateQ: *mut *mut f64, actualStateQ: *mut *const f64,
actualStateQdot: *mut *mut f64, actualStateQdot: *mut *const f64,
jointReactionForces: *mut *mut f64 jointReactionForces: *mut *const f64
) -> c_int ) -> c_int
{ {
b3GetStatusActualState( b3GetStatusActualState(
@ -271,14 +271,14 @@ pub unsafe extern "C" fn csbindgen_bullet3_b3GetStatusActualState2(
numLinks: *mut c_int, numLinks: *mut c_int,
numDegreeOfFreedomQ: *mut c_int, numDegreeOfFreedomQ: *mut c_int,
numDegreeOfFreedomU: *mut c_int, numDegreeOfFreedomU: *mut c_int,
rootLocalInertialFrame: *mut *mut f64, rootLocalInertialFrame: *mut *const f64,
actualStateQ: *mut *mut f64, actualStateQ: *mut *const f64,
actualStateQdot: *mut *mut f64, actualStateQdot: *mut *const f64,
jointReactionForces: *mut *mut f64, jointReactionForces: *mut *const f64,
linkLocalInertialFrames: *mut *mut f64, linkLocalInertialFrames: *mut *const f64,
jointMotorForces: *mut *mut f64, jointMotorForces: *mut *const f64,
linkStates: *mut *mut f64, linkStates: *mut *const f64,
linkWorldVelocities: *mut *mut f64 linkWorldVelocities: *mut *const f64
) -> c_int ) -> c_int
{ {
b3GetStatusActualState2( b3GetStatusActualState2(
@ -565,7 +565,7 @@ pub unsafe extern "C" fn csbindgen_bullet3_b3GetUserDataInfo(
physClient: b3PhysicsClientHandle, physClient: b3PhysicsClientHandle,
bodyUniqueId: c_int, bodyUniqueId: c_int,
userDataIndex: c_int, userDataIndex: c_int,
keyOut: *mut *mut c_char, keyOut: *mut *const c_char,
userDataIdOut: *mut c_int, userDataIdOut: *mut c_int,
linkIndexOut: *mut c_int, linkIndexOut: *mut c_int,
visualShapeIndexOut: *mut c_int visualShapeIndexOut: *mut c_int

View File

@ -14,6 +14,39 @@ mod lz4;
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
mod lz4_ffi; mod lz4_ffi;
// #[allow(dead_code)]
// #[allow(non_snake_case)]
// #[allow(non_camel_case_types)]
// #[allow(non_upper_case_globals)]
// mod bullet3;
// #[allow(dead_code)]
// #[allow(non_snake_case)]
// #[allow(non_camel_case_types)]
// mod bullet3_ffi;
// #[allow(dead_code)]
// #[allow(non_snake_case)]
// #[allow(non_camel_case_types)]
// #[allow(non_upper_case_globals)]
// mod quiche;
// #[allow(dead_code)]
// #[allow(non_snake_case)]
// #[allow(non_camel_case_types)]
// mod quiche_ffi;
// #[allow(dead_code)]
// #[allow(non_snake_case)]
// #[allow(non_camel_case_types)]
// #[allow(non_upper_case_globals)]
// mod zstd;
// #[allow(dead_code)]
// #[allow(non_snake_case)]
// #[allow(non_camel_case_types)]
// mod zstd_ffi;
#[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)]
@ -34,6 +67,33 @@ pub unsafe extern "C" fn nullpointer_test(p: *const u8) {
}; };
} }
#[no_mangle]
pub unsafe extern "C" fn csharp_to_rust_string(utf16_str: *const u16, utf16_len: i32) {
let slice = std::slice::from_raw_parts(utf16_str, utf16_len as usize);
let str = String::from_utf16(slice).unwrap();
println!("{}", str);
}
#[no_mangle]
pub unsafe extern "C" fn csharp_to_rust_utf8(utf8_str: *const u8, utf8_len: i32) {
let slice = std::slice::from_raw_parts(utf8_str, utf8_len as usize);
let str = String::from_utf8_unchecked(slice.to_vec());
println!("{}", str);
}
#[no_mangle]
pub unsafe extern "C" fn csharp_to_rust_bytes(bytes: *const u8, len: i32) {
let slice = std::slice::from_raw_parts(bytes, len as usize);
let vec = slice.to_vec();
println!("{:?}", vec);
}
#[no_mangle] #[no_mangle]
pub extern "C" fn callback_test(cb: extern "C" fn(a: i32) -> i32) -> i32 { pub extern "C" fn callback_test(cb: extern "C" fn(a: i32) -> i32) -> i32 {
cb(100) cb(100)
@ -46,11 +106,11 @@ pub extern "C" fn csharp_to_rust(cb: extern "C" fn(x: i32, y: i32) -> i32) {
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn rust_to_csharp() -> extern fn(x: i32, y: i32) -> i32 { pub extern "C" fn rust_to_csharp() -> extern "C" fn(x: i32, y: i32) -> i32 {
sum // return rust method sum // return rust method
} }
extern "C" fn sum(x:i32, y:i32) -> i32 { extern "C" fn sum(x: i32, y: i32) -> i32 {
x + y x + y
} }

View File

@ -3,7 +3,7 @@
#[allow(unused)] #[allow(unused)]
use ::std::os::raw::*; use ::std::os::raw::*;
use super::quiche::*;
#[no_mangle] #[no_mangle]
@ -18,7 +18,7 @@ pub unsafe extern "C" fn csbindgen_quiche_quiche_version(
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn csbindgen_quiche_quiche_enable_debug_logging( pub unsafe extern "C" fn csbindgen_quiche_quiche_enable_debug_logging(
cb: Option<extern "C" fn(line: *const c_char, argp: *mut c_void)>, cb: Option<unsafe extern "C" fn(line: *const c_char, argp: *mut c_void)>,
argp: *mut c_void argp: *mut c_void
) -> c_int ) -> c_int
{ {
@ -899,7 +899,7 @@ pub unsafe extern "C" fn csbindgen_quiche_quiche_conn_close(
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn csbindgen_quiche_quiche_conn_trace_id( pub unsafe extern "C" fn csbindgen_quiche_quiche_conn_trace_id(
conn: *const quiche_conn, conn: *const quiche_conn,
out: *mut *mut u8, out: *mut *const u8,
out_len: *mut usize out_len: *mut usize
) )
{ {
@ -913,7 +913,7 @@ pub unsafe extern "C" fn csbindgen_quiche_quiche_conn_trace_id(
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn csbindgen_quiche_quiche_conn_source_id( pub unsafe extern "C" fn csbindgen_quiche_quiche_conn_source_id(
conn: *const quiche_conn, conn: *const quiche_conn,
out: *mut *mut u8, out: *mut *const u8,
out_len: *mut usize out_len: *mut usize
) )
{ {
@ -927,7 +927,7 @@ pub unsafe extern "C" fn csbindgen_quiche_quiche_conn_source_id(
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn csbindgen_quiche_quiche_conn_destination_id( pub unsafe extern "C" fn csbindgen_quiche_quiche_conn_destination_id(
conn: *const quiche_conn, conn: *const quiche_conn,
out: *mut *mut u8, out: *mut *const u8,
out_len: *mut usize out_len: *mut usize
) )
{ {
@ -941,7 +941,7 @@ pub unsafe extern "C" fn csbindgen_quiche_quiche_conn_destination_id(
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn csbindgen_quiche_quiche_conn_application_proto( pub unsafe extern "C" fn csbindgen_quiche_quiche_conn_application_proto(
conn: *const quiche_conn, conn: *const quiche_conn,
out: *mut *mut u8, out: *mut *const u8,
out_len: *mut usize out_len: *mut usize
) )
{ {
@ -955,7 +955,7 @@ pub unsafe extern "C" fn csbindgen_quiche_quiche_conn_application_proto(
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn csbindgen_quiche_quiche_conn_peer_cert( pub unsafe extern "C" fn csbindgen_quiche_quiche_conn_peer_cert(
conn: *const quiche_conn, conn: *const quiche_conn,
out: *mut *mut u8, out: *mut *const u8,
out_len: *mut usize out_len: *mut usize
) )
{ {
@ -969,7 +969,7 @@ pub unsafe extern "C" fn csbindgen_quiche_quiche_conn_peer_cert(
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn csbindgen_quiche_quiche_conn_session( pub unsafe extern "C" fn csbindgen_quiche_quiche_conn_session(
conn: *const quiche_conn, conn: *const quiche_conn,
out: *mut *mut u8, out: *mut *const u8,
out_len: *mut usize out_len: *mut usize
) )
{ {
@ -1065,7 +1065,7 @@ pub unsafe extern "C" fn csbindgen_quiche_quiche_conn_peer_error(
conn: *const quiche_conn, conn: *const quiche_conn,
is_app: *mut bool, is_app: *mut bool,
error_code: *mut u64, error_code: *mut u64,
reason: *mut *mut u8, reason: *mut *const u8,
reason_len: *mut usize reason_len: *mut usize
) -> bool ) -> bool
{ {
@ -1083,7 +1083,7 @@ pub unsafe extern "C" fn csbindgen_quiche_quiche_conn_local_error(
conn: *const quiche_conn, conn: *const quiche_conn,
is_app: *mut bool, is_app: *mut bool,
error_code: *mut u64, error_code: *mut u64,
reason: *mut *mut u8, reason: *mut *const u8,
reason_len: *mut usize reason_len: *mut usize
) -> bool ) -> bool
{ {
@ -1261,7 +1261,7 @@ pub unsafe extern "C" fn csbindgen_quiche_quiche_conn_dgram_send(
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn csbindgen_quiche_quiche_conn_dgram_purge_outgoing( pub unsafe extern "C" fn csbindgen_quiche_quiche_conn_dgram_purge_outgoing(
conn: *mut quiche_conn, conn: *mut quiche_conn,
f: Option<extern "C" fn(arg1: *mut u8, arg2: usize) -> bool> f: Option<unsafe extern "C" fn(arg1: *mut u8, arg2: usize) -> bool>
) )
{ {
quiche_conn_dgram_purge_outgoing( quiche_conn_dgram_purge_outgoing(
@ -1427,7 +1427,7 @@ pub unsafe extern "C" fn csbindgen_quiche_quiche_h3_event_type(
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn csbindgen_quiche_quiche_h3_event_for_each_header( pub unsafe extern "C" fn csbindgen_quiche_quiche_h3_event_for_each_header(
ev: *mut quiche_h3_event, ev: *mut quiche_h3_event,
cb: Option<extern "C" fn(name: *mut u8, name_len: usize, value: *mut u8, value_len: usize, argp: *mut c_void) -> c_int>, cb: Option<unsafe extern "C" fn(name: *mut u8, name_len: usize, value: *mut u8, value_len: usize, argp: *mut c_void) -> c_int>,
argp: *mut c_void argp: *mut c_void
) -> c_int ) -> c_int
{ {
@ -1441,7 +1441,7 @@ pub unsafe extern "C" fn csbindgen_quiche_quiche_h3_event_for_each_header(
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn csbindgen_quiche_quiche_h3_for_each_setting( pub unsafe extern "C" fn csbindgen_quiche_quiche_h3_for_each_setting(
conn: *mut quiche_h3_conn, conn: *mut quiche_h3_conn,
cb: Option<extern "C" fn(identifier: u64, value: u64, argp: *mut c_void) -> c_int>, cb: Option<unsafe extern "C" fn(identifier: u64, value: u64, argp: *mut c_void) -> c_int>,
argp: *mut c_void argp: *mut c_void
) -> c_int ) -> c_int
{ {
@ -1614,7 +1614,7 @@ pub unsafe extern "C" fn csbindgen_quiche_quiche_h3_send_priority_update_for_req
pub unsafe extern "C" fn csbindgen_quiche_quiche_h3_take_last_priority_update( pub unsafe extern "C" fn csbindgen_quiche_quiche_h3_take_last_priority_update(
conn: *mut quiche_h3_conn, conn: *mut quiche_h3_conn,
prioritized_element_id: u64, prioritized_element_id: u64,
cb: Option<extern "C" fn(priority_field_value: *mut u8, priority_field_value_len: u64, argp: *mut c_void) -> c_int>, cb: Option<unsafe extern "C" fn(priority_field_value: *mut u8, priority_field_value_len: u64, argp: *mut c_void) -> c_int>,
argp: *mut c_void argp: *mut c_void
) -> c_int ) -> c_int
{ {

View File

@ -3,7 +3,7 @@
#[allow(unused)] #[allow(unused)]
use ::std::os::raw::*; use ::std::os::raw::*;
use super::zstd::*;
#[no_mangle] #[no_mangle]

View File

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

View File

@ -258,8 +258,7 @@ pub fn reduce_enum(
fn parse_type(t: &syn::Type) -> RustType { fn parse_type(t: &syn::Type) -> RustType {
match t { match t {
syn::Type::Ptr(t) => { syn::Type::Ptr(t) => {
let has_const = t.const_token.is_some(); let has_const = t.const_token.is_some(); // not is has_mut
// let has_mut = t.mutability.is_some();
if let syn::Type::Path(path) = &*t.elem { if let syn::Type::Path(path) = &*t.elem {
return RustType { return RustType {
@ -272,13 +271,18 @@ fn parse_type(t: &syn::Type) -> RustType {
}; };
} else if let syn::Type::Ptr(t) = &*t.elem { } else if let syn::Type::Ptr(t) = &*t.elem {
if let syn::Type::Path(path) = &*t.elem { if let syn::Type::Path(path) = &*t.elem {
let has_const2 = t.const_token.is_some();
let pointer_type = match (has_const, has_const2) {
(true, true) => PointerType::ConstPointerPointer,
(true, false) => PointerType::ConstMutPointerPointer,
(false, true) => PointerType::MutConstPointerPointer,
(false, false) => PointerType::MutPointerPointer,
};
return RustType { return RustType {
type_name: path.path.segments.last().unwrap().ident.to_string(), type_name: path.path.segments.last().unwrap().ident.to_string(),
type_kind: TypeKind::Pointer(if has_const { type_kind: TypeKind::Pointer(pointer_type),
PointerType::ConstPointerPointer
} else {
PointerType::MutPointerPointer
}),
}; };
} }
} }
@ -345,7 +349,7 @@ fn parse_type(t: &syn::Type) -> RustType {
}; };
return RustType { return RustType {
type_name: "extern \"C\" fn".to_string(), type_name: "unsafe extern \"C\" fn".to_string(),
type_kind: TypeKind::Function(parameters, ret), type_kind: TypeKind::Function(parameters, ret),
}; };
} }

View File

@ -77,6 +77,8 @@ pub enum PointerType {
MutPointer, MutPointer,
ConstPointerPointer, ConstPointerPointer,
MutPointerPointer, MutPointerPointer,
ConstMutPointerPointer,
MutConstPointerPointer
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -103,6 +105,8 @@ impl RustType {
MutPointer => sb.push_str("*mut"), MutPointer => sb.push_str("*mut"),
ConstPointerPointer => sb.push_str("*const *const"), ConstPointerPointer => sb.push_str("*const *const"),
MutPointerPointer => sb.push_str("*mut *mut"), MutPointerPointer => sb.push_str("*mut *mut"),
ConstMutPointerPointer =>sb.push_str("*const *mut"),
MutConstPointerPointer =>sb.push_str("*mut *const"),
}; };
} }
@ -305,12 +309,13 @@ impl RustType {
sb.push_str(convert_type_name(use_type.type_name.as_str())); sb.push_str(convert_type_name(use_type.type_name.as_str()));
if use_alias { if use_alias {
use PointerType::*;
if let TypeKind::Pointer(p) = &use_type.type_kind { if let TypeKind::Pointer(p) = &use_type.type_kind {
match p { match p {
PointerType::MutPointer | PointerType::ConstPointer => { MutPointer | ConstPointer => {
sb.push('*'); sb.push('*');
} }
PointerType::MutPointerPointer | PointerType::ConstPointerPointer => { MutPointerPointer | ConstPointerPointer | MutConstPointerPointer | ConstMutPointerPointer => {
sb.push_str("**"); sb.push_str("**");
} }
} }
@ -318,11 +323,12 @@ impl RustType {
} }
if let TypeKind::Pointer(p) = &self.type_kind { if let TypeKind::Pointer(p) = &self.type_kind {
use PointerType::*;
match p { match p {
PointerType::MutPointer | PointerType::ConstPointer => { MutPointer | ConstPointer => {
sb.push('*'); sb.push('*');
} }
PointerType::MutPointerPointer | PointerType::ConstPointerPointer => { MutPointerPointer | ConstPointerPointer | MutConstPointerPointer | ConstMutPointerPointer => {
sb.push_str("**"); sb.push_str("**");
} }
} }

View File

@ -8,7 +8,7 @@ using System.Runtime.InteropServices;
namespace CsBindgen namespace CsBindgen
{ {
internal static unsafe partial class LibRust internal static unsafe partial class NativeMethods
{ {
const string __DllName = "csbindgen_tests"; const string __DllName = "csbindgen_tests";
@ -21,6 +21,15 @@ namespace CsBindgen
[DllImport(__DllName, EntryPoint = "nullpointer_test", CallingConvention = CallingConvention.Cdecl)] [DllImport(__DllName, EntryPoint = "nullpointer_test", CallingConvention = CallingConvention.Cdecl)]
public static extern void nullpointer_test(byte* p); public static extern void nullpointer_test(byte* p);
[DllImport(__DllName, EntryPoint = "csharp_to_rust_string", CallingConvention = CallingConvention.Cdecl)]
public static extern void csharp_to_rust_string(ushort* utf16_str, int utf16_len);
[DllImport(__DllName, EntryPoint = "csharp_to_rust_utf8", CallingConvention = CallingConvention.Cdecl)]
public static extern void csharp_to_rust_utf8(byte* utf8_str, int utf8_len);
[DllImport(__DllName, EntryPoint = "csharp_to_rust_bytes", CallingConvention = CallingConvention.Cdecl)]
public static extern void csharp_to_rust_bytes(byte* bytes, int len);
[DllImport(__DllName, EntryPoint = "callback_test", CallingConvention = CallingConvention.Cdecl)] [DllImport(__DllName, EntryPoint = "callback_test", CallingConvention = CallingConvention.Cdecl)]
public static extern int callback_test(delegate* unmanaged[Cdecl]<int, int> cb); public static extern int callback_test(delegate* unmanaged[Cdecl]<int, int> cb);

View File

@ -15,19 +15,44 @@ unsafe
{ {
LibRust.alias_test1(null);
//LibRust.call_bindgen_lz4(); //NativeMethods.call_bindgen_lz4();
var str = "foobarbaz:あいうえお"; // JPN(Unicode)
fixed (char* p = str)
{
NativeMethods.csharp_to_rust_string((ushort*)p, str.Length);
}
var str2 = Encoding.UTF8.GetBytes("あいうえお:foobarbaz");
fixed (byte* p = str2)
{
NativeMethods.csharp_to_rust_utf8(p, str2.Length);
}
var bytes = new byte[] { 1, 10, 100, 255 };
fixed (byte* p = bytes)
{
NativeMethods.csharp_to_rust_bytes(p, bytes.Length);
}
//NativeMethods.csharp_to_rust_utf8
//NativeMethods.alias_test1(null);
// C# -> Rust, pass static UnmanagedCallersOnly method with `&` // C# -> Rust, pass static UnmanagedCallersOnly method with `&`
[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })]
static int Sum(int x, int y) => x + y; static int Sum(int x, int y) => x + y;
LibRust.csharp_to_rust(&Sum); NativeMethods.csharp_to_rust(&Sum);
// Rust -> C#, get typed delegate* // Rust -> C#, get typed delegate*
var f = LibRust.rust_to_csharp(); var f = NativeMethods.rust_to_csharp();
var v = f(20, 30); var v = f(20, 30);
Console.WriteLine(v); // 50 Console.WriteLine(v); // 50
@ -49,18 +74,18 @@ unsafe
//Console.WriteLine(cc); //Console.WriteLine(cc);
var context = LibRust.create_context(); // var context = LibRust.create_context();
// do anything... // // do anything...
LibRust.delete_context(context); // LibRust.delete_context(context);
var ctx = LibRust.create_counter_context(); // ctx = void* //var ctx = LibRust.create_counter_context(); // ctx = void*
LibRust.insert_counter_context(ctx, 10); //LibRust.insert_counter_context(ctx, 10);
LibRust.insert_counter_context(ctx, 20); //LibRust.insert_counter_context(ctx, 20);
LibRust.delete_counter_context(ctx); //LibRust.delete_counter_context(ctx);
//LibRust.insert_counter_context(ctx, 20); //LibRust.insert_counter_context(ctx, 20);
//LibRust.insert_counter_context(ctx, 30); //LibRust.insert_counter_context(ctx, 30);

File diff suppressed because it is too large Load Diff