10-22-2009 05:02 AM - edited 10-22-2009 05:03 AM
Another day another problem.
Fisrtly, I'd like to express thanks for all those willing to help such a patently obvious N00b in the CVI area. I'm going through a very steep learning curve with CVI at the moment.....
My problem is:
I'm getting a "redeclaration" error trying to ocmpile my DLL:
110, 1 Redeclaration of 'ListDevices' previously declared at somethingorother.h:37.
I want to pass a pointer to a struct to my DLL to be populated by a C routine. My Struct definition is as follows
struct Deviceinfo {
int vid;
int pid;
int Interface;
char serialnr[255];
};
struct DevList {
int Count;
struct Deviceinfo devs[128];
};
I want to pass a pointer to the DevList struct.
My function declaration (.c file) is
void ListDevices(struct DevList *buf)
{
and my export declaration(.h file) is
void ListDevices(struct DevList *);
Anyone got any ideas as to what I'm doing wrong? I'm aware that 128 instances of 255 chars is a bit excessive but I want to walk before I run. Getting it working comes before optimisation. I can only tackle one problem at a time.
Shane.
Solved! Go to Solution.
10-22-2009 05:09 AM
Heh,
just solved the problem.
Struct definitions must go into the .h file, not the .c file (their location until now) in order for the .h and .c definitions to "see" the same declarations.
.h processed before .c. Must remember that.
Shane.
10-22-2009 07:28 AM
i would complement your own answer by saying that every identifier has to be defined somewhere before being used. in fact, the compiler needs to know the size of a type before being able to use that type in a declaration (variable declaration, function parameter list, etc.). this is because the size matters when generating the output code.
(warning: the remaining is quite advanced C programming. )
to go further, you need to know that pointers have a fixed size which is intrinsic to the compiler: the size of a pointer depends on the processor architecture, thus it is well-known (this also applies to primary types like int, double, or such). thus, in a header file you can write:
struct something;
this declares a structure type named something whose content is unknown. then, in the same header, you can use a pointer to this structure, although the content of the structure is still unknown. the content will be filled later.
so to summarize:
device.h:
struct DevList; // now the name exists, but we still don't know what it contains
void ListDevices( struct DevList *buffer ); // we use the name.
device.c:
#include "device.h"
[...]
struct DevList
{
int count;
Deviceinfo devs[128];
};
void ListDevices( struct DevList *buffer )
{
[...]
}
this is perfectly valid C, and allows the use of "opaque" types: the type DevList exists anywhere outside device.c, but its content is unknown. so anyone can use a pointer to DevList, although its content is unknown, since the size of a pointer is known. of course, since the content of DevList is only known inside device.c, you can manipulate the content of a DevList only inside functions declared in device.c. this way of hiding the content of a structure is called data abstraction.
another use of this is for what is called a "forward declaration", which is used to declare types that mutually refers to each other, like the node of a linked list for example.
10-22-2009 07:51 AM
Thanks for the great answer,
I had a little trouble working out the syntax for declaring an Opaque item included in the Libusb package "usb_dev_handle". It is intended to be passed as a pointer only without garnering access to the internals (which may change in future implementations).
Now I understand why it's declared in the way it is. It confused me a little at first but your post cleared that up for me.
I've enough low-level knowledge of programming languages to understand everything you wrote, I'm just seriously low on practise (since 15 years or so).
In my example I need access to the internals so I just declared the entire thing in the header file and it's working now no problem. It also explains why (in some answers I found in the internet) passing the structure as a pointer (without declaring the type properly) often clears compile problems (size of function parameter is known despite unknown data structure).
Again, thanks for the response.
Shane.