How to instant casting in eiffel - eiffel

I have following code in my do~end scope of some feature:
add (tempA, tempB)
Here, type of arguments are:
tempA: A
tempB: B
Both are declared as local variable.
And, here is prototype of feature add:
add (a: A; b: B)
The compile error I get:
Formal argument type: Generic #1
Actual argument type: detachable Generic #1
How can I instant cast type of "tempA" and "tempB" to Generic type from detachable Generic type? so that I can pass them to add feature.
I am not changing prototype, but I can change type of "tempA" and "tempB" though.

Until initialized the local variables are treated as detachable. They can be initialized either by assigning values to them
tempA := exprA -- exprA should return a value of type A
tempB := exprB -- exprB should return a value of type B
(e.g. exprA could be a formal argument of the feature in question) or by creating the objects directly:
create tempA
create tempB
(possibly with creation procedures, if necessary, i.e. create tempA.make ...).

Related

Forward declaration of a function typedef in C

I have a nagging suspicion that this has been asked before, but I'm not finding it...
Suppose I have a typedef for function A that takes a pointer to a function with typedef B, which in turn takes a function of typedef A. If one of these was a struct, I know how I would handle the forward declaration, but for functions I don't know the syntax. Is there one?
I want to be able to do:
typedef void (*function_A_t)(function_B_t f_B);
typedef void (*function_B_t)(function_A_t f_A);
Any hints? Even better, a reference? Incidentally this actually just happened for me, but I was able to fix it another way, although this would actually smoother (better decoupling, less chance of next guy messing it up) if it's possible.
You can do this by taking advantage of the fact that C specifies that a function declaration with no arguments means it takes an indeterminate number of arguments.
So you could do it as follows:
typedef void (*function_A_t)(void (*)());
typedef void (*function_B_t)(function_A_t f_A);
Which allows the following to compile:
void A(function_B_t b)
{
b(A);
}
void B(function_A_t a)
{
a(B);
}
int main()
{
function_A_t a = A;
function_B_t b = B;
a(B);
b(A);
return 0;
}
Section 6.7.6.3p15 of the C standard states the following regarding the compatibility of function types:
For two function types to be compatible, both shall specify
compatible return types. Moreover, the parameter type lists, if
both are present, shall agree in the number of parameters and
in use of the ellipsis terminator; corresponding parameters
shall have compatible types. If one type has a parameter type list
and the other type is specified by a function declarator that is
not part of a function definition and that contains an empty
identifier list, the parameter list shall not have an ellipsis
terminator and the type of each parameter shall be compatible with
the type that results from the application of the default
argument promotions. If one type has a parameter type list and the
other type is specified by a function definition that contains a
(possibly empty) identifier list, both shall agree in the number
of parameters, and the type of each prototype parameter shall
be compatible with the type that results from the application
of the default argument promotions to the type of the
corresponding identifier. (In the determination of type
compatibility and of a composite type, each parameter declared
with function or array type is taken as having the adjusted type
and each parameter declared with qualified type is taken as having the
unqualified version of its declared type.)
The part in bold above specifies that void (*)() is compatible with void (*)(function_B_t)

Why can arrays not be used _directly_ when calling a variadic function in Go?

What is the reason that, given a (variadic) function
func varargs(n ...int) {}
it can be called like
varargs(1, 2, 3, 4) // Fixed number of arguments
but not with an array:
a := [4]int{1, 2, 3, 4} // Fixed number of elements
varargs(a...) // Error: cannot use (type [4]int) as type []int in argument
I understand why
var s []int = a
wouldn't work: it prevents accidental misuse, requiring manual slicing:
s := a[:]
But why does this restriction extend to calls to variadic functions?
Bonus question:
Conversely, why would calling
func fourargs(w, x, y, z int) {}
with a 4-element array like
fourargs(a...) // Error: not enough arguments in call have ([4]int...)
// want (int, int, int, int)
also be forbidden?
It can be type-checked at compile time.
Spec: Passing arguments to ... parameters:
If the final argument is assignable to a slice type []T, it may be passed unchanged as the value for a ...T parameter if the argument is followed by .... In this case no new slice is created.
So when you have a slice and you pass it as the value of the variadic parameter, no new slice is created, it is just assigned.
If you have an array, that is a different type, that is not assignable to a slice type. Therefore it is not allowed.
You must first slice the array, which you can do without an intermediate variable:
a := [4]int{1, 2, 3, 4}
varargs(a[:]...)
Yes, you could say this automatic slicing could happen automatically / internally. Why this isn't allowed is opinion based (and belongs to the authors of Go). Basically, in Go arrays are secondary. Slices are the way to go. You should have a slice in the first place, which you can pass and you don't have a problem. See related questions: Why have arrays in Go? and Slicing a slice pointer passed as argument.

Does ccall really convert arguments passed by pointer?

Considering a dynamic library with this native function that returns the sum of all even (32-bit unsigned) numbers in an array:
uint32_t sum_of_even(const uint32_t *numbers, size_t length);
The implementation of the function above was written in Rust as below, and packaged into a C dynamic library.
use libc::size_t;
use std::slice;
#[no_mangle]
pub extern "C" fn sum_of_even(n: *const u32, len: size_t) -> u32 {
let numbers = unsafe {
assert!(!n.is_null());
slice::from_raw_parts(n, len as usize)
};
numbers
.iter()
.filter(|&v| v % 2 == 0)
.sum()
}
I wrote the following Julia (v1.0.1) wrapper function:
lib = Libdl.dlopen(libname)
sumofeven_sym = Libdl.dlsym(lib, :sum_of_even)
sumofeven(a) = ccall(
sumofeven_sym,
UInt32,
(Ptr{UInt32}, Csize_t),
a, length(a)
)
The documentation states multiple times that arguments in ccall are converted to become compatible with the C function prototype (emphasis mine):
Each argvalue to the ccall will be converted to the corresponding argtype, by automatic insertion of calls to unsafe_convert(argtype, cconvert(argtype, argvalue)). (See also the documentation for unsafe_convert and cconvert for further details.) In most cases, this simply results in a call to convert(argtype, argvalue).
And moreover, that when passing an Array{T} by Ptr{U} to a C function, the call is invalidated if the two types T and U are different, since no reinterpret cast is added (section Bits Types):
When an array is passed to C as a Ptr{T} argument, it is not reinterpret-cast: Julia requires that the element type of the array matches T, and the address of the first element is passed.
Therefore, if an Array contains data in the wrong format, it will have to be explicitly converted using a call such as trunc(Int32, a).
However, this is seemingly not the case. If I deliberately pass an array with another type element:
println(sumofeven(Float32[1, 2, 3, 4, 5, 6]))
The program calls the C function with the array passed directly, without converting the values nor complaining about the different element types, resulting in either senseless output or a segmentation fault.
If I redefine the function to accept a Ref{UInt32} instead of a Ptr{UInt32}, I am prevented from calling it with the array of floats:
ERROR: LoadError: MethodError: Cannot `convert` an object of type Array{Float32,1} to an object of type UInt32
Closest candidates are:
convert(::Type{T<:Number}, !Matched::T<:Number) where T<:Number at number.jl:6
convert(::Type{T<:Number}, !Matched::Number) where T<:Number at number.jl:7
convert(::Type{T<:Integer}, !Matched::Ptr) where T<:Integer at pointer.jl:23
...
However, Ref was not designed for arrays.
Making the example work with Ptr{UInt32} requires me to either specify Array{UInt32} as the type of input a (static enforcement), or convert the array first for a more flexible function.
sumofeven(a:: Array{UInt32}) = ccall( # ← either this
sumofeven_sym,
UInt32,
(Ptr{UInt32}, Csize_t),
convert(Array{UInt32}, a), # ← or this
length(a))
With that, I still feel that there is a gap in my reasoning. What is the documentation really suggesting when it says that an array passed to C as a Ptr{T} is not reinterpret-cast? Why is Julia letting me pass an array of different element types without any explicit conversion?
This turned out to be either a bug in the core library or a very misguided documentation, depending on the perspective (issue #29850). The behavior of the function unsafe_convert changed from version 0.4 to 0.5, in a way that makes it more flexible than what is currently suggested.
According to this commit, unsafe_convert changed from this:
unsafe_convert(::Type{Ptr{Void}}, a::Array) = ccall(:jl_array_ptr, Ptr{Void}, (Any,), a)
To this:
unsafe_convert{S,T}(::Type{Ptr{S}}, a::AbstractArray{T}) = convert(Ptr{S}, unsafe_convert(Ptr{T}, a))
For arrays, this relaxed implementation will enable a transformation from an array of T to a pointer of another type S. In practice, unsafe_convert(cconvert(array)) will reinterpret-cast the array's base pointer, as in the C++ nomenclature. We are left with a dangerously reinterpreted array across the FFI boundary.
The key takeaway is that one needs to take extra care when passing arrays to C functions, as the element type of an array in a C-call function parameter is not statically enforced. Use type signatures and/or explicit conversions where applicable.

Passing structure from C to Ada

I need to pass a structure from C to Ada in an Ada binding application. Thus, I have declared the structure in both Ada and C so that both the source sides can decipher the structure composition.
In C,
typedef struct {
int Status_Code;
int Error_Code;
} Edit_Result_Type;
In Ada,
type Edit_Result_Rec_Type is
record
Status : Integer;
Error_Code : Integer;
end record;
pragma Convention (Convention => C,
Entity => Edit_Result_Rec_Type);
for Edit_Result_Rec_Type use
record
Status at 0 range 0 .. 31;
Error_Code at 0 range 32 .. 63;
end record;
type Edit_Result_Rec_Type_Ptr is access all Edit_Result_Rec_Type;
When I am passing the structure from C to Ada through call by reference, I wanted to know:
Is it ok if I declare an "access all" vector type for the structure (as done above - Edit_Result_Rec_Type_Ptr) in Ada and use it directly as a formal parameter in Ada function. For Eg:
procedure Process_Data (Edit_Result_Ptr : in out Edit_Result_Rec_Type_Ptr) is
begin
Edit_Result_Ptr.Status := 1;
Edit_Result_Ptr.Error_Code := 0;
end Process_Data;
Is this approach FATAL? I know it is, just wanted to know "how" in depth!
Any other (better) approaches for passing through call by reference? I believe I can pass it as a "System.Address" parameter and do an "unchecked conversion" into Edit_Result_Rec_Type_Ptr in a local vector inside the Ada function and then read/write record members? Does this approach has any fatalities?
When interfacing Ada and C, you should really read the RM, Annex B.3, which says:
An Ada parameter of a record type T, of any mode, other than an in parameter of a type of convention C_Pass_By_Copy, is passed as a t* argument to a C function, where t is the C struct corresponding to the Ada type T.
So, in your procedure, just do:
procedure Process_Data (Edit_Result : in out Edit_Result_Rec_Type) is
begin
Edit_Result.Status := 1;
Edit_Result.Error_Code := 0;
end Process_Data;
and
pragma Export(C, Process_Data);
(or use the aspect, if Ada 2012)
That being said, you shouldn't use Integer in your record definition, Interfaces.C.int is the way to go:
type Edit_Result_Rec_Type is
record
Status : Interfaces.C.int;
Error_Code : Interfaces.C.int;
end record;
which will match the C int on your platform (assuming your C compiler is compatible with the Ada compiler)
As for your questions:
That would work, but why mess around with pointers?
No, that wouldn't work, access types (and access values) in Ada are not addresses. Converting a System.Address to an access value requires System.Address_To_Access_Conversions, but again, why mess around with pointers?

what does this statement in c means?

struct abc
{
//some members
}arrayOf[10];
struct def
{
//some data memebers
}obj;
typedef void (*abc) (obj)
I am not sure what does the statement typedef void (*abc) (obj) implies. Please consider that I am new to this.
Even ignoring the missing semicolon, it doesn't mean anything; it's an error.
If obj were a type name, it would define abc as an alias for the type void (*)(obj), i.e., as a pointer to a function taking a single argument of type obj and returning void.
But since obj is an object name, not a type name, that's not actually what it means.
When I compile it with gcc, I get a warning:
warning: parameter names (without types) in function declaration
When I compile with -pedantic-errors, the warning becomes a fatal error.
An old-style (non-prototype) function definition can legally specify names, but not types, for arguments:
void old_style_func(obj)
/* obj is implicitly of type int */
{
}
But that form is not valid for a function declaration. In a declaration, a single identifier between the parentheses has to be a type name, not the name of a parameter -- which makes the declaration a prototype.
gcc's error message implies that it's trying to interpret it as if it were the beginning of an old-style definition, and then deciding that it's invalid because it's just a declaration.
The bottom line is that you should pay close attention to compiler warnings.
We could speculate about what was intended. Perhaps obj was meant to be a type name, and this:
struct def
{
//some data memebers
}obj;
was supposed to be:
typedef struct def
{
// some data members
} obj;
Or perhaps a type name was accidentally omitted, and the last line should have been:
typedef void (*abc) (struct def obj);
though in that case the name obj is being used twice for different purposes (legal, but confusing). But without more context, it's impossible to be sure how to "fix" it.
Where did this code come from? Are you sure you've shown us the exact code? What happened when you tried to compile it?
it defines the type abc as a pointer to a function that accepts one argument of type int called obj and returns nothing (void).
It introduces a new name abc for the type of a pointer to a function that takes an obj and returns void. The type of a pointer-to-function is always specified in this roundabout way in a declaration:
return-type (* name-being-declared)(parameter-list)
Incidentally, the * in the declaration is probably unnecessary. Function types always magically turn into pointer-to-function types when you need them (like how an array type magically turns into a pointer-to-element type), and you can use a function type directly (instead of a pointer-to-function type) to declare a new function.
As others have pointed out, the context you give doesn't have a type named obj, only an object named obj. If this code compiles, there must be another type named obj defined somewhere else, in code you haven't given.

Resources