What is the proper way to access the struct variables in a function that is called by pthread_creation. This is how I am trying to do
void *add_first_quat(void *a){
struct thread1Struct *myArray = (struct thread1Struct *)a;
int i ;
for(i= *myArray>start; i < *myArray>end; i++){
sum+= *myArray>th1Array[i];
}
/* the function must return something - NULL will do */
return NULL;
}
And in my struct I am defining two variables and pointer to a globally defined array
struct thread1Struct{
int start = 0;
int end = 25;
int *th1Array = myArray;
};
This is how I am calling pthread_create function
(pthread_create(&inc_first_quater_thread, NULL, add_first_quat, (void*) &th1StrObj))
Why my code is not working? I am getting following errors
main.c: In function ‘add_first_quat’:
main.c:14:9: error: dereferencing pointer to incomplete type
for(i= *myArray>start; i < *myArray>end; i++){
^
main.c:14:18: error: ‘start’ undeclared (first use in this function)
for(i= *myArray>start; i < *myArray>end; i++){
^
main.c:14:18: note: each undeclared identifier is reported only once for each function it appears in
main.c:14:29: error: dereferencing pointer to incomplete type
for(i= *myArray>start; i < *myArray>end; i++){
^
main.c:14:38: error: ‘end’ undeclared (first use in this function)
for(i= *myArray>start; i < *myArray>end; i++){
^
main.c:15:9: error: dereferencing pointer to incomplete type
sum+= *myArray>th1Array[i];
^
main.c:15:18: error: ‘th1Array’ undeclared (first use in this function)
sum+= *myArray>th1Array[i];
^
main.c: At top level:
main.c:34:12: error: expected ‘:’, ‘,’, ‘;’, ‘}’ or ‘__attribute__’ before ‘=’ token
int start = 0;
^
First problem (syntax):
Try myArray->start or (*myArray).start or myArray[0].start. The first syntax would be my preference in this case.
Second problem:
dereferencing pointer to incomplete type
You need to provide the full declaration before referencing any fields.
Solve the problem by moving the full declaration of the struct to the top of your code file, or put it in a .h file that you #include in all source files that use the struct.
This: *myArray>start is not the proper syntax for accessing members of a pointer to a struct.
You could do this: (*myArray).start, which dereferences the pointer so *myArray is of type struct thread1Struct, then use . for member access.
The preferred way is myArray->start, where the -> operator does member access for a pointer to struct.
The problem lies in the way you're accessing the elements of the structure. Your expression *myArray>start makes no sense to the compiler. As you know, myArray is a pointer to a struct. You can access the data members in two ways :
You could use the indirection operator (eg. (*myArray).start )
You could use the arrow operator (eg. myArray->start)
This is how you access data members of any struct pointer. It does not pertain p-threads alone.
Related
I am developing a TIN model application and have a structure 'Vertex' that I have defined in the common area at the top of my C program.
struct Vertex
{
int GblSeqNum;
int PlySeqNum;
struct Polyline *Line;
double CtrZ;
double x;
double y;
double z;
struct Edge *OwnerEdge;
struct Vertex *NextVtx;
struct Vertex *PrevVtx;
};
Next, right below the Vertex structure, I declare a global pointer to a Vertex structure:
struct Vertex *VtxsInLines;
Then, still in the common area, I use calloc to assign space for my vertices:
VtxsInLines = (struct Vertex *)(calloc(15000, sizeof(struct Vertex)));
I compile the code using GNU C compiler using MinGW on Windows 10:
C:\000WORKIndexedTasks 000-999\500 Papers\523 PositionalAccuracyContourLines>gcc -c 523*.c
The following warnings and errors are generated:
523Paper_ReadContourVertices.c:98:1: warning: data definition has no type or storage class
VtxsInLines = (struct Vertex *)(calloc(15000, sizeof(struct Vertex)));
^~~~~~~~~~~
523Paper_ReadContourVertices.c:98:1: warning: type defaults to 'int' in declaration of 'VtxsInLines' [-Wimplicit-int]
523Paper_ReadContourVertices.c:98:1: error: conflicting types for 'VtxsInLines'
523Paper_ReadContourVertices.c:47:16: note: previous declaration of 'VtxsInLines' was here
struct Vertex *VtxsInLines;
^~~~~~~~~~~
523Paper_ReadContourVertices.c:98:15: warning: initialization of 'int' from 'struct Vertex *' makes integer from pointer without a cast [-Wint-conversion]
VtxsInLines = (struct Vertex *)(calloc(15000, sizeof(struct Vertex)));
It appears my declarations are in error somehow and this leads the compiler to assume an int type. This generates lots of errors later such as:
523Paper_ReadContourVertices.c: In function 'main':
523Paper_ReadContourVertices.c:432:20: error: invalid type argument of '->' (have 'int')
(VtxsInLines+idx)->GblSeqNum = -1;
Can you tell me with what what I provided what I am doing wrong?
The problem is that you are allocating the Vertex structure in the global space. It is not permissible to run executable instructions in the global scope, only allowed in functions such as main. The fix would be to move the VtxsInLines = (struct Vertex *)(calloc(15000, sizeof(struct Vertex))); statement into the main function. You would still be able to access the memory assigned to the VtxsInLines variable in other functions without having to pass it along because VtxsInLines is global.
I have my struct like below , there can be n number of vendor which can contain n number of test struct.
I am trying to initialize this structure . This is a sample code I am trying , later I want to make it using macros and load the structure like X-macros.
I am also using flexible structure concept as I do not know how many test structs for a vendor are going to be. The data would be in a file , the struct needs to load all that is there. I have created a minimal sample code for SO.
Below is my code.
#include <stdio.h>
typedef struct test{
int a;
int b;
int c;
}test;
typedef struct vendor{
int size;
test t[0];
}vendor;
vendor v[]={
{.size = 1, .t[] = {{1,2,3},}}
};
int main()
{
return 0;
}
I get this error -
a.c:16: error: expected expression before ‘]’ token
a.c:16: error: array index in initializer not of integer type
a.c:16: error: (near initialization for ‘v[0].t’)
a.c:16: error: extra brace group at end of initializer
a.c:16: error: (near initialization for ‘v[0]’)
a.c:16: error: extra brace group at end of initializer
a.c:16: error: (near initialization for ‘v[0]’)
a.c:16: warning: excess elements in struct initializer
a.c:16: warning: (near initialization for ‘v[0]’)
I have tried without flexible struct , no luck so far.
any suggestions on how to init this struct ?
The .t[]= syntax in the initializer is invalid. When using a designated initializer, you only need to specify the name of the member:
.t={1, 2, 3}
However, this still won't work with a flexible array member.
The size of a struct with a flexible array member doesn't include space for the flexible array member, so you can't created a static or automatic instance of it. You need to allocate memory for the struct dynamically:
vendor *v;
void init()
{
v = malloc(sizeof(vendor) + 1 * sizeof(test));
v.size = 1;
v.t = (test){1, 2, 3};
}
int main()
{
init();
return 0;
}
Also, because of the variable size, a struct with a flexible array member cannon be a member of an array.
I've got a Rails app that needs to show the results of a Monte Carlo sim, and for the first time, Ruby just isn't fast enough for my needs. So, I started poking around to see if I could rewrite my simulation in C and use those results in Ruby, and some googling turned up the RubyInline gem for easily writing faster C code directly in Ruby. Doing simple stuff works great, for instance, some basic functions written in both Ruby and C:
class FasterFunctions
inline do |builder|
builder.c '
double rand_sum(int trials)
{
double sum = 0.0;
for (int i = 0; i<trials; i++)
{
sum += (double)rand()/(double)RAND_MAX;
}
return sum;
}'
builder.c '
long loop_sum(long trials)
{
long sum = 0;
for (long i = 0; i<trials; i++)
{
sum+=i;
}
return sum;
}'
end
end
#the C version is 4 orders of magnitude faster
trials = 1_000_000
ruby_sum = 0
trials.times {|i| ruby_sum += i}
c_sum = FasterRand.new.loop_sum(trials)
# the C version is 1 order of magnitude faster
ruby_sum = 0.0
trials.times {ruby_sum += rand}
c_sum = FasterRand.new.rand_sum(trials)
So, great, it should definitely speed up my sim since it's pretty much just generating random numbers and adding stuff up based on those results. Unfortunately, beyond basic stuff like this, I can't figure out how to actually write my program. I need to pass some structs around to act as state variables, so the first order of business is figuring out how to create a C struct. Reading the documentation, it seems like it should be fairly simple.
accessor(method, type, member = method)
Adds a reader and writer for a C struct member wrapped via
Data_Wrap_Struct. method is the ruby name to give the accessor, type
is the C type. Unless the C member name is overridden with member, the
method name is used as the struct member.
builder.struct_name = 'MyStruct'
builder.accessor :title, 'char *'
builder.accessor :stream_index, 'int', :index
The documentation isn't entirely clear to me, but I assume that I'd put that in a class much like before and do something like the following to access it:
class MyStructClass
inline do |builder|
builder.struct_name = 'MyStruct'
builder.accessor :title, 'char *'
builder.accessor :stream_index, 'int', :index
end
end
#possible this
struct = MyStructClass.new.MyStruct
struct.title = 'A Title'
#or maybe
struct = MyStructClass.new
struct.title = 'A Title'
Unfortunately, I can't even get that far
*/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:456:3:
error: use of undeclared identifier
'MyStruct' MyStruct *pointer; ^
*/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:456:13: error: use of undeclared identifier
'pointer' MyStruct *pointer;
^
*/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:458:35: error: use of undeclared identifier
'pointer' Data_Get_Struct(self, MyStruct, pointer);
^
/.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/ruby.h:1038:6: note: expanded from macro 'Data_Get_Struct'
(sval) = (type)DATA_PTR(obj);\
^
*/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:458:25: error: use of undeclared identifier
'MyStruct' Data_Get_Struct(self, MyStruct, pointer);
^
/.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/ruby.h:1038:15: note: expanded from macro 'Data_Get_Struct'
(sval) = (type)DATA_PTR(obj);\
^
*/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:458:3:
error: expected expression Data_Get_Struct(self, MyStruct, pointer);
^
/.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/ruby.h:1038:20: note: expanded from macro 'Data_Get_Struct'
(sval) = (type)DATA_PTR(obj);\
^
*/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:460:23: error: use of undeclared identifier
'pointer' return (rb_str_new2(pointer->title));
^
*/.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/intern.h:786:27: note: expanded from macro 'rb_str_new_cstr'
(__builtin_constant_p(str)) ? \
^
*/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:460:23: error: use of undeclared identifier
'pointer'
*/.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/intern.h:787:14: note: expanded from macro 'rb_str_new_cstr'
rb_str_new((str), (long)strlen(str)) : \
^
*/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:460:23: error: use of undeclared identifier
'pointer'
*/.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/intern.h:787:33: note: expanded from macro 'rb_str_new_cstr'
rb_str_new((str), (long)strlen(str)) : \
^
*/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:460:23: error: use of undeclared identifier
'pointer'
*/.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/intern.h:788:18: note: expanded from macro 'rb_str_new_cstr'
rb_str_new_cstr(str); \
^
*/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:460:10: error: returning 'void' from a
function with incompatible result type 'VALUE' (aka 'unsigned long') return (rb_str_new2(pointer->title));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:478:3:
error: use of undeclared identifier
'MyStruct' MyStruct *pointer; ^
*/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:478:13: error: use of undeclared identifier
'pointer' MyStruct *pointer;
^
*/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:480:35: error: use of undeclared identifier
'pointer' Data_Get_Struct(self, MyStruct, pointer);
^
/.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/ruby.h:1038:6: note: expanded from macro 'Data_Get_Struct'
(sval) = (type)DATA_PTR(obj);\
^
*/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:480:25: error: use of undeclared identifier
'MyStruct' Data_Get_Struct(self, MyStruct, pointer);
^
/.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/ruby.h:1038:15: note: expanded from macro 'Data_Get_Struct'
(sval) = (type)DATA_PTR(obj);\
^
*/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:480:3:
error: expected expression Data_Get_Struct(self, MyStruct, pointer);
^
/.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/ruby.h:1038:20: note: expanded from macro 'Data_Get_Struct'
(sval) = (type)DATA_PTR(obj);\
^
*/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:482:3:
error: use of undeclared identifier
'pointer' pointer->title = StringValuePtr(value); ^
*/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:456:3:
error: use of undeclared identifier
'MyStruct' MyStruct *pointer; ^
*/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:456:13: error: use of undeclared identifier
'pointer' MyStruct *pointer;
^
*/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:458:35: error: use of undeclared identifier
'pointer' Data_Get_Struct(self, MyStruct, pointer);
^
/.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/ruby.h:1038:6: note: expanded from macro 'Data_Get_Struct'
(sval) = (type)DATA_PTR(obj);\
^ fatal error: too many errors emitted, stopping now [-ferror-limit=]
I've done a bunch of googling, but pretty much every example I've found deals only with the simple use case I outlined at first. The first error it spit out was that MyStruct was undeclared, so I tried adding a struct definition before the accessor methods, like so:
builder.c '
typedef struct
{
char *title;
int index;
} MyStruct;
'
That doesn't do anything, and the documentation seems to be clear that the c method is only for declaring functions, not structs. I'm not really sure what to try next, does anyone else have some experience with this?
RubyInline seems to assume that you know your way around writing Ruby extensions if you are doing anything more complex than the basics.
You do need to define the struct yourself as you tried, but you should use the prefix method rather than the c method (which is for defining methods). You also need to define the allocation method for the class. You can do this with the c_singleton method by adding a function named allocate which RubyInline will recognise and use as the allocation function (this doesn’t seem to be documented, I found it by looking at the source).
Putting it all together looks something like this.
class Foo
inline do |builder|
# First define the struct that will be wrapped in the
# class.
builder.prefix <<-DEFINE_STRUCT
typedef struct {
char* bar;
} MyStruct;
DEFINE_STRUCT
# Next define the allocation function that will
# allocate and wrap a MyStruct struct when creating a
# new Foo object. You might want to initialize the values
# to avoid possible segfaults.
builder.c_singleton <<-ALLOCATE
VALUE allocate() {
MyStruct* pointer = ALLOC(MyStruct);
return Data_Wrap_Struct(self, NULL, free, pointer);
}
ALLOCATE
# Finally we can use the struct_name and accessor methods.
builder.struct_name = 'MyStruct'
builder.accessor 'bar', 'char *'
end
end
Note you can see the generated C code if you look under the directory .ruby_inline in your home directory.
It's an extremely simple and useless piece of practice code I'm working with in what is starting to seem like and extremely useless book. I was doing a struct exercise, and upon code compilation I received a handful of errors.
Here's the offending code:
struct fish = {
const char *name;
const char *species;
int teeth;
int age;
};
void catalog(struct fish f)
{
printf("%s is a %s with %i teeth. He is %i.\n", f.name, f.species, f.teeth, f.age);
}
int main()
{
struct fish snappy = {"Snappy", "piranha", 69, 4};
catalog(snappy);
return 0;
}
This is the exact code from the book, minus the struct definition above catalog. I ended up just copy pasting because I started to suspect this book was just dead wrong. The book claimed that the above code should compile and run without the struct even being defined. I've tried putting the struct definition into a header file, and I've tried removing it or adding it to different parts of the code. I get the same exact errors:
snappy.c:8:13: error: expected identifier or ‘(’ before ‘=’ token
struct fish = {
^
snappy.c:16:26: error: parameter 1 (‘f’) has incomplete type
void catalog(struct fish f)
^
snappy.c: In function ‘main’:
snappy.c:24:12: error: variable ‘snappy’ has initializer but incomplete type
struct fish snappy = {"Snappy", "piranha", 69, 4};
^
snappy.c:24:12: warning: excess elements in struct initializer
snappy.c:24:12: warning: (near initialization for ‘snappy’)
snappy.c:24:12: warning: excess elements in struct initializer
snappy.c:24:12: warning: (near initialization for ‘snappy’)
snappy.c:24:12: warning: excess elements in struct initializer
snappy.c:24:12: warning: (near initialization for ‘snappy’)
snappy.c:24:12: warning: excess elements in struct initializer
snappy.c:24:12: warning: (near initialization for ‘snappy’)
snappy.c:24:17: error: storage size of ‘snappy’ isn’t known
struct fish snappy = {"Snappy", "piranha", 69, 4};
struct fish = { is wrong in struct declaration. It should be struct fish {. Remove = sign.
When i have run the following piece of code:
typedef char *lrfield();
struct lrfields {
char name[26];
lrfield *f;
};
struct lrfields lr_table[] = {
{"pri_tran_code1", pri_tran_code2},
{"sec_tran_code", sec_tran_code},
{"type_code", type_code},
{"sys_seq_nbr", sys_seq_nbr},
{"authorizer", authorizer},
{"void_code", void_code},
{"",0}
};
char *pri_tran_code2()
{
return pri_tran_code;
}
*
*
if(second)
{
for(bp=lr_table; bp->name[0]; bp++)
if(strcmp(bp->name, second)==0)
{
tmpval=bp->f();
break;
}
}
I have got these errors:
error: `pri_tran_code2' undeclared here (not in a function)
error: initializer element is not constant
error: (near initialization for `lr_table[0].f')
error: initializer element is not constant
error: (near initialization for `lr_table[0]')
error: initializer element is not constant
error: (near initialization for `lr_table[1]')
As you can see in the code that i have defined 'pri_tran_code2' above its call. Please help me to solve this error.
Add char *pri_tran_code2(); before you mention this name? Or simply move the whole implementation there. It doesn't matter where you call it, what matters is where you refer to it.
Your declaration is erroneous. To declare a function (function-pointer) type, try this instead:
typedef char *(*lrfield)();