mirror of
https://github.com/Sarsoo/csbindgen.git
synced 2024-12-22 22:46:26 +00:00
ReadMe 1.7.0
multi input_bindgen_file support bitflags crate support tuple struct support unit struct new csharp_disable_emit_dll_name option GroupedNativeMethods code generator
This commit is contained in:
parent
11c68c818d
commit
e4b25c3d73
@ -141,13 +141,19 @@ using System.Runtime.InteropServices;
|
|||||||
|
|
||||||
static string ConvertMethodName(string typeName, string methodName, string removePrefix, string removeSuffix, bool removeUntilTypeName, bool fixMethodName)
|
static string ConvertMethodName(string typeName, string methodName, string removePrefix, string removeSuffix, bool removeUntilTypeName, bool fixMethodName)
|
||||||
{
|
{
|
||||||
|
if (!fixMethodName) return methodName;
|
||||||
|
|
||||||
if (removeUntilTypeName)
|
if (removeUntilTypeName)
|
||||||
{
|
{
|
||||||
var match = methodName.IndexOf(typeName);
|
var match = methodName.IndexOf(typeName);
|
||||||
if (match != -1)
|
if (match != -1)
|
||||||
{
|
{
|
||||||
methodName = methodName.Substring(match + typeName.Length);
|
var substringMethodName = methodName.Substring(match + typeName.Length);
|
||||||
goto FINAL;
|
if (substringMethodName.Trim(' ', '_') != "")
|
||||||
|
{
|
||||||
|
methodName = substringMethodName;
|
||||||
|
goto FINAL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,18 +169,15 @@ using System.Runtime.InteropServices;
|
|||||||
methodName = Regex.Replace(methodName, $"{Regex.Escape(removeSuffix)}$", "");
|
methodName = Regex.Replace(methodName, $"{Regex.Escape(removeSuffix)}$", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
methodName = methodName.Trim('_');
|
methodName = methodName.Trim('_', ' ');
|
||||||
|
|
||||||
if (fixMethodName)
|
var split = methodName.Split('_');
|
||||||
|
methodName = string.Concat(split.Select(x =>
|
||||||
{
|
{
|
||||||
var split = methodName.Split('_');
|
if (x.Length == 0) return x;
|
||||||
methodName = string.Concat(split.Select(x =>
|
if (x.Length == 1) return char.ToUpper(x[0]).ToString();
|
||||||
{
|
return char.ToUpper(x[0]) + x.Substring(1);
|
||||||
if (x.Length == 0) return x;
|
}));
|
||||||
if (x.Length == 1) return char.ToUpper(x[0]).ToString();
|
|
||||||
return char.ToUpper(x[0]) + x.Substring(1);
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
return methodName;
|
return methodName;
|
||||||
}
|
}
|
||||||
|
164
README.md
164
README.md
@ -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.6.0"
|
csbindgen = "1.7.0"
|
||||||
```
|
```
|
||||||
|
|
||||||
### Rust to C#.
|
### Rust to C#.
|
||||||
@ -163,6 +163,7 @@ csbindgen::Builder::default()
|
|||||||
.csharp_entry_point_prefix("") // optional, default: ""
|
.csharp_entry_point_prefix("") // optional, default: ""
|
||||||
.csharp_method_prefix("") // optional, default: ""
|
.csharp_method_prefix("") // optional, default: ""
|
||||||
.csharp_use_function_pointer(true) // optional, default: true
|
.csharp_use_function_pointer(true) // optional, default: true
|
||||||
|
.csharp_disable_emit_dll_name(false) // optional, default: false
|
||||||
.csharp_dll_name_if("UNITY_IOS && !UNITY_EDITOR", "__Internal") // optional, default: ""
|
.csharp_dll_name_if("UNITY_IOS && !UNITY_EDITOR", "__Internal") // optional, default: ""
|
||||||
.generate_csharp_file("../dotnet-sandbox/NativeMethods.cs") // required
|
.generate_csharp_file("../dotnet-sandbox/NativeMethods.cs") // required
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -192,7 +193,9 @@ 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.
|
`csharp_disable_emit_dll_name` is optional, if set to true then don't emit `const string __DllName`. It is useful for generate same class-name from different builder.
|
||||||
|
|
||||||
|
`input_extern_file` and `input_bindgen_file` allow mulitple call, if you need to add dependent struct, use this.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
csbindgen::Builder::default()
|
csbindgen::Builder::default()
|
||||||
@ -341,6 +344,56 @@ internal static unsafe partial class NativeMethods
|
|||||||
|
|
||||||
If Unity, configure Platform settings in each native library's inspector.
|
If Unity, configure Platform settings in each native library's inspector.
|
||||||
|
|
||||||
|
Grouping Extension Methods
|
||||||
|
---
|
||||||
|
In an object-oriented style, it is common to create methods that take a pointer to a state (this) as their first argument. With csbindgen, you can group these methods using extension methods by specifying a Source Generator on the C# side.
|
||||||
|
|
||||||
|
Install csbindgen from NuGet, and specify [GroupedNativeMethods] for the partial class of the generated extension methods.
|
||||||
|
|
||||||
|
> PM> Install-Package [csbindgen](https://www.nuget.org/packages/csbindgen)
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// create new file and write same type-name with same namespace
|
||||||
|
namespace CsBindgen
|
||||||
|
{
|
||||||
|
// append `GroupedNativeMethods` attribute
|
||||||
|
[GroupedNativeMethods()]
|
||||||
|
internal static unsafe partial class NativeMethods
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// original methods
|
||||||
|
[DllImport(__DllName, EntryPoint = "counter_context_insert", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
|
public static extern void counter_context_insert(counter_context* context, int value);
|
||||||
|
|
||||||
|
// generated methods
|
||||||
|
public static void Insert(this ref global::CsBindgen.counter_context @context, int @value)
|
||||||
|
|
||||||
|
// ----
|
||||||
|
|
||||||
|
counter_context* context = NativeMethods.create_counter_context();
|
||||||
|
|
||||||
|
// standard style
|
||||||
|
NativeMethods.counter_context_insert(context, 10);
|
||||||
|
|
||||||
|
// generated style
|
||||||
|
context->Insert(10);
|
||||||
|
```
|
||||||
|
|
||||||
|
`GroupedNativeMethods` has four configuration parameters.
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public GroupedNativeMethodsAttribute(
|
||||||
|
string removePrefix = "",
|
||||||
|
string removeSuffix = "",
|
||||||
|
bool removeUntilTypeName = true,
|
||||||
|
bool fixMethodName = true)
|
||||||
|
```
|
||||||
|
|
||||||
|
`removeUntilTypeName` will remove until find type-name in method-name. For example `foo_counter_context_insert(countext_context* foo)` -> `Insert`. As a result, it is recommended to use a naming convention where the same type name is placed immediately before the verb.
|
||||||
|
|
||||||
Type Marshalling
|
Type Marshalling
|
||||||
---
|
---
|
||||||
@ -383,6 +436,7 @@ Rust types will map these C# types.
|
|||||||
| `#[repr(C)]Struct` | `[StructLayout(LayoutKind.Sequential)]Struct` |
|
| `#[repr(C)]Struct` | `[StructLayout(LayoutKind.Sequential)]Struct` |
|
||||||
| `#[repr(C)]Union` | `[StructLayout(LayoutKind.Explicit)]Struct` |
|
| `#[repr(C)]Union` | `[StructLayout(LayoutKind.Explicit)]Struct` |
|
||||||
| `#[repr(u*/i*)]Enum` | `Enum` |
|
| `#[repr(u*/i*)]Enum` | `Enum` |
|
||||||
|
| [bitflags!](https://crates.io/crates/bitflags) | `[Flags]Enum` |
|
||||||
| `extern "C" fn` | `delegate* unmanaged[Cdecl]<>` or `Func<>/Action<>` |
|
| `extern "C" fn` | `delegate* unmanaged[Cdecl]<>` or `Func<>/Action<>` |
|
||||||
| `Option<extern "C" fn>` | `delegate* unmanaged[Cdecl]<>` or `Func<>/Action<>` |
|
| `Option<extern "C" fn>` | `delegate* unmanaged[Cdecl]<>` or `Func<>/Action<>` |
|
||||||
| `*mut T` | `T*` |
|
| `*mut T` | `T*` |
|
||||||
@ -442,6 +496,62 @@ internal unsafe partial struct MyVector3
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Also supports tuple struct, it will generate `Item*` fields in C#.
|
||||||
|
|
||||||
|
```
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct MyIntVec3(i32, i32, i32);
|
||||||
|
```
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal unsafe partial struct MyIntVec3
|
||||||
|
{
|
||||||
|
public int Item1;
|
||||||
|
public int Item2;
|
||||||
|
public int Item3;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
It also supports unit struct, but there is no C# struct that is synonymous with Rust's unit struct (0 byte), so it cannot be materialized. Instead of using void*, it is recommended to use typed pointers.
|
||||||
|
|
||||||
|
```
|
||||||
|
// 0-byte
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct CounterContext;
|
||||||
|
```
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// 1-byte
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal unsafe partial struct CounterContext
|
||||||
|
{
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```rust
|
||||||
|
// recommend to use as pointer, in C#, holds CounterContext*
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn create_counter_context() -> *mut CounterContext {
|
||||||
|
let ctx = Box::new(InternalCounterContext {
|
||||||
|
set: HashSet::new(),
|
||||||
|
});
|
||||||
|
Box::into_raw(ctx) as *mut CounterContext
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn counter_context_insert(context: *mut CounterContext, value: i32) {
|
||||||
|
let mut counter = Box::from_raw(context as *mut InternalCounterContext);
|
||||||
|
counter.set.insert(value);
|
||||||
|
Box::into_raw(counter);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn destroy_counter_context(context: *mut CounterContext) {
|
||||||
|
_ = Box::from_raw(context as *mut InternalCounterContext);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Union
|
### Union
|
||||||
|
|
||||||
`Union` will generate `[FieldOffset(0)]` struct.
|
`Union` will generate `[FieldOffset(0)]` struct.
|
||||||
@ -492,6 +602,34 @@ internal enum ByteTest : byte
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### bitflags Enum
|
||||||
|
|
||||||
|
csbindgen supports [bitflags](https://crates.io/crates/bitflags) crate.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
bitflags! {
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
struct EnumFlags: u32 {
|
||||||
|
const A = 0b00000001;
|
||||||
|
const B = 0b00000010;
|
||||||
|
const C = 0b00000100;
|
||||||
|
const ABC = Self::A.bits() | Self::B.bits() | Self::C.bits();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
[Flags]
|
||||||
|
internal enum EnumFlags : uint
|
||||||
|
{
|
||||||
|
A = 0b00000001,
|
||||||
|
B = 0b00000010,
|
||||||
|
C = 0b00000100,
|
||||||
|
ABC = A | B | C,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Function
|
### Function
|
||||||
|
|
||||||
You can receive, return function to/from C#.
|
You can receive, return function to/from C#.
|
||||||
@ -591,40 +729,42 @@ NativeMethods.delete_context(context);
|
|||||||
|
|
||||||
You can also pass memory allocated by C# to Rust (use `fixed` or `GCHandle.Alloc(Pinned)`). The important thing is that memory allocated in Rust must release in Rust and memory allocated in C# must release in C#.
|
You can also pass memory allocated by C# to Rust (use `fixed` or `GCHandle.Alloc(Pinned)`). The important thing is that memory allocated in Rust must release in Rust and memory allocated in C# must release in C#.
|
||||||
|
|
||||||
If you want to pass a non FFI Safe struct, cast it to `*mut c_void`. Then C# will treat it as a `void*`. csbindgen does not support Opaque Type.
|
If you want to pass a non FFI Safe struct, cast it to `*mut c_void`. Then C# will treat it as a `void*`. csbindgen does not support Opaque Type. Additionally, by returning a unit struct instead of `c_void`, you can create a typed handler.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn create_counter_context() -> *mut c_void {
|
pub extern "C" fn create_counter_context() -> *mut CounterContext {
|
||||||
let ctx = Box::new(CounterContext {
|
let ctx = Box::new(InternalCounterContext {
|
||||||
set: HashSet::new(),
|
set: HashSet::new(),
|
||||||
});
|
});
|
||||||
Box::into_raw(ctx) as *mut c_void
|
Box::into_raw(ctx) as *mut c_void
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn insert_counter_context(context: *mut c_void, value: i32) {
|
pub unsafe extern "C" fn insert_counter_context(context: *mut CounterContext, value: i32) {
|
||||||
let mut counter = Box::from_raw(context as *mut CounterContext);
|
let mut counter = Box::from_raw(context as *mut InternalCounterContext);
|
||||||
counter.set.insert(value);
|
counter.set.insert(value);
|
||||||
Box::into_raw(counter);
|
Box::into_raw(counter);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn delete_counter_context(context: *mut c_void) {
|
pub unsafe extern "C" fn delete_counter_context(context: *mut CounterContext) {
|
||||||
let counter = Box::from_raw(context as *mut CounterContext);
|
let counter = Box::from_raw(context as *mut InternalCounterContext);
|
||||||
for value in counter.set.iter() {
|
for value in counter.set.iter() {
|
||||||
println!("counter value: {}", value)
|
println!("counter value: {}", value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct CounterContext {
|
pub struct CounterContext;
|
||||||
|
|
||||||
|
// no repr(C)
|
||||||
|
pub struct InternalCounterContext {
|
||||||
pub set: HashSet<i32>,
|
pub set: HashSet<i32>,
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// in C#, ctx = void*
|
|
||||||
var ctx = NativeMethods.create_counter_context();
|
var ctx = NativeMethods.create_counter_context();
|
||||||
|
|
||||||
NativeMethods.insert_counter_context(ctx, 10);
|
NativeMethods.insert_counter_context(ctx, 10);
|
||||||
@ -633,6 +773,8 @@ NativeMethods.insert_counter_context(ctx, 20);
|
|||||||
NativeMethods.delete_counter_context(ctx);
|
NativeMethods.delete_counter_context(ctx);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
In this case, recommed to use with [Grouping Extension Methods](#grouping-extension-methods).
|
||||||
|
|
||||||
If you want to pass null-pointer, in rust side, convert to Option by `as_ref()`.
|
If you want to pass null-pointer, in rust side, convert to Option by `as_ref()`.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
|
1
csbindgen-tests/Cargo.toml
vendored
1
csbindgen-tests/Cargo.toml
vendored
@ -14,6 +14,7 @@ path = "src/lib.rs"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
csbindgen = { path = "../csbindgen" }
|
csbindgen = { path = "../csbindgen" }
|
||||||
|
bitflags = "2.1.0"
|
||||||
# physx-sys = "0.11.0"
|
# physx-sys = "0.11.0"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
|
1
csbindgen-tests/build.rs
vendored
1
csbindgen-tests/build.rs
vendored
@ -64,7 +64,6 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
// .csharp_use_function_pointer(true)
|
// .csharp_use_function_pointer(true)
|
||||||
.generate_to_file("src/lz4_ffi.rs", "../dotnet-sandbox/lz4_bindgen.cs")
|
.generate_to_file("src/lz4_ffi.rs", "../dotnet-sandbox/lz4_bindgen.cs")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|
||||||
// csbindgen::Builder::default()
|
// csbindgen::Builder::default()
|
||||||
// .input_bindgen_file("src/sqlite3.rs")
|
// .input_bindgen_file("src/sqlite3.rs")
|
||||||
|
86
csbindgen-tests/src/lib.rs
vendored
86
csbindgen-tests/src/lib.rs
vendored
@ -1,6 +1,6 @@
|
|||||||
use std::{
|
use std::{
|
||||||
collections::HashSet,
|
collections::HashSet,
|
||||||
ffi::{c_char, c_long, c_ulong, c_void, CString},
|
ffi::{c_char, c_long, c_ulong, CString},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@ -66,8 +66,6 @@ mod lz4_ffi;
|
|||||||
// println!("{:?}", hoge);
|
// println!("{:?}", hoge);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// #[no_mangle]
|
// #[no_mangle]
|
||||||
// pub extern "C" fn string_char(str: char) {
|
// pub extern "C" fn string_char(str: char) {
|
||||||
// println!("{}", str);
|
// println!("{}", str);
|
||||||
@ -100,43 +98,46 @@ pub struct JPH_ContactManifold {
|
|||||||
pub extern "C" fn JPH_PruneContactPoints(
|
pub extern "C" fn JPH_PruneContactPoints(
|
||||||
ioContactPointsOn1: *mut JPH_ContactPoints,
|
ioContactPointsOn1: *mut JPH_ContactPoints,
|
||||||
ioContactPointsOn2: *mut JPH_ContactManifold,
|
ioContactPointsOn2: *mut JPH_ContactManifold,
|
||||||
)
|
) {
|
||||||
{
|
|
||||||
todo!();
|
todo!();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use bitflags::bitflags;
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
struct EnumFlags: u32 {
|
||||||
|
const A = 0b00000001;
|
||||||
|
const B = 0b00000010;
|
||||||
|
const C = 0b00000100;
|
||||||
|
const ABC = Self::A.bits() | Self::B.bits() | Self::C.bits();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// my comment!
|
/// my comment!
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn comment_one() {
|
extern "C" fn comment_one(_flags: EnumFlags) {}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Multiline Comments
|
/// Multiline Comments
|
||||||
/// # GOTO
|
/// # GOTO
|
||||||
/// Here
|
/// Here
|
||||||
/// Foo
|
/// Foo
|
||||||
/// Bar
|
/// Bar
|
||||||
///
|
///
|
||||||
/// TO
|
/// TO
|
||||||
///
|
///
|
||||||
/// ZZZ
|
/// ZZZ
|
||||||
pub extern "C" fn long_jpn_comment() {
|
pub extern "C" fn long_jpn_comment() {}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct my_int_vec3(i32,i32,i32);
|
pub struct my_int_vec3(i32, i32, i32);
|
||||||
|
|
||||||
pub extern "C" fn use_vec3(_v3: my_int_vec3) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
pub extern "C" fn use_vec3(_v3: my_int_vec3) {}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct NfcCard {
|
pub struct NfcCard {
|
||||||
pub delegate: unsafe extern "C" fn(ByteArray) -> ByteArray
|
pub delegate: unsafe extern "C" fn(ByteArray) -> ByteArray,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@ -150,11 +151,11 @@ pub struct ByteArray {
|
|||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct event {
|
pub struct event {
|
||||||
pub a: i32
|
pub a: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn event(event: event ) {
|
pub extern "C" fn event(event: event) {
|
||||||
println!("{:?}", event);
|
println!("{:?}", event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -283,27 +284,30 @@ pub extern "C" fn my_add(x: i32, y: i32) -> i32 {
|
|||||||
x + y
|
x + y
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct CounterContext;
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn create_counter_context() -> *mut c_void {
|
pub extern "C" fn create_counter_context() -> *mut CounterContext {
|
||||||
let ctx = Box::new(CounterContext {
|
let ctx = Box::new(InternalCounterContext {
|
||||||
set: HashSet::new(),
|
set: HashSet::new(),
|
||||||
});
|
});
|
||||||
Box::into_raw(ctx) as *mut c_void
|
Box::into_raw(ctx) as *mut CounterContext
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn insert_counter_context(context: *mut c_void, value: i32) {
|
pub unsafe extern "C" fn counter_context_insert(context: *mut CounterContext, value: i32) {
|
||||||
let mut counter = Box::from_raw(context as *mut CounterContext);
|
let mut counter = Box::from_raw(context as *mut InternalCounterContext);
|
||||||
counter.set.insert(value);
|
counter.set.insert(value);
|
||||||
Box::into_raw(counter);
|
Box::into_raw(counter);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn delete_counter_context(context: *mut c_void) {
|
pub unsafe extern "C" fn destroy_counter_context(context: *mut CounterContext) {
|
||||||
let counter = Box::from_raw(context as *mut CounterContext);
|
_ = Box::from_raw(context as *mut InternalCounterContext);
|
||||||
for value in counter.set.iter() {
|
// for value in counter.set.iter() {
|
||||||
println!("counter value: {}", value)
|
// println!("counter value: {}", value)
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@ -329,8 +333,8 @@ pub struct MyVector3 {
|
|||||||
pub z: f32,
|
pub z: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
// not repr(C)
|
||||||
pub struct CounterContext {
|
pub struct InternalCounterContext {
|
||||||
pub set: HashSet<i32>,
|
pub set: HashSet<i32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -472,7 +476,6 @@ fn build_test() {
|
|||||||
// .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("csbindgen-tests/src/physx/physx_generated.rs")
|
.input_bindgen_file("csbindgen-tests/src/physx/physx_generated.rs")
|
||||||
.input_bindgen_file("csbindgen-tests/src/physx/x86_64-pc-windows-msvc/structgen.rs")
|
.input_bindgen_file("csbindgen-tests/src/physx/x86_64-pc-windows-msvc/structgen.rs")
|
||||||
@ -567,12 +570,11 @@ pub struct CallbackTable {
|
|||||||
pub foobar: extern "C" fn(i: i32) -> i32,
|
pub foobar: extern "C" fn(i: i32) -> i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// fn run_physix(){
|
// fn run_physix(){
|
||||||
// unsafe {
|
// unsafe {
|
||||||
// let foundation = physx_create_foundation();
|
// let foundation = physx_create_foundation();
|
||||||
// let physics = physx_create_physics(foundation);
|
// let physics = physx_create_physics(foundation);
|
||||||
|
|
||||||
// let mut scene_desc = PxSceneDesc_new(PxPhysics_getTolerancesScale(physics));
|
// let mut scene_desc = PxSceneDesc_new(PxPhysics_getTolerancesScale(physics));
|
||||||
// scene_desc.gravity = PxVec3 {
|
// scene_desc.gravity = PxVec3 {
|
||||||
// x: 0.0,
|
// x: 0.0,
|
||||||
@ -580,8 +582,6 @@ pub struct CallbackTable {
|
|||||||
// z: 0.0,
|
// z: 0.0,
|
||||||
// };
|
// };
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// let dispatcher = phys_PxDefaultCpuDispatcherCreate(
|
// let dispatcher = phys_PxDefaultCpuDispatcherCreate(
|
||||||
// 1,
|
// 1,
|
||||||
// null_mut(),
|
// null_mut(),
|
||||||
@ -590,9 +590,9 @@ pub struct CallbackTable {
|
|||||||
// );
|
// );
|
||||||
// scene_desc.cpuDispatcher = dispatcher.cast();
|
// scene_desc.cpuDispatcher = dispatcher.cast();
|
||||||
// scene_desc.filterShader = get_default_simulation_filter_shader();
|
// scene_desc.filterShader = get_default_simulation_filter_shader();
|
||||||
|
|
||||||
// let scene = PxPhysics_createScene_mut(physics, &scene_desc);
|
// let scene = PxPhysics_createScene_mut(physics, &scene_desc);
|
||||||
|
|
||||||
// // Your physics simulation goes here
|
// // Your physics simulation goes here
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::{alias_map::AliasMap, builder::BindgenOptions, field_map::FieldMap, type_meta::*};
|
use crate::{alias_map::AliasMap, builder::BindgenOptions, field_map::FieldMap, type_meta::*};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use std::{collections::HashSet};
|
use std::collections::HashSet;
|
||||||
use syn::{ForeignItem, Item, Pat, ReturnType};
|
use syn::{ForeignItem, Item, Pat, ReturnType};
|
||||||
|
|
||||||
enum FnItem {
|
enum FnItem {
|
||||||
@ -164,6 +164,14 @@ pub fn collect_struct(ast: &syn::File, result: &mut Vec<RustStruct>) {
|
|||||||
fields,
|
fields,
|
||||||
is_union: false,
|
is_union: false,
|
||||||
});
|
});
|
||||||
|
} else if let syn::Fields::Unit = &t.fields {
|
||||||
|
let struct_name = t.ident.to_string();
|
||||||
|
let fields: Vec<FieldMember> = Vec::new();
|
||||||
|
result.push(RustStruct {
|
||||||
|
struct_name,
|
||||||
|
fields,
|
||||||
|
is_union: false,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -249,7 +257,7 @@ pub fn collect_enum(ast: &syn::File, result: &mut Vec<RustEnum>) {
|
|||||||
|
|
||||||
let token_string = t.mac.tokens.to_string();
|
let token_string = t.mac.tokens.to_string();
|
||||||
|
|
||||||
let match1 = Regex::new("pub struct ([^ ]+) : ([^ ]+)")
|
let match1 = Regex::new("struct ([^ ]+) : ([^ ]+)")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.captures(token_string.as_str())
|
.captures(token_string.as_str())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -269,6 +277,7 @@ pub fn collect_enum(ast: &syn::File, result: &mut Vec<RustEnum>) {
|
|||||||
.as_str()
|
.as_str()
|
||||||
.to_string()
|
.to_string()
|
||||||
.replace("Self :: ", "")
|
.replace("Self :: ", "")
|
||||||
|
.replace(" . bits ()", "")
|
||||||
.replace(" . bits", "")
|
.replace(" . bits", "")
|
||||||
.trim()
|
.trim()
|
||||||
.to_string(),
|
.to_string(),
|
||||||
|
26
dotnet-sandbox/NativeMethods.cs
vendored
26
dotnet-sandbox/NativeMethods.cs
vendored
@ -18,7 +18,7 @@ namespace CsBindgen
|
|||||||
|
|
||||||
/// <summary>my comment!</summary>
|
/// <summary>my comment!</summary>
|
||||||
[DllImport(__DllName, EntryPoint = "comment_one", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(__DllName, EntryPoint = "comment_one", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern void comment_one();
|
public static extern void comment_one(EnumFlags _flags);
|
||||||
|
|
||||||
/// <summary>Multiline Comments # GOTO Here Foo Bar TO ZZZ</summary>
|
/// <summary>Multiline Comments # GOTO Here Foo Bar TO ZZZ</summary>
|
||||||
[DllImport(__DllName, EntryPoint = "long_jpn_comment", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(__DllName, EntryPoint = "long_jpn_comment", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
@ -91,13 +91,13 @@ namespace CsBindgen
|
|||||||
public static extern int my_add(int x, int y);
|
public static extern int my_add(int x, int y);
|
||||||
|
|
||||||
[DllImport(__DllName, EntryPoint = "create_counter_context", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(__DllName, EntryPoint = "create_counter_context", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern void* create_counter_context();
|
public static extern counter_context* create_counter_context();
|
||||||
|
|
||||||
[DllImport(__DllName, EntryPoint = "insert_counter_context", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(__DllName, EntryPoint = "counter_context_insert", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern void insert_counter_context(void* context, int value);
|
public static extern void counter_context_insert(counter_context* context, int value);
|
||||||
|
|
||||||
[DllImport(__DllName, EntryPoint = "delete_counter_context", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(__DllName, EntryPoint = "destroy_counter_context", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern void delete_counter_context(void* context);
|
public static extern void destroy_counter_context(counter_context* context);
|
||||||
|
|
||||||
[DllImport(__DllName, EntryPoint = "pass_vector3", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(__DllName, EntryPoint = "pass_vector3", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern void pass_vector3(MyVector3 v3);
|
public static extern void pass_vector3(MyVector3 v3);
|
||||||
@ -186,6 +186,11 @@ namespace CsBindgen
|
|||||||
public int a;
|
public int a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal unsafe partial struct counter_context
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Explicit)]
|
[StructLayout(LayoutKind.Explicit)]
|
||||||
internal unsafe partial struct MyUnion
|
internal unsafe partial struct MyUnion
|
||||||
{
|
{
|
||||||
@ -225,6 +230,15 @@ namespace CsBindgen
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
internal enum EnumFlags : uint
|
||||||
|
{
|
||||||
|
A = 0b00000001,
|
||||||
|
B = 0b00000010,
|
||||||
|
C = 0b00000100,
|
||||||
|
ABC = A | B | C,
|
||||||
|
}
|
||||||
|
|
||||||
internal enum IntEnumTest : sbyte
|
internal enum IntEnumTest : sbyte
|
||||||
{
|
{
|
||||||
A = 1,
|
A = 1,
|
||||||
|
14
dotnet-sandbox/Program.cs
vendored
14
dotnet-sandbox/Program.cs
vendored
@ -23,8 +23,18 @@ unsafe
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
var ctx = NativeMethods.create_context();
|
var handler = NativeMethods.create_counter_context();
|
||||||
ctx->DeleteContext2();
|
|
||||||
|
handler->Insert(10);
|
||||||
|
handler->Insert(20);
|
||||||
|
handler->Insert(30);
|
||||||
|
|
||||||
|
NativeMethods.destroy_counter_context(handler);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//ctx->DeleteContext2();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user