Add py_method!() macro for creating method descriptors.
This commit is contained in:
parent
5c74f55862
commit
4980053e95
|
@ -33,6 +33,8 @@ stamps/test-hello: hello.out
|
||||||
@grep "Rust says: Hello Python!" hello.out >/dev/null
|
@grep "Rust says: Hello Python!" hello.out >/dev/null
|
||||||
@grep "Rust got 42" hello.out >/dev/null
|
@grep "Rust got 42" hello.out >/dev/null
|
||||||
|
|
||||||
|
all: custom_type.so
|
||||||
|
|
||||||
all: inheritance.so
|
all: inheritance.so
|
||||||
|
|
||||||
|
|
||||||
|
|
21
extensions/custom_type.rs
Normal file
21
extensions/custom_type.rs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#![crate_type = "dylib"]
|
||||||
|
#![feature(plugin)]
|
||||||
|
#![plugin(interpolate_idents)]
|
||||||
|
|
||||||
|
#[macro_use] extern crate cpython;
|
||||||
|
|
||||||
|
use cpython::{PythonObject, PyObject, PyRustObject, PyTuple, PyResult};
|
||||||
|
|
||||||
|
py_module_initializer!(custom_type, |_py, m| {
|
||||||
|
try!(m.add("__doc__", "Module documentation string"));
|
||||||
|
try!(m.add_type::<i32>("MyType")
|
||||||
|
.add("a", py_method!(a))
|
||||||
|
.finish());
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
|
||||||
|
fn a<'p>(slf: &PyRustObject<'p, i32>, args: &PyTuple<'p>) -> PyResult<'p, PyObject<'p>> {
|
||||||
|
println!("a() was called with self={:?} and args={:?}", slf.get(), args.as_object());
|
||||||
|
Ok(slf.python().None())
|
||||||
|
}
|
||||||
|
|
87
src/function.rs
Normal file
87
src/function.rs
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
// Copyright (c) 2015 Daniel Grunwald
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||||
|
// software and associated documentation files (the "Software"), to deal in the Software
|
||||||
|
// without restriction, including without limitation the rights to use, copy, modify, merge,
|
||||||
|
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
|
||||||
|
// to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all copies or
|
||||||
|
// substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||||
|
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
use libc::c_char;
|
||||||
|
use std::ptr;
|
||||||
|
use python::Python;
|
||||||
|
use objects::PyObject;
|
||||||
|
use conversion::ToPyObject;
|
||||||
|
use ffi;
|
||||||
|
use err;
|
||||||
|
|
||||||
|
/// Creates a python callable object that invokes a Rust function.
|
||||||
|
///
|
||||||
|
/// As arguments, takes the name of a rust function with the signature
|
||||||
|
/// `for<'p> fn(Python<'p>, &PyTuple<'p>) -> PyResult<'p, T>`
|
||||||
|
/// for some `T` that implements `ToPyObject`.
|
||||||
|
///
|
||||||
|
/// Returns a type that implements `ToPyObject` by producing a python callable.
|
||||||
|
///
|
||||||
|
/// See `py_module_initializer!` for example usage.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! py_fn {
|
||||||
|
($f: ident) => ( interpolate_idents! {{
|
||||||
|
unsafe extern "C" fn [ wrap_ $f ](
|
||||||
|
_slf: *mut $crate::_detail::ffi::PyObject,
|
||||||
|
args: *mut $crate::_detail::ffi::PyObject)
|
||||||
|
-> *mut $crate::_detail::ffi::PyObject
|
||||||
|
{
|
||||||
|
let _guard = $crate::_detail::PanicGuard::with_message("Rust panic in py_fn!");
|
||||||
|
let py = $crate::_detail::bounded_assume_gil_acquired(&args);
|
||||||
|
let args = $crate::PyObject::from_borrowed_ptr(py, args);
|
||||||
|
let args = <$crate::PyTuple as $crate::PythonObject>::unchecked_downcast_from(args);
|
||||||
|
match $f(py, &args) {
|
||||||
|
Ok(val) => {
|
||||||
|
let obj = $crate::ToPyObject::into_py_object(val, py);
|
||||||
|
return $crate::ToPythonPointer::steal_ptr(obj);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
e.restore();
|
||||||
|
return ::std::ptr::null_mut();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static mut [ method_def_ $f ]: $crate::_detail::ffi::PyMethodDef = $crate::_detail::ffi::PyMethodDef {
|
||||||
|
//ml_name: bytes!(stringify!($f), "\0"),
|
||||||
|
ml_name: 0 as *const $crate::_detail::libc::c_char,
|
||||||
|
ml_meth: Some([ wrap_ $f ]),
|
||||||
|
ml_flags: $crate::_detail::ffi::METH_VARARGS,
|
||||||
|
ml_doc: 0 as *const $crate::_detail::libc::c_char
|
||||||
|
};
|
||||||
|
unsafe {
|
||||||
|
$crate::_detail::py_fn_impl(&mut [ method_def_ $f ])
|
||||||
|
}
|
||||||
|
}})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PyFn(*mut ffi::PyMethodDef);
|
||||||
|
|
||||||
|
pub unsafe fn py_fn_impl(def: *mut ffi::PyMethodDef) -> PyFn {
|
||||||
|
PyFn(def)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <'p> ToPyObject<'p> for PyFn {
|
||||||
|
type ObjectType = PyObject<'p>;
|
||||||
|
|
||||||
|
fn to_py_object(&self, py: Python<'p>) -> PyObject<'p> {
|
||||||
|
unsafe {
|
||||||
|
err::from_owned_ptr_or_panic(py, ffi::PyCFunction_New(self.0, ptr::null_mut()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
67
src/lib.rs
67
src/lib.rs
|
@ -113,6 +113,7 @@ mod conversion;
|
||||||
mod objects;
|
mod objects;
|
||||||
mod objectprotocol;
|
mod objectprotocol;
|
||||||
mod pythonrun;
|
mod pythonrun;
|
||||||
|
mod function;
|
||||||
#[cfg(feature="python27-sys")]
|
#[cfg(feature="python27-sys")]
|
||||||
mod rustobject;
|
mod rustobject;
|
||||||
|
|
||||||
|
@ -123,6 +124,9 @@ pub mod _detail {
|
||||||
pub use libc;
|
pub use libc;
|
||||||
pub use abort_on_panic::PanicGuard;
|
pub use abort_on_panic::PanicGuard;
|
||||||
pub use err::from_owned_ptr_or_panic;
|
pub use err::from_owned_ptr_or_panic;
|
||||||
|
pub use function::py_fn_impl;
|
||||||
|
#[cfg(feature="python27-sys")]
|
||||||
|
pub use rustobject::method::py_method_impl;
|
||||||
|
|
||||||
/// assume_gil_acquired(), but the returned Python<'p> is bounded by the scope
|
/// assume_gil_acquired(), but the returned Python<'p> is bounded by the scope
|
||||||
/// of the referenced variable.
|
/// of the referenced variable.
|
||||||
|
@ -282,66 +286,3 @@ pub unsafe fn py_module_initializer_impl(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a python callable object that invokes a Rust function.
|
|
||||||
///
|
|
||||||
/// As arguments, takes the name of a rust function with the signature
|
|
||||||
/// `<'p>(Python<'p>, &PyTuple<'p>) -> PyResult<'p, T>`
|
|
||||||
/// for some `T` that implements `ToPyObject`.
|
|
||||||
///
|
|
||||||
/// Returns a type that implements `ToPyObject` by producing a python callable.
|
|
||||||
///
|
|
||||||
/// See `py_module_initializer!` for example usage.
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! py_fn {
|
|
||||||
($f: ident) => ( interpolate_idents! {{
|
|
||||||
unsafe extern "C" fn [ wrap_ $f ](
|
|
||||||
_slf: *mut $crate::_detail::ffi::PyObject,
|
|
||||||
args: *mut $crate::_detail::ffi::PyObject)
|
|
||||||
-> *mut $crate::_detail::ffi::PyObject
|
|
||||||
{
|
|
||||||
let _guard = $crate::_detail::PanicGuard::with_message("Rust panic in py_fn!");
|
|
||||||
let py = $crate::_detail::bounded_assume_gil_acquired(&args);
|
|
||||||
let args = $crate::PyObject::from_borrowed_ptr(py, args);
|
|
||||||
let args = <$crate::PyTuple as $crate::PythonObject>::unchecked_downcast_from(args);
|
|
||||||
match $f(py, &args) {
|
|
||||||
Ok(val) => {
|
|
||||||
let obj = $crate::ToPyObject::into_py_object(val, py);
|
|
||||||
return $crate::ToPythonPointer::steal_ptr(obj);
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
e.restore();
|
|
||||||
return ::std::ptr::null_mut();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static mut [ method_def_ $f ]: $crate::_detail::ffi::PyMethodDef = $crate::_detail::ffi::PyMethodDef {
|
|
||||||
//ml_name: bytes!(stringify!($f), "\0"),
|
|
||||||
ml_name: b"<rust function>\0" as *const u8 as *const $crate::_detail::libc::c_char,
|
|
||||||
ml_meth: Some([ wrap_ $f ]),
|
|
||||||
ml_flags: $crate::_detail::ffi::METH_VARARGS,
|
|
||||||
ml_doc: 0 as *const $crate::_detail::libc::c_char
|
|
||||||
};
|
|
||||||
unsafe { $crate::PyRustFunctionHandle::new(&mut [ method_def_ $f ]) }
|
|
||||||
}})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub struct PyRustFunctionHandle(*mut ffi::PyMethodDef);
|
|
||||||
|
|
||||||
impl PyRustFunctionHandle {
|
|
||||||
#[inline]
|
|
||||||
pub unsafe fn new(p: *mut ffi::PyMethodDef) -> PyRustFunctionHandle {
|
|
||||||
PyRustFunctionHandle(p)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl <'p> ToPyObject<'p> for PyRustFunctionHandle {
|
|
||||||
type ObjectType = PyObject<'p>;
|
|
||||||
|
|
||||||
fn to_py_object(&self, py: Python<'p>) -> PyObject<'p> {
|
|
||||||
unsafe {
|
|
||||||
err::from_owned_ptr_or_panic(py, ffi::PyCFunction_New(self.0, ptr::null_mut()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1,119 @@
|
||||||
use python::Python;
|
// Copyright (c) 2015 Daniel Grunwald
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||||
|
// software and associated documentation files (the "Software"), to deal in the Software
|
||||||
|
// without restriction, including without limitation the rights to use, copy, modify, merge,
|
||||||
|
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
|
||||||
|
// to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all copies or
|
||||||
|
// substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||||
|
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
use std::{ptr, marker};
|
||||||
|
use python::{Python, PythonObject};
|
||||||
|
use objects::{PyObject, PyTuple, PyType};
|
||||||
|
use conversion::ToPyObject;
|
||||||
|
use super::typebuilder::TypeMember;
|
||||||
|
use ffi;
|
||||||
|
use err;
|
||||||
|
|
||||||
|
/// Creates a python instance method descriptor that invokes a Rust function.
|
||||||
|
///
|
||||||
|
/// As arguments, takes the name of a rust function with the signature
|
||||||
|
/// `for<'p> fn(&PyRustObject<'p, _>, &PyTuple<'p>) -> PyResult<'p, T>`
|
||||||
|
/// for some `T` that implements `ToPyObject`.
|
||||||
|
///
|
||||||
|
/// Returns a type that implements `pythonobject::TypeMember<PyRustObject<_>>`
|
||||||
|
/// by producing an instance method descriptor.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// #![feature(plugin)]
|
||||||
|
/// #![plugin(interpolate_idents)]
|
||||||
|
/// #[macro_use] extern crate cpython;
|
||||||
|
/// use cpython::{Python, PythonObject, PyResult, PyErr, ObjectProtocol,
|
||||||
|
/// PyTuple, PyRustObject, PyRustTypeBuilder};
|
||||||
|
/// use cpython::{exc};
|
||||||
|
///
|
||||||
|
/// fn mul<'p>(slf: &PyRustObject<'p, i32>, args: &PyTuple<'p>) -> PyResult<'p, i32> {
|
||||||
|
/// let py = slf.python();
|
||||||
|
/// match slf.get().checked_mul(try!(args.get_item(0).extract::<i32>())) {
|
||||||
|
/// Some(val) => Ok(val),
|
||||||
|
/// None => Err(PyErr::new_lazy_init(py.get_type::<exc::OverflowError>(), None))
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// fn main() {
|
||||||
|
/// let gil = Python::acquire_gil();
|
||||||
|
/// let multiplier_type = PyRustTypeBuilder::<i32>::new(gil.python(), "Multiplier")
|
||||||
|
/// .add("mul", py_method!(mul))
|
||||||
|
/// .finish().unwrap();
|
||||||
|
/// let obj = multiplier_type.create_instance(3, ()).into_object();
|
||||||
|
/// let result = obj.call_method("mul", &(4,), None).unwrap().extract::<i32>().unwrap();
|
||||||
|
/// assert_eq!(result, 12);
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! py_method {
|
||||||
|
($f: ident) => ( interpolate_idents! {{
|
||||||
|
unsafe extern "C" fn [ wrap_ $f ](
|
||||||
|
slf: *mut $crate::_detail::ffi::PyObject,
|
||||||
|
args: *mut $crate::_detail::ffi::PyObject)
|
||||||
|
-> *mut $crate::_detail::ffi::PyObject
|
||||||
|
{
|
||||||
|
let _guard = $crate::_detail::PanicGuard::with_message("Rust panic in py_method!");
|
||||||
|
let py = $crate::_detail::bounded_assume_gil_acquired(&args);
|
||||||
|
let slf = $crate::PyObject::from_borrowed_ptr(py, slf);
|
||||||
|
let slf = $crate::PythonObject::unchecked_downcast_from(slf);
|
||||||
|
let args = $crate::PyObject::from_borrowed_ptr(py, args);
|
||||||
|
let args = <$crate::PyTuple as $crate::PythonObject>::unchecked_downcast_from(args);
|
||||||
|
match $f(&slf, &args) {
|
||||||
|
Ok(val) => {
|
||||||
|
let obj = $crate::ToPyObject::into_py_object(val, py);
|
||||||
|
return $crate::ToPythonPointer::steal_ptr(obj);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
e.restore();
|
||||||
|
return ::std::ptr::null_mut();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static mut [ method_def_ $f ]: $crate::_detail::ffi::PyMethodDef = $crate::_detail::ffi::PyMethodDef {
|
||||||
|
//ml_name: bytes!(stringify!($f), "\0"),
|
||||||
|
ml_name: b"<rust method>\0" as *const u8 as *const $crate::_detail::libc::c_char,
|
||||||
|
ml_meth: Some([ wrap_ $f ]),
|
||||||
|
ml_flags: $crate::_detail::ffi::METH_VARARGS,
|
||||||
|
ml_doc: 0 as *const $crate::_detail::libc::c_char
|
||||||
|
};
|
||||||
|
unsafe { $crate::_detail::py_method_impl(&mut [ method_def_ $f ], $f) }
|
||||||
|
}})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct MethodDescriptor<T>(*mut ffi::PyMethodDef, marker::PhantomData<fn(&T)>);
|
||||||
|
|
||||||
|
// py_method_impl takes fn(&T) to ensure that the T in MethodDescriptor<T>
|
||||||
|
// corresponds to the T in the function signature.
|
||||||
|
pub unsafe fn py_method_impl<'p, T, R>(
|
||||||
|
def: *mut ffi::PyMethodDef,
|
||||||
|
_f: fn(&T, &PyTuple<'p>) -> err::PyResult<'p, R>
|
||||||
|
) -> MethodDescriptor<T> {
|
||||||
|
MethodDescriptor(def, marker::PhantomData)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <'p, T> TypeMember<'p, T> for MethodDescriptor<T> where T: PythonObject<'p> {
|
||||||
|
#[inline]
|
||||||
|
fn into_descriptor(self, ty: &PyType<'p>, name: &str) -> PyObject<'p> {
|
||||||
|
unsafe {
|
||||||
|
err::from_owned_ptr_or_panic(ty.python(),
|
||||||
|
ffi::PyDescr_NewMethod(ty.as_type_ptr(), self.0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,9 @@ use std::{mem, ops, ptr, marker};
|
||||||
use err::{self, PyResult};
|
use err::{self, PyResult};
|
||||||
|
|
||||||
pub mod typebuilder;
|
pub mod typebuilder;
|
||||||
mod method;
|
pub mod method;
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests;
|
||||||
|
|
||||||
/// A PythonObject that is usable as a base type with PyTypeBuilder::base().
|
/// A PythonObject that is usable as a base type with PyTypeBuilder::base().
|
||||||
pub trait PythonBaseObject<'p> : PythonObject<'p> {
|
pub trait PythonBaseObject<'p> : PythonObject<'p> {
|
||||||
|
|
|
@ -1,8 +1,24 @@
|
||||||
extern crate cpython;
|
// Copyright (c) 2015 Daniel Grunwald
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||||
|
// software and associated documentation files (the "Software"), to deal in the Software
|
||||||
|
// without restriction, including without limitation the rights to use, copy, modify, merge,
|
||||||
|
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
|
||||||
|
// to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all copies or
|
||||||
|
// substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||||
|
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use cpython::*;
|
use {Python, NoArgs, PythonObject, PyRustTypeBuilder};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rustobject_calls_drop() {
|
fn rustobject_calls_drop() {
|
||||||
|
@ -29,7 +45,7 @@ fn rustobject_calls_drop() {
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rustobject_no_init_from_python() {
|
fn no_init_from_python() {
|
||||||
let gil = Python::acquire_gil();
|
let gil = Python::acquire_gil();
|
||||||
let py = gil.python();
|
let py = gil.python();
|
||||||
let t = PyRustTypeBuilder::<i32>::new(py, "MyType").finish().unwrap();
|
let t = PyRustTypeBuilder::<i32>::new(py, "MyType").finish().unwrap();
|
||||||
|
@ -38,7 +54,7 @@ fn rustobject_no_init_from_python() {
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rustobject_heaptype_refcount() {
|
fn heaptype_refcount() {
|
||||||
let gil = Python::acquire_gil();
|
let gil = Python::acquire_gil();
|
||||||
let py = gil.python();
|
let py = gil.python();
|
||||||
let t = PyRustTypeBuilder::<i32>::new(py, "MyType").finish().unwrap();
|
let t = PyRustTypeBuilder::<i32>::new(py, "MyType").finish().unwrap();
|
|
@ -1,3 +1,21 @@
|
||||||
|
// Copyright (c) 2015 Daniel Grunwald
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||||
|
// software and associated documentation files (the "Software"), to deal in the Software
|
||||||
|
// without restriction, including without limitation the rights to use, copy, modify, merge,
|
||||||
|
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
|
||||||
|
// to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all copies or
|
||||||
|
// substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||||
|
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
use libc;
|
use libc;
|
||||||
use ffi;
|
use ffi;
|
||||||
use python::{Python, ToPythonPointer, PythonObject};
|
use python::{Python, ToPythonPointer, PythonObject};
|
||||||
|
|
Loading…
Reference in a new issue