How to dynamically create and read structs in C? - c

How can I do something like that (just an example):
any_struct *my_struct = create_struct();
add_struct_member(my_struct, "a", int_member);
add_struct_member(my_struct, "b", float_member);
So that I could load and use a struct instance "from the outside" (at the address addressOfMyStruct) with the given structure here?
any_struct_instance *instance = instance(my_struct, addressOfMyStruct);
int a = instance_get_member(instance, "a");
float b = instance_get_member(instance, "b");
I would also like to be able to create struct instances dynamically this way.
I hope it's clear what I want to do. I know that C/Invoke is able to do it, but is there a separate library to do that?

Actually demonstrating the code to make this work in C is a bit too involved for an SO post. But explaining the basic concept is doable.
What you're really creating here is a templated property bag system. The one thing you'll need a lot of to keep this going is some assiociative structure like a hash table. I'd say go with std::map but you mentioned this was a C only solution. For the sake of discussion I'm just going to assume you have some sort of hashtable available.
The "create_struct" call will need to return a structure which contains a pointer to a hashtable which makes const char* to essentially a size_t. This map defines what you need in order to create a new instance of the struct.
The "insance" method will essentially create a new hashtable with equal number of members as the template hashtable. Lets throw lazy evualation out the window for a second and assume you create all members up front. The method will need to loop over the template hashtable adding a member for every entry and malloc'ing a memory chunk of the specified size.
The implementation of instance_get_member will simply do a lookup in the map by name. The signature though and usage pattern will need to change though. C does not support templates and must chose a common return type that can represent all data. In this case you'll need to chose void* since that's how the memory will need to be stored.
void* instance_get_member(any_struct_instance* inst, const char* name);
You can make this a bit better by adding an envil macro to simulate templates
#define instance_get_member2(inst, name, type) \
*((type*)instance_get_member((inst),(name)))
...
int i = instance_get_member2(pInst,"a", int);

You've gone so far defining the problem that all that's left is a bit of (slightly tricky in some parts) implementation. You just need to keep track of the information:
typedef struct {
fieldType type;
char name[NAMEMAX];
/* anything else */
} meta_struct_field;
typedef struct {
unsigned num_fields;
meta_struct_field *fields;
/* anything else */
} meta_struct;
Then create_struct() allocates memory for meta_struct and initialized it to 0, and add_struct_member() does an alloc()/realloc() on my_struct.fields and increments my_struct.num_fields. The rest follows in the same vein.
You'll also want a union in meta_struct_field to hold actual values in instances.

I did some of this a long time ago.
The way I did it was to generate code containing the struct definition, plus all routines for accessing it and then compile and link it into a DLL "on the fly", then load that DLL dynamically.

Related

Creating a certain struct at run time in c

I have an assignment for which the user will specify at run time the type of struct that they want to create.
For instance, lets say that the user inputs:
name : char[50], address: char[50] and age: int
Then my program will have to create a struct containing these 3 types of variables. Note that the user can specify as many variables as they want for the struct, only limiting them to char and int.
How should my code be in order to create a struct as specified above?
This is for c programming language only!
a variable have 3 fields:
1) type, 2) name, 3) address.
you shuold create an array of struct containing these 3, array of this struct will be what you want
your structs may look like this:
typedef enum _Type{T_INT,T_STRING}Type;
typedef struct _var{
Type type;
char* name;
union {int n; char* str;} data;
}var;
typedef struct _Struct{
int count;
var* array;
} Struct;
when you get the input, you need to build the Struct according to it.
name : char[50], address: char[50] and age: int
Struct *s = malloc(sizeof(Struct));
s->count = 3;//count of fields in the input
s->array = malloc(s->count*sizeof(var));
//you really should do it in a loop, after parsed the input...
for(i=0;i<s->count;i++){
s->array[i].name = strdup(parsedname);//"name", "address", "age"
s->array[i].type = strcmp(parsedtype,"int")?T_STRING: T_INT;
//for string you need to alloc memory for string...
if(s->array[i].type == T_STRING)
s->array[i].data.str=malloc(50 /*the size you've got*/);
//not need to alloc memory for the int
}
when you finish don't forget to free the mallocs:
for(i=0;i<s->count;i++){
free(s-array[i].name);
if(s->array[i].type == T_STRING)
free(s->array[1].data.str);
}
free(s->array);
free(s);
You'll also need a method to fill the struct and print it, and so on...
I have been wondering about this myself, because I was thinking about writing an FFI implementation for a language. (Although I suspect, based on your accepted answer, that your use case is somewhat different).
As pointed out, structs can only be generated at compile time, but this is primarily also a feature of the C language to enable type checking and so that type safety can be enforced.
At run time, you can still manipulate areas in memory as raw bytes. You just need to know the length and offset based on the individual components of the datatype you are declaring and manage these at accordingly.
I picked this up from looking at how the Ruby FFI library was implemented. The following is from their documentation:
When you call Struct.new, it allocs an “internal bytes” worth of
memory right then. When you then do a set, like struct[:member] = 3,
the bits within that struct are set right then. The inverse is also
true; x = struct[:member] does a read from the raw memory (and
translation into a ruby object), each time you access it. Memory is
“zeroed out” when it is first allocated, unless you pass in your own
Pointer or specify it to not clear memory (additional notes). If you
pass it a Pointer it basically uses that as its base instead of
allocating anything.
https://github.com/ffi/ffi/wiki/Structs#when-allocated
"only limiting them to char and int"
So you can create general datatype (struct), holding a list of nodes with name and char*, and a list of nodes with name and int.
On each new input you just fill the lists with required number of char* and int nodes.
To access the field of such data structure you'll need to traverse the list, although.
If you need efficiency, you can replace list to map (associative array). You'll need to implement it yourself as you are on C.

In C, is it possible access a variable name at run time via pointer

In C, I want to access a variable name at run time.
For instance there is a structure abc
struct alpha
{
int aaa1,
int aaa2,
char bbb1
};
struct alpha alp;
char *ptr_alpha =&alp;
Is it possible I can use any expression like
if (alpha element1 name == "aaa1")
{
do this;
}
else
{
do that;
}
It doesn't make any sense to access a variable name in runtime. Every beginner gets this idea at some point, but it originates from lack of understanding of what goes on "underneath the hood". Identifiers such a variable names, function names, types etc only exist in your source code. They are there to help the programmer. In the compiled binary, there isn't a trace left of any identifiers.
There are various language mechanisms that should be used for what you try to achieve: enums, pointers, function pointers and so on. As for your specific case, there is too little information about what you are trying to achieve, to give a suggestion about how to solve it.
Names of identifiers are not known to a compiled program (ignoring dlsym magic), so no, there is no way to test for access to certain struct members at runtime. But if you just need to select members according to some string, then
if (strcmp (user_input, "aaa1") == 0) {
/* do something to alp->aaa1 */
} else if (strcmp (user_input, "aaa2") == 0) {
/* do something to alp->aaa2 */
}
There are usually ways to do everything if you put your mind to it. It's just that sometimes the cure is worse than the disease as it were.
I've been involved with a legitimate reason to do something like this in the past, and the best solution we came up with was to literally parse the header file(s) defining your data in question.
It's not an easy problem to solve; when you parse your header, you're going to need to take note of the following: variable name, variable type, and any possible padding that may occur. As you parse each element, you save an offset you keep track of so that when you get your name later on, you stuff the value into something like: (unsigned char *)(&data_structure + var_offset).
When you're parsing your xml, then you'll look up the element name, and call a handler (that you write) for putting the data in for each type of data you need to support. Most commonly you'd probably need an int handler and a char * (or whatever) handler. Bonus points for implementing simple defines (usually as constant values for array sizes (oh yeah, you'll have to implement arrays, especially for char * strings), etc.) and recursive processors that implement previously-defined struct types referred to by later structs.
Quick example: Your token def would be something like:
struct token_def
{
char *token_name;
enum supported_token_types token_type;
int array_length;
int token_offset;
}
and your example struct would therefore fill in as
{
{ "aaa1", TT_INT, 1, 0 },
{ "aaa2", TT_INT, 1, 4 },
{ "bbb1", TT_CHAR, 1, 8 },
}
etc. If you had a bbb2 element that was a 10-byte string after that, then it might look like:
{ "bbb2", TT_CHAR, 10, 9 },
Although that 9 is going to be dependent on padding rules, and could possibly be like 12 or something. Padding will probably be your hardest problem to solve, although in reality it's fairly straightforward if you "get it."
I seem to recall there may be a library that does this for you already, but I couldn't find it with a quick search. Good luck.

Simulating array_pop for various structures in C

I am new to C but I am currently working on a project which I cannot work out how I can do what is needed.
I have 2 different struct arrays, they are completely differently defined and I am trying to do the same action as PHP's array_pop would do, i.e. remove the last element of the array structure.
I know I could create 2 separate functions, one for each structure type, but obviously is not the best idea, so am wondering whether it is possible that I can pass either structure type to the one function, and possibly a flag, and the flag determine what type of structure it should be cast to.
My structures are defined as follows
typedef struct CallLogSearchResultStruct
{
long date;
int dRowIndex;
} callLogSearchResultStruct;
typedef struct CallLogSearchDataStruct
{
char * date;
char * time;
char * bParty;
char * aParty;
float duration;
char * cleardownCause;
struct CallLogSearchOutboundStruct * outboundLegs;
} callLogSearchDataStruct;
Below is how the structures are initialised
callLogSearchData = calloc(numRows, sizeof(callLogSearchDataStruct));
callLogSearch = calloc(numRows, sizeof(callLogSearchResultStruct));
numRows being the number of structs to contain within the array.
Below is how I am using the structures
callLogSearchData[dataRow].aParty = NULL;
callLogSearchData[dataRow].bParty = NULL;
callLogSearchData[dataRow].cleardownCause = NULL;
callLogSearchData[dataRow].date = NULL;
callLogSearchData[dataRow].time = NULL;
callLogSearchData[dataRow].outboundLegs = NULL;
Apologise if this is a simple straight forward answer, I can't find anything on Google, although not entirely sure what this would be called so maybe I'm using the wrong keywords.
Thanks for any help you can provide.
What do you mean by "remove"? How are the arrays allocated?
If you have an array created by a declaration such as:
struct foo my_foos[123];
there is nothing you can do to change the fact that my_foos is 123 elements long. You can of course select to ignore some of them by having a separate size_t foo_count variable that you maintain.
Arrays in C are not generally dynamic (unlike lists/arrays in many more high-level languages). You can implement a dynamic array using malloc(), which is not too hard but it's unclear if that's what you've done.
If you're open for using external files, have a look at utarray:
It's a collection of macros stored in one header that allow what you're searching for. No need to link an additional library, just #include the file and you have what you need.
You'd have to implement a custom UT_icd providing functions to init, copy and free the elements stored in the array.
What you want is actually a linked list. It is a collection of structures each one pointing to the Nth element and to the next element in the list. That way you can easily remove any element by unlinking it in the chain. You can google for a linked list lib in C or, implement one (it's a good exercise).
Arrays in C are static memory ranges with only enough space for your elements. Nothing more. In general you can not remove one element. You can, however, use realloc function to resize an existing array.
For what you're trying to do I'd go for a linked list.

Manually zeroing variables VS copying struct

I have a long C (not C++) struct. It is used to control entities in a game, with position, some behavior data, nothing flashy, except for two strings. The struct is global.
Right now, whenever an object is initialized, I put all the values to defaults, one by one
myobjects[index].angle = 0; myobjects[index].speed = 0;
like that. It doesn't really feel slow, but I am wondering if copying a "template" struct with all values set to the defaults is faster or more convenient.
So, to sum up into two proper questions: Is it faster to copy a struct instead of manually setting all the data?
What should I keep in mind about the malloc-ed memory for the strings?
"More convenient" is likely the more important part.
struct s vs[...];
...
// initialize every member to "default"
// but can't use in normal assignment
struct s newv = {0};
vs[...] = newv;
Or hide the "initialization details" behind an init-function (or a macro, if you dislike maintainable code :-)
struct s* init_s (struct s* v, ...) { /* and life goes on */ }
You may use this sequence:
memset(myobjects+index,0,sizeof(myobjects[0]);
if all you need is to set all members to zero
Beware: if a particular member is pointer, it will be set to NULL
Nelu Cozac

Resizing a char[x] to char[y] at runtime

OK, I hope I explain this one correctly.
I have a struct:
typedef struct _MyData
{
char Data[256];
int Index;
} MyData;
Now, I run into a problem. Most of the time MyData.Data is OK with 256, but in some cases I need to expand the amount of chars it can hold to different sizes.
I can't use a pointer.
Is there any way to resize Data at run time? How?
Code is appreciated.
EDIT 1:
While I am very thankful for all the comments, the "maybe try this..." or "do that", or "what you are dong is wrong..." comments are not helping. Code is the help here. Please, if you know the answer post the code.
Please note that:
I cannot use pointers. Please don't try to figure out why, I just can't.
The struct is being injected into another program's memory that's why no pointers can be used.
Sorry for being a bit rough here but I asked the question here because I already tried all the different approaches that thought might work.
Again, I am looking for code. At this point I am not interested in "might work..." or " have you considered this..."
Thank you and my apologies again.
EDIT 2
Why was this set as answered?
You can use a flexible array member
typedef struct _MyData
{
int Index;
char Data[];
} MyData;
So that you can then allocate the right amount of space
MyData *d = malloc(sizeof *d + sizeof(char[100]));
d->Data[0..99] = ...;
Later, you can free, and allocate another chunk of memory and make a pointer to MyData point to it, at which time you will have more / less elements in the flexible array member (realloc). Note that you will have to save the length somewhere, too.
In Pre-C99 times, there isn't a flexible array member: char Data[] is simply regarded as an array with incomplete type, and the compiler would moan about that. Here i recommend you two possible ways out there
Using a pointer: char *Data and make it point to the allocated memory. This won't be as convenient as using the embedded array, because you will possibly need to have two allocations: One for the struct, and one for the memory pointed to by the pointer. You can also have the struct allocated on the stack instead, if the situation in your program allows this.
Using a char Data[1] instead, but treat it as if it were bigger, so that it overlays the whole allocated object. This is formally undefined behavior, but is a common technique, so it's probably safe to use with your compiler.
The problem here is your statement "I can't use a pointer". You will have to, and it will make everything much easier. Hey, realloc even copies your existing data, what do you want more?
So why do you think you can't use a pointer? Better try to fix that.
You would re-arrange the structure like that
typedef struct _MyData
{
int Index;
char Data[256];
} MyData;
And allocate instances with malloc/realloc like that:
my_data = (MyData*) malloc ( sizeof(MyData) + extra_space_needed );
This is an ugly approach and I would not recommend it (I would use pointers), but is an answer to your question how to do it without a pointer.
A limitation is that it allows for only one variable size member per struct, and has to be at the end.
Let me sum up two important points I see in this thread:
The structure is used to interact between two programs through some IPC mechanism
The destination program cannot be changed
You cannot therefore change that structure in any way, because the destination program is stuck trying to read it as currently defined. I'm afraid you are stuck.
You can try to find ways to get the equivalent behavior, or find some evil hack to force the destination program to read a new structure (e.g., modifying the binary offsets in the executable). That's all pretty application specific so I can't give much better guidance than that.
You might consider writing a third program to act as an interface between the two. It can take the "long" messages and do something with them, and pass the "short" messages onward to the old program. You can inject that in between the IPC mechanisms fairly easily.
You may be able to do this like this, without allocating a pointer for the array:
typedef struct _MyData
{
int Index;
char Data[1];
} MyData;
Later, you allocate like this:
int bcount = 256;
MyData *foo;
foo = (MyData *)malloc(sizeof(*foo) + bcount);
realloc:
int newbcount = 512;
MyData *resized_foo;
resized_foo = realloc((void *)foo, sizeof(*foo) + newbcount);
It looks like from what you're saying that you definitely have to keep MyData as a static block of data. In which case I think the only option open to you is to somehow (optionally) chain these data structures together in a way that can be re-assembled be the other process.
You'd need and additional member in MyData, eg.
typedef struct _MyData
{
int Sequence;
char Data[256];
int Index;
} MyData;
Where Sequence identifies the descending sequence in which to re-assemble the data (a sequence number of zero would indicate the final data buffer).
The problem is in the way you're putting the question. Don't think about C semantics: instead, think like a hacker. Explain exactly how you are currently getting your data into the other process at the right time, and also how the other program knows where the data begins and ends. Is the other program expecting a null-terminated string? If you declare your struct with a char[300] does the other program crash?
You see, when you say "passing data" to the other program, you might be [a] tricking the other process into copying what you put in front of it, [b] tricking the other program into letting you overwrite its normally 'private' memory, or [c] some other approach. No matter which is the case, if the other program can take your larger data, there is a way to get it to them.
I find KIV's trick quite usable. Though, I would suggest investigating the pointer issue first.
If you look at the malloc implementations
(check this IBM article, Listing 5: Pseudo-code for the main allocator),
When you allocate, the memory manager allocates a control header and
then free space following it based on your requested size.
This is very much like saying,
typedef struct _MyData
{
int size;
char Data[1]; // we are going to break the array-bound up-to size length
} MyData;
Now, your problem is,
How do you pass such a (mis-sized?) structure to this other process?
That brings us the the question,
How does the other process figure out the size of this data?
I would expect a length field as part of the communication.
If you have all that, whats wrong with passing a pointer to the other process?
Will the other process identify the difference between a pointer to a
structure and that to a allocated memory?
You cant reacolate manualy.
You can do some tricks wich i was uning when i was working aon simple data holding sistem. (very simple filesystem).
typedef struct
{
int index ;
char x[250];
} data_ztorage_250_char;
typedef struct
{
int index;
char x[1000];
} data_ztorage_1000_char;
int main(void)
{
char just_raw_data[sizeof(data_ztorage_1000_char)];
data_ztorage_1000_char* big_struct;
data_ztorage_250_char* small_struct;
big_struct = (data_ztorage_1000_char*)big_struct; //now you have bigg struct
// notice that upper line is same as writing
// big_struct = (data_ztorage_1000_char*)(&just_raw_data[0]);
small_struct = (data_ztorage_250_char*)just_raw_data;//now you have small struct
//both structs starts at same locations and they share same memory
//addresing data is
small_struct -> index = 250;
}
You don't state what the Index value is for.
As I understand it you are passing data to another program using the structure shown.
Is there a reason why you can't break your data to send into chunks of 256bytes and then set the index value accordingly? e.g.
Data is 512 bytes so you send one struct with the first 256 bytes and index=0, then another with the next 256 bytes in your array and Index=1.
How about a really, really simple solution? Could you do:
typedef struct _MyData
{
char Data[1024];
int Index;
} MyData;
I have a feeling I know your response will be "No, because the other program I don't have control over expects 256 bytes"... And if that is indeed your answer to my answer, then my answer becomes: this is impossible.

Resources