I'm converting from C/C++ header to Delphi.
I've carefully read the great Rudy's Delphi Corner article about this kind of conversion. Anyway, I'm facing something I'm hard to understand.
There's an opaque pointer, then a function prototype that has that pointer as parameter, followed by the struct declaration og the function type.
Maybe the code will make things clearer.
source .h code:
struct my_ManagedPtr_t_;
typedef struct my_ManagedPtr_t_ my_ManagedPtr_t;
typedef int (*my_ManagedPtr_ManagerFunction_t)(
my_ManagedPtr_t *managedPtr,
const my_ManagedPtr_t *srcPtr,
int operation);
typedef union {
int intValue;
void *ptr;
} my_ManagedPtr_t_data_;
struct my_ManagedPtr_t_ {
void *pointer;
my_ManagedPtr_t_data_ userData[4];
my_ManagedPtr_ManagerFunction_t manager;
};
typedef struct my_CorrelationId_t_ {
unsigned int size:8; // fill in the size of this struct
unsigned int valueType:4; // type of value held by this correlation id
unsigned int classId:16; // user defined classification id
unsigned int reserved:4; // for internal use must be 0
union {
my_UInt64_t intValue;
my_ManagedPtr_t ptrValue;
} value;
} my_CorrelationId_t;
... i'm lost. :-( I can't figure out where to start.
The structure? The function?
Thank you.
As you clarified in the comments, the immediate area of confusion for you is the circular reference. The function pointer parameters refer to the struct, but the struct contains the function pointer. In the C code this is dealt with by the opaque struct type declaration which is simply a forward declaration. A forward declaration simply promises that the type will be fully declared at some later point.
In Delphi you can deal with this in a directly analogous manner. You need to use a forward type declaration. I don't want to translate all the types in your question because that would require dealing with unions and bitfields which I deem to be separate topics. Instead I will present a simple Delphi example that shows how to deal with such circular type declarations. You can take the concept and apply it to your specific types.
type
PMyRecord = ^TMyRecord; // forward declaration
TMyFunc = function(rec: PMyRecord): Integer; cdecl;
TMyRecord = record
Func: TMyFunc;
end;
It is a little hard to find out where to start, but #DavidHeffernan's explanation of forward declaring a pointer type should give you a start.
I would translate this to following (untested) code:
type
_my_ManagedPtr_p = ^my_ManagedPtr_t;
my_ManagedPtr_ManagerFunction_t = function(
managedPtr: my_ManagedPtr_p;
scrPtr: my_ManagedPtr_p;
operation: Integer): Integer cdecl;
my_ManagedPtr_t_data = record
case Boolean of
False: (intValue: Integer);
True: (ptr: Pointer);
end;
my_ManagedPtr_t = record
ptr: Pointer;
userData: array[0..3] of my_ManagedPr_t_data;
manager: my_ManagedPtr_ManagerFunction_t;
end;
my_CorrelationId_t = record
typeData: UInt32; // size, valueType, classId and reserved combined in one integer.
case Byte of
0: (intValue: my_UInt64_t);
1: (ptrValue: my_ManagedPtr_t;
end;
I am not going to do the bitfields, but please read the Bitfields section of my article Pitfalls of converting again (I see you mentioned it already) to find a few solutions. If you want to make it really nice, use the methods and indexed access, otherwise just use shifts and masks to access the bitfields contained in the member I called typeData. How this can be done is explained in the article and is far too much to repeat here.
If you have problems with them anyway, ask a new question.
Related
I have a union (ValueDefinition) with pointers of different datatypes in it and functions to create it. With String it works fine:
ValueDefinition CreateValDefString(String value){
ValueDefinition valDef = {.ValueString = new String(value)};
return valDef;
}
But when I do the same with e.g. uint8_t it compiles, but at runtime I get this error:
[E][WString.cpp:185] changeBuffer(): realloc failed! Buffer unchanged
That's the code for the uint8_t:
ValueDefinition CreateValDefUint8(uint8_t value){
ValueDefinition valDef = {.ValueUInt8 = new uint8_t(value)};
return valDef;
}
What am I doing wrong? I tried it without "new" and with malloc, but I still get the same error.
Edit: As requested, the definition of ValueDefinition:
union ValueDefinition{
bool* ValueBool;
int8_t* ValueInt8;
int16_t* ValueInt16;
int32_t* ValueInt32;
uint8_t* ValueUInt8;
uint16_t* ValueUInt16;
uint32_t* ValueUInt32;
float* ValueFloat;
ulong* ValueULong;
String* ValueString;
};
In your code, it looks like C++ is throwing an error to a function to create a WString instead of uint8_t, hence the stacktrace in a completely separate header. Searching the source code in the repository for arduino shows that there is an error in WString.cpp here, which is what your compiler's detecting.
The github users suggest using a different string library, and since the bug hasn't been fixed you'll have to change, probably to the standard string library defined by C++ and not arduino. As the users have stated on github, arduino strings are notoriously unreliable.
In other words, this error has nothing to do with your code, but a question that I'd like to ask is "Why use unions in C++?" If you want to define a generic type just use templates, ex:
template<class T>
class ValueDefinition<T> {
private:
T typeDat;
public:
Valuedefinition(T t);
/* etc. */
}
Unions were made so that C could have a way to use generic typing by having several types share the data in the union. Another common use is taking advantage of the data types using the same memory to find the underlying binary of more complex types, such as using individual uint8_t values underlying a long long to find the value of its bits or using an int to get the binary value of a float, ex:
union foo {
uint8_t bits[4]; /* Represent the bits of 'data' */
long long int data;
}
union foo myLong = {.data = 12378591249169278l};
printf("%d\n", myLong.bits[0]); // Returns the value of the high bit of myLong
However note that this is undefined behavior because unions are usually padded and architectures use a different form of endianess. Whatever you're doing, if you're using C++ there's a better way to implement your solution than using unions, since this was a feature meant for a language that had no generic typing in order to save memory.
Edit:
Initialize ValueDefinition using C's malloc like so:
union ValueDefinition *value = malloc(sizeof(union ValueDefinition));
value->ValueUInt8 = malloc(sizeof(uint8_t));
/* more code */
Or with C++'s new:
union ValueDefinition *value = new ValueDefinition();
value->ValueUInt8 = new uint8_t(/* Some number */);
/* more code */
I'm playing a bit with the C++ syntax to figure out a generalized way to keep track of an offset within a class, sort of like offsetof, but in a type-safe way and without #defines
I know that a template class can be template-parametrized with fields, besides types and constants. So I came out with this prototype:
#include <iostream>
template <typename class_type, typename field_type>
struct offsetter
{
offsetter(const char* name, field_type class_type::*field)
: name(name)
{
fprintf(stderr, "%zu\n", field);
}
const char* const name;
};
struct some_struct
{
float avg;
int min;
int max;
struct internal
{
unsigned flag;
int x;
} test;
char* name;
};
int main()
{
offsetter<some_struct, float>("%h", &some_struct::avg);
offsetter<some_struct, int>("%h", &some_struct::min);
offsetter<some_struct, char*>("%h", &some_struct::name);
offsetter<some_struct, some_struct::internal>("x", &some_struct::test);
return 0;
}
This code is actually able to print the field offset, but I'm not really sure on what I'm doing here. Indeed it feels utterly wrong to reference field without referring to an instance (foo.*field).
But it does the job: it prints the offset. My guess is that I'm hitting on some loophole though, since for instance I can't assign size_t offset = field.
I figured out I probably want something like this:
size_t offset = (&(std::declval<class_type>().*field) - &(std::declval<class_type>()))
Which however wont' work as I can't take the address of an xvalue:
taking address of xvalue (rvalue reference)
Is there any way to do this?
AFAIK there isn't a standard way of doing this. Even the standard offsetof is defined only for standard layout types.
What you are doing is UB. You are using the wrong specifier zu. There isn't much you can do with a member pointer. You can't even do pointer arithmetics on them, you can't convert to char* nor to an integer type.
Also if your assumption is that a member pointer is just an integer representing the offset from the beginning of the structure that is false, not only in theory, but also in practice. Having multiple inheritance and virtual inheritance made sure of that.
I'm working with a library that uses a C interface and several functions that pass a pointer to a struct as the output (not return).
The struct is something like
struct S {
short a;
short b;
union {
char cdata[5];
short sdata[5];
long ldata[5];
float fdata[5];
double dfdata[5];
} u;
}
I've written some template classes that can provide access to this in the form
auto parameter = MyClass<double>(constructor parameters);
parameter.SetValue(5.2); // Sets u.dfdata[0] = 5.2;
// other functions for changing index, or passing in a vector, etc
This is nice(ish) in that it abstracts away a lot of the required knowledge about structs, and only requires the user (still me, but whatever...) to know about the type of the parameter (double, float, long, short or char).
However, it's a compile time construct. The hardware I'm communicating with through this library is able to provide a function that has something like:
// renamed and tidied for ease of reading
// I don't have the source for this function, only docs
short GetParameter(short address, short* prevAddress, short* nextAddress,
S* parameter, Other* info);
where info can be parsed to tell me the type of the parameter. This would, if it were not compile time and different types, allow something like
std::vector<??> a;
a.push_back(MyClass<double>(args));
a.push_back(MyClass<short>(args));
where double and short can be read from the info struct as a short (0 = char, 1 = short...) and the other arguments can be read from the S struct.
I can build a std::vector<std::variant<MyClass<char>, MyClass<short>, ..., MyClass<double>>> but then trying to work out how to use a variant has left me confused if this is a good idea at all.
I want to be able to store sets of different types of parameters, for example for saving a complete configuration, but at the moment I think my functions are all compile-time calculations (variations on if constexpr(std::is_same_v<T, char>) { // do something with u.cdata[index] }).
If I want to be able to create lists with a single type, I can't (as far as I can work out) have virtual T ReadValue() or virtual void SetValue(T) because I can't use templating on virtual functions, and if I template the class (as I do now) then I have different (class) types which become hard to operate on.
An ideal solution would look something like
using valType = std::variant<char, short, long, float, double>;
using varType = std::variant<MyClass<char>, ..., MyClass<double>>;
// Read this from some file, or whatever
auto values = std::vector<valType> { 3, 2.6f, 17.2, 1523l };
std::vector<varType> paramList = MyFunctionThatReadsThroughParamToNextParam();
for (size_t i = 0; i < values.size(); i++) {
paramList[i].SetValue(values[i]);
// where the type contained in values[i] matches the type expected by paramList[i]
// ideally this would throw if the types were incorrect, but really
// any defined behaviour here would be great.
}
Is anything like this remotely possible?
I have a struct something like:
/**
* Typical dOxygen brief about the typedef. Longer description follows.
*/
typedef struct _SOME_STRUCT_TAG {
int var1; /**< Something useful. */
int var2; /**< something equally useful. */
} SOME_STRUCT_T, *LPSOME_STRUCT_T /**< A post doc the pointer here. Longer description follows */;
I've enabled the project option TYPEDEF_HIDES_STRUCT.
I'd like the documentation to create two separate entries: one for the pointer typedef and one for the non-pointer typedef. Currently, I only seem to get one for the pointer typedef.
What am I doing wrong here? I'm also open to general syntax suggestions. Note this is for a C library, not C++. It seems dOxygen has trouble dealing with a typedef which has multiple statements (ie typedef int var_t,*pvar_t).
IIRC, doxygen doesn't support different documentation for multiple identifiers in a single declaration at all. So separate them.
Instead of
int a, b, c;
use
int a;
int b;
int c;
and instead of
typedef struct _SOME_STRUCT_TAG {
int var1; /**< Something useful. */
int var2; /**< something equally useful. */
} SOME_STRUCT_T, *LPSOME_STRUCT_T;
use
typedef struct _SOME_STRUCT_TAG {
int var1; /**< Something useful. */
int var2; /**< something equally useful. */
} SOME_STRUCT_T;
typedef SOME_STRUCT_T *LPSOME_STRUCT_T;
Also note that you're using reserved words for struct and typedef names, which is inviting trouble, not only from doxygen.
Also, this practice of transparent typedef names for pointers is bad style. If the pointer type is an opaque handle and clients will never see the underlying type, or even know that the handle is a pointer (as opposed to a table index or other key), use a typedef. If the client works directly with the structure, let them use SOME_STRUCT_T *.
I have enable to the user choosing the type of data he wants to use, for example if he wants to use long or double etc.
I would like to declare first the name of the variable then set its type. Is it possible in C++?
If I understood your question correctly, you want to do this:
declare variable;
// in the program:
variable = (int) anotherVariable;
Short answer:
No
Long answer:
a void * does exactly this, it needs to be explicitly converted to a different type before dereferencing. But this is not possible on variables that are not void *s.
void *variable = NULL;
int someIntVariable = 100;
int *someIntPointer = NULL;
variable = &someIntVariable;
someIntPointer = (int *)variable;
.. // but this seems unncessary.
Have a look at boost::variant, or, if you need only PODs, union. However keep in mind that this complicates many things.
enum VariantType {
USER_INT, USER_DOUBLE
};
union Variant {
int i;
double d;
}
int main() {
VariantType type;
Variant data;
type = getUserDataType();
switch(type) {
case USER_INT:
data.i = 42;
break;
case USER_DOUBLE:
data.d = 42.0;
break;
default:
break;
}
...or use some ready Variant implmementation.
Look into using VARIANT (if you're on Windows) or something similar on other platforms. The point of VARIANT is that it's a union that is capable of storing all kinds of data types but only 1 particular type at a given time. This way you can define a new generic variable type (VARIANT) ahead of time and then adapt its internal type at run-time, depending on user choice.
Using something like VARIANT comes at a price, though, since every operation that you do on it will have to check if the operation is correct for the current underlying type. VARIANT also uses more memory since the union has its own overhead (see the definition for details).
You may want to wrap variant operations in a class to simplify its usage. The nice thing about VARIANT as opposed to void* is that it gives you a lot more type safety and the code becomes a lot more readable.
Edit: as another answer pointed out, boos::variant is for this purpose.