mirror of
https://github.com/Sarsoo/csbindgen.git
synced 2024-12-23 06:56:27 +00:00
callback complete
This commit is contained in:
parent
b986cbefff
commit
12af43c76c
28
csbindgen-tests/src/lib.rs
vendored
28
csbindgen-tests/src/lib.rs
vendored
@ -14,6 +14,28 @@ mod lz4;
|
|||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
mod lz4_ffi;
|
mod lz4_ffi;
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn callback_test(cb: extern "C" fn(a: i32) -> i32) -> i32 {
|
||||||
|
cb(100)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn nullable_callback_test(cb: Option<extern "C" fn(a: i32) -> i32>) -> i32 {
|
||||||
|
match cb {
|
||||||
|
Some(f) => f(100),
|
||||||
|
None => -1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn callback_test2() -> extern "C" fn(a: i32) -> i32 {
|
||||||
|
callback
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" fn callback(a: i32) -> i32 {
|
||||||
|
a * a
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[allow(improper_ctypes_definitions)]
|
#[allow(improper_ctypes_definitions)]
|
||||||
pub extern "C" fn ignore_nop() -> (i32, i32) {
|
pub extern "C" fn ignore_nop() -> (i32, i32) {
|
||||||
@ -31,12 +53,6 @@ pub extern "C" fn my_add(x: i32, y: i32) -> i32 {
|
|||||||
x + y
|
x + y
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern "C" fn callback_test(cb: extern fn(a: i32) -> i32) -> i32 {
|
|
||||||
// Fn
|
|
||||||
cb(100)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn create_counter_context() -> *mut c_void {
|
pub extern "C" fn create_counter_context() -> *mut c_void {
|
||||||
let ctx = Box::new(CounterContext {
|
let ctx = Box::new(CounterContext {
|
||||||
|
@ -25,7 +25,7 @@ pub fn emit_rust_method(list: &Vec<ExternMethod>, options: &BindgenOptions) -> S
|
|||||||
format!(
|
format!(
|
||||||
" {}: {}",
|
" {}: {}",
|
||||||
p.name,
|
p.name,
|
||||||
p.rust_type.to_string(method_type_path)
|
p.rust_type.to_rust_string(method_type_path)
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
@ -33,7 +33,7 @@ pub fn emit_rust_method(list: &Vec<ExternMethod>, options: &BindgenOptions) -> S
|
|||||||
|
|
||||||
let return_line = match &item.return_type {
|
let return_line = match &item.return_type {
|
||||||
None => "".to_string(),
|
None => "".to_string(),
|
||||||
Some(v) => format!(" -> {}", v.to_string(method_type_path)),
|
Some(v) => format!(" -> {}", v.to_rust_string(method_type_path)),
|
||||||
};
|
};
|
||||||
|
|
||||||
let parameter_only_names = item
|
let parameter_only_names = item
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
use crate::{builder::BindgenOptions, type_meta::*};
|
use crate::{builder::BindgenOptions, type_meta::*};
|
||||||
use std::{
|
use std::collections::{HashMap, HashSet};
|
||||||
collections::{HashMap, HashSet},
|
use syn::{ForeignItem, Item, Pat, ReturnType};
|
||||||
};
|
|
||||||
use syn::{ForeignItem, Item, Pat, ReturnType};
|
|
||||||
|
|
||||||
enum FnItem {
|
enum FnItem {
|
||||||
ForeignItem(syn::ForeignItemFn),
|
ForeignItem(syn::ForeignItemFn),
|
||||||
@ -120,8 +118,8 @@ pub fn collect_type_alias(ast: &syn::File) -> Vec<(String, RustType)> {
|
|||||||
name,
|
name,
|
||||||
RustType {
|
RustType {
|
||||||
type_name: alias.to_string(),
|
type_name: alias.to_string(),
|
||||||
type_kind: TypeKind::Normal
|
type_kind: TypeKind::Normal,
|
||||||
}
|
},
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -217,22 +215,46 @@ fn parse_type(t: &syn::Type) -> RustType {
|
|||||||
if let syn::Type::Path(path) = &*t.elem {
|
if let syn::Type::Path(path) = &*t.elem {
|
||||||
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 { PointerType::ConstPointer } else { PointerType::MutPointer })
|
type_kind: TypeKind::Pointer(if has_const {
|
||||||
|
PointerType::ConstPointer
|
||||||
|
} else {
|
||||||
|
PointerType::MutPointer
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
} 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 {
|
||||||
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 { PointerType::ConstPointerPointer } else { PointerType::MutPointerPointer })
|
type_kind: TypeKind::Pointer(if has_const {
|
||||||
|
PointerType::ConstPointerPointer
|
||||||
|
} else {
|
||||||
|
PointerType::MutPointerPointer
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
syn::Type::Path(t) => {
|
syn::Type::Path(t) => {
|
||||||
return RustType{
|
let last_segment = t.path.segments.last().unwrap();
|
||||||
type_name:t.path.segments.last().unwrap().ident.to_string(),
|
if let syn::PathArguments::AngleBracketed(x) = &last_segment.arguments {
|
||||||
type_kind: TypeKind::Normal
|
// generics, only supports Option<> for null function pointer
|
||||||
}
|
if last_segment.ident.to_string() == "Option" {
|
||||||
|
if let Some(x) = x.args.first() {
|
||||||
|
if let syn::GenericArgument::Type(t) = x {
|
||||||
|
let rust_type = parse_type(t);
|
||||||
|
return RustType {
|
||||||
|
type_name: "Option".to_string(),
|
||||||
|
type_kind: TypeKind::Option(Box::new(rust_type)),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return RustType {
|
||||||
|
type_name: last_segment.ident.to_string(),
|
||||||
|
type_kind: TypeKind::Normal,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
syn::Type::Array(t) => {
|
syn::Type::Array(t) => {
|
||||||
let mut digits = "".to_string();
|
let mut digits = "".to_string();
|
||||||
@ -256,8 +278,29 @@ fn parse_type(t: &syn::Type) -> RustType {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
syn::Type::BareFn(_) => {
|
syn::Type::BareFn(t) => {
|
||||||
//todo!();
|
let mut parameters = Vec::new();
|
||||||
|
|
||||||
|
for arg in t.inputs.iter() {
|
||||||
|
let rust_type = parse_type(&arg.ty);
|
||||||
|
|
||||||
|
let name = if let Some((ident, _)) = &arg.name {
|
||||||
|
ident.to_string()
|
||||||
|
} else {
|
||||||
|
"".to_string()
|
||||||
|
};
|
||||||
|
parameters.push(Parameter { name, rust_type });
|
||||||
|
}
|
||||||
|
|
||||||
|
let ret = match &t.output {
|
||||||
|
syn::ReturnType::Default => None,
|
||||||
|
syn::ReturnType::Type(_, t) => Some(Box::new(parse_type(&t))),
|
||||||
|
};
|
||||||
|
|
||||||
|
return RustType {
|
||||||
|
type_name: "extern \"C\" fn".to_string(),
|
||||||
|
type_kind: TypeKind::Function(parameters, ret),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use std::collections::HashMap;
|
use std::{collections::HashMap};
|
||||||
|
|
||||||
use crate::builder::BindgenOptions;
|
use crate::builder::BindgenOptions;
|
||||||
|
|
||||||
@ -51,8 +51,9 @@ pub struct RustType {
|
|||||||
pub enum TypeKind {
|
pub enum TypeKind {
|
||||||
Normal,
|
Normal,
|
||||||
Pointer(PointerType),
|
Pointer(PointerType),
|
||||||
FixedArray(String, Option<PointerType>), // digits
|
FixedArray(String, Option<PointerType>), // digits
|
||||||
Function(Vec<RustType>, Option<Box<RustType>>), // parameter, return
|
Function(Vec<Parameter>, Option<Box<RustType>>), // parameter, return
|
||||||
|
Option(Box<RustType>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@ -71,7 +72,7 @@ pub struct RustStruct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl RustType {
|
impl RustType {
|
||||||
pub fn to_string(&self, type_path: &str) -> String {
|
pub fn to_rust_string(&self, type_path: &str) -> String {
|
||||||
let mut sb = String::new();
|
let mut sb = String::new();
|
||||||
|
|
||||||
fn emit_pointer(sb: &mut String, p: &PointerType) {
|
fn emit_pointer(sb: &mut String, p: &PointerType) {
|
||||||
@ -118,8 +119,25 @@ impl RustType {
|
|||||||
sb.push_str(digits.as_str());
|
sb.push_str(digits.as_str());
|
||||||
sb.push(']');
|
sb.push(']');
|
||||||
}
|
}
|
||||||
Function(x, y) => {
|
Function(parameters, return_type) => {
|
||||||
todo!();
|
emit_type_name(&mut sb); // extern fn
|
||||||
|
sb.push('(');
|
||||||
|
let params = parameters
|
||||||
|
.iter()
|
||||||
|
.map(|x| format!("{}: {}", x.escape_name(), x.rust_type.to_rust_string(type_path)))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(", ");
|
||||||
|
sb.push_str(params.as_str());
|
||||||
|
sb.push(')');
|
||||||
|
if let Some(t) = return_type {
|
||||||
|
sb.push_str(" -> ");
|
||||||
|
sb.push_str(t.to_rust_string(type_path).as_str());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Option(inner) => {
|
||||||
|
sb.push_str("Option<");
|
||||||
|
sb.push_str(inner.to_rust_string(type_path).as_str());
|
||||||
|
sb.push('>');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -180,7 +198,7 @@ impl RustType {
|
|||||||
|
|
||||||
let mut sb = String::new();
|
let mut sb = String::new();
|
||||||
|
|
||||||
match self.type_kind {
|
match &self.type_kind {
|
||||||
TypeKind::FixedArray(_, _) => {
|
TypeKind::FixedArray(_, _) => {
|
||||||
sb.push_str("fixed ");
|
sb.push_str("fixed ");
|
||||||
|
|
||||||
@ -194,6 +212,27 @@ impl RustType {
|
|||||||
|
|
||||||
sb.push_str(type_name.as_str());
|
sb.push_str(type_name.as_str());
|
||||||
}
|
}
|
||||||
|
TypeKind::Function(parameters, return_type) => {
|
||||||
|
sb.push_str("delegate* unmanaged[Cdecl]");
|
||||||
|
sb.push('<');
|
||||||
|
for p in parameters {
|
||||||
|
sb.push_str(&p.rust_type.to_csharp_string(options, alias_map));
|
||||||
|
sb.push_str(", ");
|
||||||
|
}
|
||||||
|
match return_type {
|
||||||
|
Some(x) => {
|
||||||
|
sb.push_str(&x.to_csharp_string(options, alias_map));
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
sb.push_str("void");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
sb.push('>');
|
||||||
|
},
|
||||||
|
TypeKind::Option(inner) =>{
|
||||||
|
// function pointer can not annotate ? so emit inner only
|
||||||
|
sb.push_str(inner.to_csharp_string(options, alias_map).as_str());
|
||||||
|
},
|
||||||
_ => {
|
_ => {
|
||||||
sb.push_str(convert_type_name(use_type.type_name.as_str(), options).as_str());
|
sb.push_str(convert_type_name(use_type.type_name.as_str(), options).as_str());
|
||||||
|
|
||||||
@ -229,6 +268,6 @@ impl RustType {
|
|||||||
|
|
||||||
impl std::fmt::Display for RustType {
|
impl std::fmt::Display for RustType {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "{}", self.to_string(""))
|
write!(f, "{}", self.to_rust_string(""))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
24
dotnet-sandbox/Program.cs
vendored
24
dotnet-sandbox/Program.cs
vendored
@ -13,16 +13,24 @@ using System.Text;
|
|||||||
|
|
||||||
unsafe
|
unsafe
|
||||||
{
|
{
|
||||||
// LibRust.call_bindgen();
|
[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })]
|
||||||
|
static int Method(int x) => x * x;
|
||||||
|
|
||||||
|
var tako = LibRust.callback_test(&Method);
|
||||||
|
|
||||||
|
|
||||||
|
var n = LibRust.nullable_callback_test(null);
|
||||||
|
|
||||||
|
Console.WriteLine(n);
|
||||||
|
|
||||||
|
|
||||||
var ctx = LibRust.create_counter_context();
|
//var ctx = LibRust.create_counter_context();
|
||||||
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.insert_counter_context(ctx, 20);
|
//LibRust.insert_counter_context(ctx, 20);
|
||||||
LibRust.insert_counter_context(ctx, 30);
|
//LibRust.insert_counter_context(ctx, 30);
|
||||||
LibRust.insert_counter_context(ctx, 99);
|
//LibRust.insert_counter_context(ctx, 99);
|
||||||
LibRust.delete_counter_context(ctx);
|
//LibRust.delete_counter_context(ctx);
|
||||||
|
|
||||||
//var cString = LibRust.alloc_c_string();
|
//var cString = LibRust.alloc_c_string();
|
||||||
//var u8String = LibRust.alloc_u8_string();
|
//var u8String = LibRust.alloc_u8_string();
|
||||||
|
12
dotnet-sandbox/method_call.cs
vendored
12
dotnet-sandbox/method_call.cs
vendored
@ -11,6 +11,18 @@ namespace CsBindgen
|
|||||||
{
|
{
|
||||||
const string __DllName = "csbindgen_tests";
|
const string __DllName = "csbindgen_tests";
|
||||||
|
|
||||||
|
[DllImport(__DllName, EntryPoint = "callback_test", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
public static extern int callback_test(delegate* unmanaged[Cdecl]<int, int> cb);
|
||||||
|
|
||||||
|
[DllImport(__DllName, EntryPoint = "nullable_callback_test", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
public static extern int nullable_callback_test(delegate* unmanaged[Cdecl]<int, int> cb);
|
||||||
|
|
||||||
|
[DllImport(__DllName, EntryPoint = "callback_test2", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
public static extern delegate* unmanaged[Cdecl]<int, int> callback_test2();
|
||||||
|
|
||||||
|
[DllImport(__DllName, EntryPoint = "callback", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
public static extern int callback(int a);
|
||||||
|
|
||||||
[DllImport(__DllName, EntryPoint = "nop", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(__DllName, EntryPoint = "nop", CallingConvention = CallingConvention.Cdecl)]
|
||||||
public static extern void nop();
|
public static extern void nop();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user