Skip to content

Commit

Permalink
generate extern c functions
Browse files Browse the repository at this point in the history
  • Loading branch information
vhdirk committed May 26, 2018
1 parent 795f7c3 commit 8030304
Show file tree
Hide file tree
Showing 4 changed files with 179 additions and 30 deletions.
25 changes: 13 additions & 12 deletions src/codegen/subclass/class_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use std::result::Result as StdResult;
use codegen::general;
use codegen::subclass::virtual_methods;
use codegen::sys::fields;

use library::*;

use analysis::general::StatusedTypeId;
Expand Down Expand Up @@ -554,18 +555,18 @@ fn generate_extern_c_funcs(
object_analysis: &analysis::object::Info,
subclass_info: &SubclassInfo,
) -> Result<()> {
// unsafe extern "C" fn application_startup<T: ApplicationBase>(ptr: *mut gio_ffi::GApplication)
// where
// T::ImplType: ApplicationImpl<T>,
// {
// callback_guard!();
// floating_reference_guard!(ptr);
// let application = &*(ptr as *mut T::InstanceStructType);
// let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
// let imp = application.get_impl();
//
// imp.startup(&wrap)
// }


for method_analysis in &object_analysis.virtual_methods {
try!(virtual_methods::generate_extern_c_func(
w,
env,
object_analysis,
method_analysis,
subclass_info,
0
));
}

Ok(())
}
39 changes: 39 additions & 0 deletions src/codegen/subclass/virtual_method_body_chunks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use codegen::parameter::*;

#[derive(Default)]
pub struct Builder {
object_name: String,
object_class_c_type: String,
ffi_crate_name: String,
method_name: String,
Expand All @@ -36,6 +37,11 @@ impl Builder {
Default::default()
}

pub fn object_name(&mut self, name: &str) -> &mut Builder {
self.object_name = name.into();
self
}

pub fn object_class_c_type(&mut self, c_class_type: &str) -> &mut Builder {
self.object_class_c_type = c_class_type.into();
self
Expand Down Expand Up @@ -109,6 +115,39 @@ impl Builder {
Chunk::Chunks(chunks)
}

pub fn generate_extern_c_func(&self, env: &Env) -> Chunk {
let mut chunks = Vec::new();

chunks.push(Chunk::Custom("callback_guard!();".to_owned()));
chunks.push(Chunk::Custom("floating_reference_guard!(ptr);".to_owned()));

chunks.push(Chunk::Let{ is_mut:false,
name: self.object_name.to_lowercase(),
value: Box::new(Chunk::Custom("&*(ptr as *mut T::InstanceStructType)".to_owned())),
type_: None
});

chunks.push(Chunk::Let{ is_mut:false,
name: "wrap".to_owned(),
value: Box::new(Chunk::Custom("from_glib_borrow(ptr as *mut T::InstanceStructType))".to_owned())),
type_: Some(Box::new(Chunk::Custom("T".to_owned())))
});

chunks.push(Chunk::Let{ is_mut:false,
name: "imp".to_owned(),
value: Box::new(Chunk::Custom(format!("{}.get_impl())",
self.object_name.to_lowercase()).to_owned())),
type_: None
});

chunks.push(Chunk::Custom(format!("imp.{}({})",
self.method_name,
&"").to_owned()));

Chunk::Chunks(chunks)
}



fn base_impl_body_chunk(&self) -> Chunk {
Chunk::Closure {
Expand Down
143 changes: 126 additions & 17 deletions src/codegen/subclass/virtual_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,16 @@ use writer::primitives::tabs;
use writer::ToCode;
use codegen::parameter::ToParameter;
use chunk::{ffi_function_todo, Chunk};
use traits::IntoString;
use nameutil;

use std::result::Result as StdResult;
use std::fmt;

use codegen::subclass::class_impl::SubclassInfo;
use codegen::subclass::virtual_method_body_chunks::Builder;
use codegen::sys::ffi_type::ffi_type;
use codegen::function_body_chunk::{Parameter, ReturnValue};

pub fn generate_default_impl(
w: &mut Write,
Expand All @@ -39,7 +43,7 @@ pub fn generate_default_impl(

let parent_name = &method_analysis.parameters.rust_parameters[0].name;

let param_str = virtual_method_params(env, method_analysis, parent_name, true);
let param_str = virtual_method_params(env, method_analysis, Some(parent_name));

try!(writeln!(w, "{}){{", param_str));

Expand Down Expand Up @@ -97,7 +101,7 @@ fn virtual_method_args(method_analysis: &analysis::virtual_methods::Info, includ
arg_str
}

fn virtual_method_params(env: &Env, method_analysis: &analysis::virtual_methods::Info, parent_name: &String, include_templated: bool) -> String
fn virtual_method_params(env: &Env, method_analysis: &analysis::virtual_methods::Info, parent_name: Option<&String>) -> String
{
let mut param_str = String::with_capacity(100);
for (pos, par) in method_analysis.parameters.rust_parameters.iter().enumerate() {
Expand All @@ -106,12 +110,15 @@ fn virtual_method_params(env: &Env, method_analysis: &analysis::virtual_methods:
}

let c_par = &method_analysis.parameters.c_parameters[par.ind_c];
let s = c_par.to_parameter(env, &method_analysis.bounds);

// generate types, not trait bounds
let bounds = Bounds::default();
let s = c_par.to_parameter(env, &bounds);
param_str.push_str(&s);

// insert the templated param
if include_templated && pos == 0{
param_str.push_str(&format!(", {}: &T", parent_name));
if parent_name.is_some() && pos == 0{
param_str.push_str(&format!(", {}: &T", parent_name.as_ref().unwrap()));
}
}
param_str
Expand All @@ -137,16 +144,7 @@ pub fn generate_base_impl(
method_analysis.name,
));

let mut param_str = String::with_capacity(100);
for (pos, par) in method_analysis.parameters.rust_parameters.iter().enumerate() {
if pos > 0 {
param_str.push_str(", ");
}

let c_par = &method_analysis.parameters.c_parameters[par.ind_c];
let s = c_par.to_parameter(env, &method_analysis.bounds);
param_str.push_str(&s);
}
let mut param_str = virtual_method_params(env, method_analysis, None);


try!(writeln!(w, "{}){{", param_str));
Expand Down Expand Up @@ -240,7 +238,7 @@ pub fn generate_box_impl(

let parent_name = &method_analysis.parameters.rust_parameters[0].name;

let param_str = virtual_method_params(env, method_analysis, parent_name, true);
let param_str = virtual_method_params(env, method_analysis, Some(parent_name));
try!(writeln!(w, "{}){{", param_str));


Expand Down Expand Up @@ -272,7 +270,56 @@ pub fn generate_box_impl(
Ok(())
}

pub fn generate_extern_c_func(
w: &mut Write,
env: &Env,
object_analysis: &analysis::object::Info,
method_analysis: &analysis::virtual_methods::Info,
subclass_info: &SubclassInfo,
indent: usize,
) -> Result<()> {

try!(writeln!(w));

try!(writeln!(
w,
"unsafe extern \"C\" fn {}_{}<T: {}>",
object_analysis.name.to_lowercase(),
method_analysis.name,
object_analysis.subclass_base_trait_name
));

let (_, sig) = function_signature(env, method_analysis, false);

try!(writeln!(
w,
"{}",
sig
));

try!(writeln!(
w,
"where\n{}T::ImplType: {}<T>",
tabs(indent+1),
object_analysis.subclass_impl_trait_name
));
try!(writeln!(
w,
"{{"
));

let body = extern_c_func_body_chunk(env, object_analysis, method_analysis, subclass_info).to_code(env);
for s in body {
try!(writeln!(w, "{}{}", tabs(indent+1), s));
}

try!(writeln!(
w,
"}}"
));

Ok(())
}

pub fn body_chunk_builder(env: &Env,
object_analysis: &analysis::object::Info,
Expand All @@ -284,7 +331,8 @@ pub fn body_chunk_builder(env: &Env,

let outs_as_return = !method_analysis.outs.is_empty();

builder.object_class_c_type(object_analysis.c_class_type.as_ref().unwrap())
builder.object_name(&object_analysis.name)
.object_class_c_type(object_analysis.c_class_type.as_ref().unwrap())
.ffi_crate_name(&env.namespaces[object_analysis.type_id.ns_id].ffi_crate_name)
.method_name(&method_analysis.name)
.ret(&method_analysis.ret)
Expand Down Expand Up @@ -312,3 +360,64 @@ pub fn base_impl_body_chunk(env: &Env,

builder.generate_base_impl(env)
}

pub fn extern_c_func_body_chunk(env: &Env,
object_analysis: &analysis::object::Info,
method_analysis: &analysis::virtual_methods::Info,
subclass_info: &SubclassInfo
) -> Chunk
{
let mut builder = body_chunk_builder(env, object_analysis, method_analysis, subclass_info);

builder.generate_extern_c_func(env)
}


pub fn function_signature(env: &Env, method: &analysis::virtual_methods::Info, bare: bool) -> (bool, String) {
let (mut commented, ret_str) = function_return_value(env, method);

let mut parameter_strs: Vec<String> = Vec::new();
for par in &method.parameters.c_parameters {
let (c, par_str) = function_parameter(env, par, bare);
parameter_strs.push(par_str);
if c {
commented = true;
}
}

(
commented,
format!("({}){}", parameter_strs.join(", "), ret_str),
)
}

fn function_return_value(env: &Env, method: &analysis::virtual_methods::Info) -> (bool, String) {
if method.ret.parameter.is_none(){
return (false, "".to_string());
}
let ret = method.ret.parameter.as_ref().unwrap();
if ret.typ == Default::default() {
return (false, String::new());
}
let ffi_type = ffi_type(env, ret.typ, &ret.c_type);
let commented = ffi_type.is_err();
(commented, format!(" -> {}", ffi_type.into_string()))
}

fn function_parameter(env: &Env, par: &analysis::function_parameters::CParameter, bare: bool) -> (bool, String) {
if let library::Type::Fundamental(library::Fundamental::VarArgs) = *env.library.type_(par.typ) {
return (false, "...".into());
}
let ffi_type = ffi_type(env, par.typ, &par.c_type);
let commented = ffi_type.is_err();
let res = if bare {
ffi_type.into_string()
} else {
format!(
"{}: {}",
nameutil::mangle_keywords(&*par.name),
ffi_type.into_string()
)
};
(commented, res)
}
2 changes: 1 addition & 1 deletion src/codegen/sys/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ mod build;
mod cargo_toml;
pub mod ffi_type;
pub mod fields;
mod functions;
pub mod functions;
mod lib_;
mod statics;
mod tests;
Expand Down

0 comments on commit 8030304

Please sign in to comment.