Why does casting from a reference to a c_void pointer require a double cast? [duplicate] - casting

This question already has an answer here:
Why would it be necessary to perform two casts to a mutable raw pointer in a row?
(1 answer)
Closed 4 years ago.
When working with Foreign Function Interfaces (FFIs), I regularly see a double cast from reference-to-pointer-to-struct to pointer-to-pointer-to-void. For example, given an FFI-like function:
unsafe fn ffi(param: *mut *mut c_void) {}
The way to call this is:
struct foo;
let mut bar: *mut foo = ptr::null_mut();
unsafe { ffi(&mut bar as *mut *mut _ as *mut *mut c_void); }
Removing the intermediate cast yields this error:
error[E0606]: casting `&mut *mut foo` as `*mut *mut winapi::ctypes::c_void` is invalid
--> src\main.rs:36:18
|
36 | unsafe { ffi(&mut bar as *mut *mut c_void); }
|
I tried to get the compiler to tell me what the intermediate type is by forcing it into an obviously wrong type:
let mut bar: *mut foo = ptr::null_mut();
let mut test: u8 = &mut bar as *mut *mut _;
Which resulted in this error:
error[E0308]: mismatched types
--> src\main.rs:36:24
|
36 | let mut test: u8 = &mut bar as *mut *mut _;
| ^^^^^^^^^^^^^^^^^^^^^^^ expected u8, found *-ptr
|
= note: expected type `u8`
found type `*mut *mut _`
But *-ptr doesn't seem to be an actual type that I can put in place of _. Why is the intermediate as *mut *mut _ required, and what is the inferred type?
I found this question which is related (Working with c_void in an FFI) but it doesn't actually explain anything about the double cast.

If you have:
let mut bar: *mut foo = ptr::null_mut();
Then you take &mut bar, the type is &mut *mut foo. But you need *mut *mut foo, so you can simply coerce it by doing &mut *mut foo as *mut *mut _, where _ is inferred as foo (try typing it explicitly: *mut *mut foo). Once you have it as a raw pointer, then you are able to cast to *mut *mut c_void.
So to recap, the double cast is necessary to first coerce from a reference to a raw pointer, then from a raw pointer cast to a c_void, because you otherwise normally can't cast straight from a reference to a raw c_void pointer.
Fully typed example:
let mut bar: *mut foo = std::ptr::null_mut();
let mut_ref: &mut *mut foo = &mut bar;
let raw_ptr: *mut *mut foo = mut_ref as *mut *mut _;
let void_cast: *mut *mut c_void = raw_ptr as *mut *mut c_void;
unsafe { ffi(void_cast); }
Playground

Related

How to fix the OCaml compile error when using type annotations with functors?

I am new to OCaml and I am trying use functors. When I use the module type annotations with the functors, this results in a compile time error in my code.
When I remove the : Printable (from the module FromToString line) and the : ToString (from the module IntToString line) annotations, the following program compiles without error:
module type ToString =
sig
type t
val to_string: t -> string
end
module type Printable =
sig
type t
val print: t -> unit
end
module FromToString (S:ToString) : Printable =
struct
type t = S.t
let print a = print_string ( S.to_string a)
end
module IntToString : ToString =
struct
type t = int
let to_string = string_of_int
end
module PrintableInt = FromToString(IntToString)
let () = PrintableInt.print 3
However, when I add these annotations (as shown in the code) the compiler gives the following error:
File "Functor.ml", line 26, characters 28-29:
Error: This expression has type int but an expression was expected of type
PrintableInt.t = FromToString(IntToString).t
How can I use these annotations without causing a compile error?
The root issue is that your signature constraints make the resulting module far too opaque. When you constrain your functor result:
module FromToString (S:ToString) : Printable = ...
you are making the type t an abstract type, which can only be consumed by the to_string function and never been produced. In other words, a module of type Printable is unusable by itself.
When starting with functor, it is very often useful to look at the module type inferred by the compiler for the resulting module.
In the FromToString case, this is:
module FromToString (S:ToString) : sig
type t = S.t
val print: t -> unit
end = ...
You can see that the inferred module type of the result
sig
type t = S.t
val print: t -> unit
end
that it is quite similar to Printable except that now the type t is equal to the type t of the argument module S.
Thus, it is possible to reuse Printable to write the full module type of the result by adding a type equality with a with constraint:
module FromToString (S:ToString): Printable with type t = S.t = struct
type t = S.t
let print a = print_string ( S.to_string a)
end
The same issue appears for IntToString and can be fixed in a similar way:
module IntToString : ToString with type t = int =
struct
type t = int
let to_string = string_of_int
end
Then the compiler error is gone:
module PrintableInt = FromToString(IntToString)
let () = PrintableInt.print 3
One has to make the type t public, using the with notation:
module type ToString =
sig
type t
val to_string: t -> string
end
module type Printable =
sig
type t
val print: t -> unit
end
module FromToString (S:ToString) : Printable with type t = S.t =
struct
type t = S.t
let print a = print_string ( S.to_string a)
end
module IntToString : ToString with type t =int =
struct
type t = int
let to_string = string_of_int
end
module PrintableInt = FromToString(IntToString)
let () = PrintableInt.print 3

Losing type precision from module signature

Let's say I had a simple module MyFoo that looks something like this
module MyFoo = struct
type t =
| A of string
| B of int
let to_string thing =
match thing with
| A str -> str
| B n -> string_of_int n
end
With this definition, it works great and as expected — I can do something like
let _ = MyFoo.A "";;
- : MyFoo.t = MyFoo.A ""
without any problems.
Now maybe I want to create a functor that consumes modules with this structure, so I define a module signature that describes generally what this looks like and call it BaseFoo
module type BaseFoo = sig
type t
val to_string : t -> string
end
If I redefine MyFoo the same way but giving it this signature like
module MyFoo : BaseFoo = struct
type t =
| A of string
| B of int
let to_string thing =
match thing with
| A str -> str
| B n -> string_of_int n
end
I lose the precision of its type t (is there a better way to describe what happens here?) — for example:
let _ = MyFoo.A "";;
Error: Unbound constructor MyFoo.A
What exactly is going on here and why does it happen? Is there a canonical way for dealing with this kind of problem (besides just leaving off the signature)?
I've tried manually including the signature and the specific type type definition too but get a different kind of error (this probably isn't the right approach).
module MyFoo : sig
include BaseFoo
type t = | A of string | B of int
end = struct
type t =
| A of string
| B of int
let to_string thing =
match thing with
| A str -> str
| B n -> string_of_int n
end
let _ = MyFoo.A "test";;
Error: Multiple definition of the type name t.
Names must be unique in a given structure or signature.
You don't need the signature
What is going on is pretty much what you describe: giving MyFoo the BaseFoo signature in its definition restricts it to the signature.
Why? Because this is what specifying a signature at this place is for. The canonical solution is to leave of the signature (usually, letting the signature definition next to the module definition will be clear enough for the reader).
Note that when you call MyFoo on your functor, the signature will be checked. My usual choice is to rely on that.
A few workarounds
Given what you've tried, I guess this could be interesting to you:
module type BaseFoo = sig ... end
module MyFoo = struct ... end
module MyFooHidden : BaseFoo = MyFoo (* Same as defining MyFoo : BaseFoo *)
module MyFooWithType :
BaseFoo with type t = MyFoo.t
= MyFoo (* What you want *)
The with type t = t' clause allows you to annotate a module signature to add type information to it. It is quite useful, especially when dealing with functors. See here for more information.
MyFooHidden may seem useless, but you can see it as a check that MyFoo has the right signature. You can still use MyFoo however you want after all. MyFooWithType is actually (a bit) less useful because if you change your signature to add a type you'd want exported, you'd need to add the export here too.
Using include
As for your include try. Well, nice try! You were almost there:
module MyFoo : sig
type t = A of string | B of int
include BaseFoo with type t := t
end
The with type t := t' is a bit different in that it doesn't perform an equality but a replacement. The type t definition is removed from the BaseFoo signature altogether and all instances are replaced with your own t, that way you don't get any double definition problem. See here for more details.
As you point out, this is probably not the approach you want, as you no longer easily know that MyFoo is indeed a BaseFoo.

Matching C-style array passed as void* with GMock

I'm trying to mock such function:
int write(int fd, const void* buffer, size_t size, bool something)
I want to check the correctness of data passed with buffer (first and last argument are not important for the test).
There are few nice matchers to help us with that, namely ElementsAreArray. If the pointer was e.g. char*, then it's simple:
EXPECT_CALL(myMock, write(_, NotNull(), expectedSize, _)
.With(Args<1,2>(ElementsAreArray(dummyArray));
Problem: void* can't be dereferenced. Thus, it's can't be matched with ElementsAreArray.
I tried the following:
EXPECT_CALL(myMock, write(_, NotNull(), expectedSize, _)
.With(Args<1,2>(MatcherCast<::testing::tuple<const char*, size_t>>(ElementsAreArray(dummyArray)));
but it fails static_assert within MatcherCast - T_must_be_implicitly_convertible_to_U
It is possible to write own matcher to avoid that, but it feels clumsy. The below one works, but I prefer to avoid writing my own matchers:
MATCHER_P2(EqualToArray, compareArray, n, "")
{
const char *arr = static_cast<const char*>(arg);
for (size_t i = 0; i < n; ++i)
{
if (arr[i] != compareArray[i])
{
return false;
}
}
return true;
}
EXPECT_CALL(myMock, write(_, EqualToArray(dummyArray, expectedSize), expectedSize, _);
EDIT: I'm sorry, I probably haven't made myself clear.
I understand that casting from void* to any other pointer type is not much of problem. But this requires us to have a function or user defined matcher, for example like the one I've written, and I'm trying to avoid having user defined matchers, if it is possible to use already defined GMock matchers.
So, the more specific question is:
Is it possible to cast void* to a char* within EXPECT_CALL macro?
Or another words:
Is it possible to make the following snippet work without changing ElementsAreArray() to user-defined matcher:
EXPECT_CALL(myMock, write(_, NotNull(), expectedSize, _)
.With(Args<1,2>(ElementsAreArray(dummyArray));
Edit: I found a way to do this without a custom matcher, following the information in this answer. It involves creating an intermediate class and using 3 (count 'em) nested SafeMatcherCasts:
#include <tuple>
#include <gmock/gmock.h>
// This is a matcher like ElementsAreArray, but it allows you to match against a void *.
template <typename T>
testing::Matcher<std::tuple<const void*, size_t>> elementsAreArrayVoidPointer(
const T* ptr, size_t size) {
class TupleConverter : public std::tuple<const T*, size_t> {
public:
TupleConverter(const std::tuple<const void*, size_t>& t)
: std::tuple<const T*, size_t>(static_cast<const T*>(std::get<0>(t)), std::get<1>(t)) {}
};
return testing::SafeMatcherCast<std::tuple<const void*, size_t>>(
testing::SafeMatcherCast<TupleConverter>(
testing::SafeMatcherCast<std::tuple<const T*, size_t>>(
testing::ElementsAreArray(ptr, size))));
}
You can use it as follows:
EXPECT_CALL(mock_cstdio, fwrite(_, 1, _, _))
.With(Args<0, 2>(elementsAreArrayVoidPointer(my_char_p, my_size)));
Previous Answer:
I don't think this is possible.
From googlemock's cookbook:
... MatcherCast works as long as you can static_cast type T to type U.
In this context, T is tuple<void*, size_t> (what you're trying to match) and U is tuple<char*, size_t> (what your ElementsAreArray matcher accepts).
As discussed in this question, tuple<void*, size_t> to tuple<char*, size_t> is not a valid static_cast. (Even though void* to char* is a valid static_cast!)
So I think in this case you need to write a custom matcher.
Note: The T_must_be_implicitly_convertible_to_U message is a red-herring. You see that because googlemock also tries to use SafeMatcherCast and fails, as expected. This is the real error (from the template instantiation that we wish would work, but doesn't):
external/gtest/googlemock/include/gmock/gmock-matchers.h:577:73: error: invalid static_cast from type 'std::tuple<void*, long unsigned int>' to type 'const std::tuple<char*, long unsigned int>&'
return source_matcher_.MatchAndExplain(static_cast<U>(x), listener);

Why doesn’t assigning an int to an f32 variable compile?

Why does rust consider assigning an int value to a float variable as an error even though there is no narrowing of value?
fn main() {
let i: f32 = 1i;
}
In Rust, all such casting must be done explicitly:
fn main() {
let i = 1i as f32;
}
This is a simple design decision.
Also the conversion from int to f32 is not lossless, still more reason for needing such things to be explicit.

Confusing type declaration?

I haven't worked with SML in awhile and I came across this line of code:
type memory = string -> int;
Does this define 'memory' to be a function which takes a string a returns an int, or something else entirely? I've searched for a similar declaration but I can't seem to find one or figure out what it does.
When I put it into SML/NJ, I just get this:
- type memory = string -> int;
type memory = string -> int
memory is not a function , it's just an abbreviation for a type that is a function that takes as input a string and returns an int.
So whenever you would like to write that something is of type string->int you can just write it's of type memory.
For example instead of writing:
- fun foo(f : string->int, s) = f s;
val foo = fn : (string -> int) * string -> int
you could write:
- fun foo( f: memory, s) = f s;
val foo = fn : memory * string -> int
Such type declarations can make your code more readable (e.g. instead of writing that a pair x is of type int*int like (x: int*int), you can just create an abbreviation type pair = int*int and then you can write that x is of type pair like this (x: pair)).