I'm trying to create a proc that returns a custom tuple that contains a single element that is a proc type i.e.
type
CustomTuple = tuple
foo: proc(input: int): int
proc createCustomTuple(): CustomTuple =
(foo: proc(input: int): int = 10)
However, when I compile this I get the following error (I am compiling with Nim Version 1.2.6 on Windows).
Error: type mismatch: got <tuple[foo: proc (input: int):
int{.noSideEffect, gcsafe, locks: 0.}]> but expected 'CustomTuple =
tuple[foo: proc (input: int): int{.closure.}]'
So the compiler thinks I am returning a regular tuple and not a CustomTuple but I have no idea how to change this to make it work. The documentation for tuples in the Nim manual show custom tuples being constructed in the way that I am doing it and I couldn't find any examples of returning a custom tuple from a proc.
If I change my CustomTuple definition to contain types that aren't procs then it compiles successfully so it appears it has something to do my custom tuple containing a proc that is causing this to fail to compile.
Can anyone explain why the above code is not compiling?
I think the reason my original code isn't working is because Nim is unable to convert the proc to a closure automatically when it is added to a tuple. There is some discussion around this in the Nim forums.
As the proc is not converted to a closure the compiler is unable to determine that the tuple being returned is a CustomTuple because the types don't match which explains the error message.
So when packing a proc in a tuple you need to explicitly convert it to a closure. This can be done by explicitly casting the proc like this:
type
CustomTuple = tuple
foo: proc(input: int): int
proc createCustomTuple(): CustomTuple =
(foo: (proc(input:int):int)(proc(input: int): int = 10))
or by adding a {.closure.} pragma like this (which I think is much cleaner).
type
CustomTuple = tuple
foo: proc(input: int): int
proc createCustomTuple(): CustomTuple =
(foo: proc(input: int): int {.closure.} = 10)
If you don't want to do either of these you can assign the proc to the foo property of the implicit result variable as per Salewski's answer.
This also explains why Salewski's original solution of assigning the proc to the foo property of the implicit result variable worked; the compiler is able to automatically convert the proc to a closure in that case.
type
CustomObject = object
foo: proc(input: int): int
proc createCustomObject(): CustomObject =
#(foo: proc(input: int): int = 10)
#result.foo = proc(input: int): int = 10
CustomObject(foo: proc(input: int): int = input * 2)
var x = createCustomObject()
echo x.foo(2)
Related
Using the OUnit unit testing framework in OCaml, I would like to test that the result of evaluating a function is an instance of a specified type.
Defining such a test in Python's PyTest would be done as follows:
def test_foo():
assert isinstance(foo(2), int)
How can this logic be translated to OUnit? That is, how are assertions of type membership specified?
I'm aware that, assuming the function under test is annotated with the proper type signature, this testing might be unnecessary.
This is the job of a type checker, and it is made automatically during the compilation (at static time). The type checker (i.e., the compiler) guarantees that all values that are created by a function has the same type, and the type is defined statically at the compilation time. You will not be able to compile a function, that creates values of different types, as you will get a type error during the compilation. This is an essential property of all statically typed languages, e.g., Java, C and C++ also has the same property.
So, probably, you're using are confusing terminology. It might be the case, that what you're actually trying to test, is that the value belongs to a particular variant of a sum type. For example, if you have a sum type called numbers defined as:
type t =
| Float of float
| Int of int
and you would like to test that function truncate, defined as
let truncate = function
| Float x -> Int (truncate x)
| x -> x
always returns the Int variant, then you can do this as follows:
let is_float = function Float _ -> true | _ -> false
let is_int = function Int _ -> true | _ -> false
assert (is_int (truncate 3.14))
I have the following c++ code :
#include <OAIdl.h> // for VARIANT, BSTR etc
__declspec(dllexport) void __stdcall updatevar(VARIANT * x)
{
double nb = 3.0;
++nb;
}
with a function doing (almost) nothing (to avoid warnings)
and a .def file :
LIBRARY tmp0
EXPORTS
updatevar #1LIBRARY
I compile this with visual studio 2013 into a dll that I reference as follows in excel-2013's VBA :
Declare Sub updatevar Lib "C:\path\to\thedll.dll" (ByRef x As Variant)
and that I use like this :
Public Sub DoIt()
Dim r As Range
Set r = ActiveWorkbook.Sheets("Sheet1").Range("B2:C4")
Dim var As Variant
var = r.Value
Call updatevar(var)
End Sub
where the 6-cells excel range B2:C4 contains strings, dates, doubles and ints/longs.
I put a breakpoint in c++ code to inspect the variant pointed to that I receive, as remarked that the type of its 6 elements is always rightly resolved : dates go to a vt (variant type VT_DATE) equal to 7, doubles to a vt (variant type VT_R8) equal to 5, strings go to a vt (variant type VT_BSTR) of 8, except for ints/longs, that are mapped to VT_R8 and treated as doubles.
At the beginning I thought it was a c++ problem but, already inspecting the range r in the VBA code, and its Value2 field, showed to me that all ints/longs were treated in VBA as Variant/Double and not Variant/Long, and I have no idea why this is happening.
Note. I put c++ and dll tags as the people interested in these tags may also help given the context involving exchanging VARIANT's between c++ and VBA.
Remark. "Downcasting" from double to int is not an option, especially as VARIANT is supposed to know about ints/longs (VT_I4 = 2 and VT_I4 = 3 do exist.)
typedef struct _FILE_OBJECTID_INFORMATION {
LONGLONG FileReference;
UCHAR ObjectId[16];
union {
struct {
UCHAR BirthVolumeId[16];
UCHAR BirthObjectId[16];
UCHAR DomainId[16];
} DUMMYSTRUCTNAME;
UCHAR ExtendedInfo[48];
} DUMMYUNIONNAME;
} FILE_OBJECTID_INFORMATION, *PFILE_OBJECTID_INFORMATION;
How to translate such a union to Delphi?
The Pascal equivalent of a C union is known as a variant record.
A record type can have a variant part, which looks like a case
statement. The variant part must follow the other fields in the record
declaration.
To declare a record type with a variant part, use the following
syntax:
type recordTypeName = record
fieldList1: type1;
...
fieldListn: typen;
case tag: ordinalType of
constantList1: (variant1);
...
constantListn: (variantn);
end;
The first part of the declaration - up to the reserved word case - is
the same as that of a standard record type. The remainder of the
declaration - from case to the optional final semicolon - is called
the variant part. In the variant part,
tag is optional and can be any valid identifier. If you omit tag, omit the colon (:) after it as well.
ordinalType denotes an ordinal type.
Each constantList is a constant denoting a value of type ordinalType, or a comma-delimited list of such constants. No value can
be represented more than once in the combined constantLists.
Each variant is a semicolon-delimited list of declarations resembling the fieldList: type constructions in the main part of the
record type. That is, a variant has the form:
fieldList1: type1;
...
fieldListn: typen;
where each fieldList is a valid identifier or comma-delimited list of
identifiers, each type denotes a type, and the final semicolon is
optional. The types must not be long strings, dynamic arrays, variants
(that is, Variant types), or interfaces, nor can they be structured
types that contain long strings, dynamic arrays, variants, or
interfaces; but they can be pointers to these types.
Records with variant parts are complicated syntactically but
deceptively simple semantically. The variant part of a record contains
several variants which share the same space in memory. You can read or
write to any field of any variant at any time; but if you write to a
field in one variant and then to a field in another variant, you may
be overwriting your own data. The tag, if there is one, functions as
an extra field (of type ordinalType) in the non-variant part of the
record.
As for the rest, it's pretty routine: LONGLONG is a 64 bit integer, and UCHAR is unsigned char, or AnsiChar in Delphi.
type
TFileObjectIDInformation = record
FileReference: Int64;
ObjectID: array[0..15] of AnsiChar;
case Integer of
0:
(
BirthVolumeId: array[0..15] of AnsiChar;
BirthObjectId: array[0..15] of AnsiChar;
DomainId: array[0..15] of AnsiChar;
);
1:
(ExtendedInfo: array[0..47] of AnsiChar);
end;
It's possible that Byte may be more appropriate than AnsiChar. It's a bit hard to tell of course because C, unlike Pascal, doesn't have separate types for Byte and AnsiChar. But these arrays look to me as though they would be read as text so my guess is that AnsiChar would be more appropriate.
Similar structure can be found in JEDI API Lib:
_FILE_OBJECTID_BUFFER = record
//
// This is the portion of the object id that is indexed.
//
ObjectId: array [0..15] of BYTE;
//
// This portion of the object id is not indexed, it's just
// some metadata for the user's benefit.
//
case Integer of
0: (
BirthVolumeId: array [0..15] of BYTE;
BirthObjectId: array [0..15] of BYTE;
DomainId: array [0..15] of BYTE);
1: (
ExtendedInfo: array [0..47] of BYTE);
end;
I am experiencing some very strange things right now.
When I am passing a struct from C++ to a Delphi DLL as a parameter everything works fine.
However, as soon as I want to receive a record as a result I either get wrong values or exceptions.
I deactivated the alignment of the record so that passing them should work!
Heres the code!
Delphi DLL:
TSimpleRecord = packed record
Nr1 : Integer;
Nr2 : Integer;
end;
//...
function TTest() : TSimpleRecord; cdecl;
begin
Result.Nr1 := 1;
Result.Nr2 := 201;
ShowMessage(IntToStr(SizeOf(Result)));
end;
C++ call :
#pragma pack(1)
struct TSimpleRecord
{
int Nr1;
int Nr2;
};
//...
typedef TSimpleRecord (__cdecl TestFunc)(void);
TestFunc* Function;
HINSTANCE hInstLibrary = LoadLibrary("Reactions.dll");
if (hInstLibrary)
{
Function = (TestFunc*)GetProcAddress(hInstLibrary, "TTest");
if (Function)
{
TSimpleRecord Result = {0};
Result = Function();
printf("%d - %d - %d", sizeof(Result), Result.Nr1, Result.Nr2);
cin.get();
}
}
I have got no idea why passing this record as a parameter works but not as a result of a function!?
Can anybody help me?`
Thanks
PS: As I said, both C++ and Delphi show that the record is 8 bytes large.
Some compilers will return struct types (possibly depending on the size) in registers, others will add a hidden extra parameter where the result should be stored. Unfortunately, it looks like you're dealing two compilers that do not agree on how to return these.
You should be able to avoid the problem by explicitly using an out parameter instead.
procedure TTest(out Result: TSimpleRecord); cdecl;
begin
Result.Nr1 := 1;
Result.Nr2 := 201;
end;
Do not forget to update the C++ code accordingly.
Rudy Velthuis has written about this:
This showed me that the ABCVar struct was returned in the registers EDX:EAX (EDX with the top 32 bits, and EAX with the lower ones). This is not what Delphi does with records at all, not even with records of this size. Delphi treats such return types as extra var parameters, and does not return anything (so the function is actually a procedure).
[...]
The only type which Delphi returns as EDX:EAX combination is Int64.
which suggests that an alternative way to avoid the problem is
function TTest() : Int64; cdecl;
begin
TSimpleRecord(Result).Nr1 := 1;
TSimpleRecord(Result).Nr2 := 201;
end;
Note that Delphi allows such type punning even in situations where the behaviour would be undefined in C++.
Delphi does not follow the platform standard ABI for return values. The standard ABI passes return values to the caller by value. Delphi treats the return value as an implicit extra var parameter, passed after all other parameters. The documentation describes the rules.
You can change your calling code to match that. Pass an extra reference to struct parameter in your C++ function.
typedef void (__cdecl TestFunc)(TSimpleRecord&);
If you are going to do this on the C++ side, you would be best doing the same change on the Delphi side for clarity.
Since Delphi does not follow the platform standards for return values I suggest you restrict yourself to types that are compatible with other tools. That means integral values up to 32 bits, pointers and floating point values.
As a general rule of thumb, do not pack records. If you do so you will have mis-alignment which affects performance. For the record in the question, there will be no padding anyway since both fields are the same size.
I can do this on initialization for a struct Foo:
Foo foo = {bunch, of, things, initialized};
but, I can't do this:
Foo foo;
foo = {bunch, of, things, initialized};
So, two questions:
Why can't I do the latter, is the former a special constructor for initialization only?
How can I do something similar to the second example, i.e. declare a bunch of variables for a struct in a single line of code after it's already been initialized? I'm trying to avoid having to do this for large structs with many variables:
Foo foo;
foo.a = 1;
foo.b = 2;
foo.c = 3;
//... ad infinitum
Try this:
Foo foo;
foo = (Foo){bunch, of, things, initialized};
This will work if you have a good compiler (e.g. GCC).
Update: In modern versions of C (but not C++), you can also use a compound literal with designated initializers, which looks like this:
foo = (Foo){ .bunch = 4, .of = 2, .things = 77, .initialized = 8 };
The name right after the "." should be the name of the structure member you wish to initialize. These initializers can appear in any order, and any member that is not specified explicitly will get initialized to zero.
The first is an aggregate initializer - you can read up on those and tagged initializers at this solution:
What is tagged structure initialization syntax?
It is a special initialization syntax, and you can't do something similar after initialization of your struct. What you can do is provide a member (or non-member) function to take your series of values as parameters which you then assign within the member function - that would allow you to accomplish this after the structure is initialized in a way that is equally concise (after you've written the function the first time of course!)
In C++11 you can perform multiple assignment with "tie" (declared in the tuple header)
struct foo {
int a, b, c;
} f;
std::tie(f.a, f.b, f.c) = std::make_tuple(1, 2, 3);
If your right hand expression is of fixed size and you only need to get some of the elements, you can use the ignore placeholder with tie
std::tie(std::ignore, f.b, std::ignore) = some_tuple; // only f.b modified
If you find the syntax std::tie(f.a, f.b, f.c) too code cluttering you could have a member function returning that tuple of references
struct foo {
int a, b, c;
auto members() -> decltype(std::tie(a, b, c)) {
return std::tie(a, b, c);
}
} f;
f.members() = std::make_tuple(1, 2, 3);
All this ofcourse assuming that overloading the assignment operator is not an option because your struct is not constructible by such sequence of values, in which case you could say
f = foo(1, 2, 3);
Memory Footprint - Here is an interesting i386 addition.
After much hassle, using optimization and memcpy seems to generate the smallest footprint using i386 with GCC and C99. I am using -O3 here. stdlib seems to have all sorts of fun compiler optimizations at hand, and this example makes use of that (memcpy is actually compiled out here).
Do this by:
Foo foo; //some global variable
void setStructVal (void) {
const Foo FOO_ASSIGN_VAL = { //this goes into .rodata
.bunch = 1,
.of = 2,
.things = 3,
.initialized = 4
};
memcpy((void*) &FOO_ASSIGN_VAL, (void*) foo, sizeof(Foo));
return;
}
Result:
(.rodata) FOO_ASSIGN_VAL is stored in .rodata
(.text) a sequence of *movl FOO_ASSIGN_VAL, %registers* occur
(.text) a sequence of movl %registers, foo occur
Example:
Say Foo was a 48 field struct of uint8_t values. It is aligned in memory.
(IDEAL) On a 32-bit machine, this COULD be as quick as 12 MOVL instructions of immediates out to foo's address space. For me this is 12*10 == 120bytes of .text in size.
(ACTUAL) However, using the answer by AUTO will likely generate 48 MOVB instructions in .text. For me this is 48*7 == 336bytes of .text!!
(SMALLEST*) Use the memcpy version above. IF alignment is taken care of,
FOO_ASSIGN_VAL is placed in .rodata (48 bytes),
12 MOVL into %register
12 MOVL outof %registers are used in .text (24*10) == 240bytes.
For me then this is a total of 288 bytes.
So, for me at least with my i386 code,
- Ideal: 120 bytes
- Direct: 336 bytes
- Smallest: 288 bytes
*Smallest here means 'smallest footprint I know of'. It also executes faster than the above methods (24 instructions vs 48). Of course, the IDEAL version is fastest & smallest, but I still can't figure that out.
-Justin
*Does anyone know how to get implementation of 'IDEAL' above? It is annoying the hell out of me!!
If you don't care too much about efficiency, you could double assign: i.e. create a new instance of the structure using aggregate initialization, and then copy it over:
struct Foo foo;
{
struct Foo __tmp__ = {bunch, of, things, initialized};
foo = __tmp__;
}
Make sure you keep the portion wrapped in {}s so as to discard the unnecessary temporary variable as soon as it's no longer necessary.
Note this isn't as efficient as making, e.g., a 'set' function in the struct (if c++) or out of the struct, accepting a struct pointer (if C). But if you need a quick, preferably temporary, alternative to writing element-by-element assignment, this might do.
If you care about efficiency, you can define a union of the same length as your structure, with a type you can assign at once.
To assign values by elements use the struct of your union, to assign the whole data, use the other type of your union.
typedef union
{
struct
{
char a;
char b;
} Foo;
unsigned int whole;
} MyUnion;
MyUnion _Union;
_Union.Foo.a = 0x23; // assign by element
_Union.Foo.b = 0x45; // assign by element
_Union.whole = 0x6789; // assign at once
Be carefull about your memory organization (is "a" the MSB or the LSB of "whole"?).