allow passing a null through a cstr arg/return
This commit is contained in:
18
src/ffi.rs
18
src/ffi.rs
@@ -80,8 +80,18 @@ impl FunctionImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn call_cstr(&self, args: &[Arg], _: &mut Arena) -> Result<Value, FfiError> {
|
unsafe fn call_cstr(&self, args: &[Arg], _: &mut Arena) -> Result<Value, FfiError> {
|
||||||
let ptr = unsafe { self.cif.call::<*mut c_char>(self.code_ptr, args) };
|
let ptr = unsafe {
|
||||||
Ok(Value::CString(unsafe { CStr::from_ptr(ptr) }.to_owned()))
|
self.cif
|
||||||
|
.call::<Option<NonNull<c_char>>>(self.code_ptr, args)
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(cstr) = ptr {
|
||||||
|
Ok(Value::CString(
|
||||||
|
unsafe { CStr::from_ptr(cstr.as_ptr()) }.to_owned(),
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
Ok(Value::Number(Number::Fixnum(Fixnum::build_with(0))))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn call_struct(
|
unsafe fn call_struct(
|
||||||
@@ -353,7 +363,7 @@ impl<'args, 'val> PointerArgs<'args, 'val> {
|
|||||||
ArgValue::I64(a) => libffi::middle::arg(a),
|
ArgValue::I64(a) => libffi::middle::arg(a),
|
||||||
ArgValue::F32(a) => libffi::middle::arg(a),
|
ArgValue::F32(a) => libffi::middle::arg(a),
|
||||||
ArgValue::F64(a) => libffi::middle::arg(a),
|
ArgValue::F64(a) => libffi::middle::arg(a),
|
||||||
ArgValue::Ptr(ptr, _) => unsafe { std::mem::transmute::<*mut c_void, Arg>(*ptr) },
|
ArgValue::Ptr(ptr, _) => Arg::new(ptr),
|
||||||
ArgValue::Struct(s) => unsafe {
|
ArgValue::Struct(s) => unsafe {
|
||||||
std::mem::transmute::<*mut c_void, Arg>(s.ptr.as_ptr())
|
std::mem::transmute::<*mut c_void, Arg>(s.ptr.as_ptr())
|
||||||
},
|
},
|
||||||
@@ -653,7 +663,7 @@ impl Value {
|
|||||||
|
|
||||||
fn as_ptr(&mut self) -> Result<*mut c_void, FfiError> {
|
fn as_ptr(&mut self) -> Result<*mut c_void, FfiError> {
|
||||||
match self {
|
match self {
|
||||||
Value::CString(ref mut cstr) => Ok(&mut *cstr as *mut _ as *mut c_void),
|
Value::CString(ref mut cstr) => Ok(cstr.as_ptr().cast_mut().cast()),
|
||||||
Value::Number(Number::Fixnum(fixnum)) => Ok(std::ptr::with_exposed_provenance_mut(
|
Value::Number(Number::Fixnum(fixnum)) => Ok(std::ptr::with_exposed_provenance_mut(
|
||||||
fixnum.get_num() as usize,
|
fixnum.get_num() as usize,
|
||||||
)),
|
)),
|
||||||
|
|||||||
@@ -1,16 +1,21 @@
|
|||||||
:- use_module(library(os)).
|
:- use_module(library(os)).
|
||||||
:- use_module(library(ffi)).
|
:- use_module(library(ffi)).
|
||||||
|
|
||||||
test :-
|
init :-
|
||||||
read(Body),
|
read(Body),
|
||||||
term_variables(Body, [LIB]),
|
term_variables(Body, [LIB]),
|
||||||
Body,
|
Body,
|
||||||
use_foreign_module(LIB, [
|
use_foreign_module(LIB, [
|
||||||
'ffi_cstr_len'([cstr], u64),
|
'ffi_cstr_len'([cstr], u64),
|
||||||
'ffi_example_cstr'([], cstr)
|
'ffi_example_cstr'([], cstr),
|
||||||
]),
|
'ffi_null_cstr'([], cstr)
|
||||||
|
]).
|
||||||
|
|
||||||
|
test :-
|
||||||
ffi:'ffi_cstr_len'("Scryer Prolog", Len),
|
ffi:'ffi_cstr_len'("Scryer Prolog", Len),
|
||||||
ffi:'ffi_example_cstr'(Str),
|
ffi:'ffi_example_cstr'(Str),
|
||||||
write((Len-Str)).
|
ffi:'ffi_null_cstr'(Null),
|
||||||
|
ffi:'ffi_cstr_len'(0, MaxU64),
|
||||||
|
write((Len-Str-Null-MaxU64)).
|
||||||
|
|
||||||
:- initialization(test).
|
:- initialization((init,test)).
|
||||||
|
|||||||
@@ -257,20 +257,29 @@ fn ffi_cstr() {
|
|||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
extern "C" fn ffi_cstr_len(c_str: *const core::ffi::c_char) -> u64 {
|
extern "C" fn ffi_cstr_len(c_str: Option<std::ptr::NonNull<core::ffi::c_char>>) -> u64 {
|
||||||
unsafe { CStr::from_ptr(c_str) }.count_bytes() as u64
|
if let Some(c_str) = c_str {
|
||||||
|
unsafe { CStr::from_ptr(c_str.as_ptr()) }.count_bytes() as u64
|
||||||
|
} else {
|
||||||
|
u64::MAX
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
extern "C" fn ffi_example_cstr() -> *const core::ffi::c_char {
|
extern "C" fn ffi_example_cstr() -> *const core::ffi::c_char {
|
||||||
c"Rust Lang".as_ptr()
|
c"Rust Lang".as_ptr()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
extern "C" fn ffi_null_cstr() -> *const core::ffi::c_char {
|
||||||
|
std::ptr::null()
|
||||||
|
}
|
||||||
"##,
|
"##,
|
||||||
);
|
);
|
||||||
|
|
||||||
load_module_test_with_input(
|
load_module_test_with_input(
|
||||||
"tests-pl/ffi_cstr.pl",
|
"tests-pl/ffi_cstr.pl",
|
||||||
format!("LIB={dynlib_path:?}."),
|
format!("LIB={dynlib_path:?}."),
|
||||||
r#"13-[R,u,s,t, ,L,a,n,g]"#,
|
format!(r#"13-[R,u,s,t, ,L,a,n,g]-0-{}"#, u64::MAX).as_str(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user