Passing an instance of struct to functions in other src files


 
Thread Tools Search this Thread
Top Forums Programming Passing an instance of struct to functions in other src files
# 1  
Old 03-31-2011
Passing an instance of struct to functions in other src files

I am trying to work out the best syntax for a relatively simple operation. The goal is to declare an instance of a struct and pass it around to be populated and have the data manipulated. There is an extra wrinkle in that the functions are in different src files.

The main is simple,
Code:
#include <iostream>
#include <stdio.h>
#include "struct1.h"
#include "extern_funcs.h"

int main(int argc, char**argv) {

   // declarations
   STRUCT1 myStruct1;
   int answer;
   int a, b, c, d;
   
   // load data
   a = 1; b = 2; c = 3; d = 4;

   // call functionto load data into stuct
   load_struct( &myStruct1, a, b, c, d );

   // get answer
   answer = calc_struct( &myStruct1 );

   std::cout << "the answer is " << answer << std::endl;

   return 0;
}

With the struct definition and the prototypes for the external functions in header files.
Code:
// struct1.h
// structure definition

typedef struct STRUCT1 {
   int var_a;
   int var_b;
   int var_c;
   int var_d;
} STRUCT1;

Code:
// external_funcs.h
// prototypes for external functions

extern "C" {
   void load_struct( STRUCT1 *myStruct1,
                     int var_a, int var_b, int var_c, int var_d );
   int calc_struct( STRUCT1 *myStruct1 );
}

Then there are two other functions, one to load data into the struct, and the other to do a simple calculation based on the loaded data.
Code:
// load_struct function
#include <stdio.h>
#include "struct1.h"

void load_struct( STRUCT1 *myStruct1, int var_a, int var_b, int var_c, int var_d)

   // load struct with passed data
   myStruct1.var_a = var_a;
   myStruct1.var_b = var_b;
   myStruct1.var_c = var_c;
   myStruct1.var_d = var_d;

   return;

}

Code:
#include <stdio.h>
#include "struct1.h"

int calc_struct( STRUCT1 *myStruct1 ) {

   int answer;

   answer = myStruct1.var_a + myStruct1.var_b + myStruct1.var_c + myStruct1.var_d;

   return answer;
}

As usual, I am a bit confused about passing by reference, pointer, value, etc. The main function compiles, but load_struct does not and gives the following errors.
Code:
load_struct.cpp:8: error: expected init-declarator before "myStruct1"
load_struct.cpp:8: error: expected `,' or `;' before "myStruct1"
load_struct.cpp:9: error: expected constructor, destructor, or type conversion before '.' token
load_struct.cpp:9: error: expected `,' or `;' before '.' token
load_struct.cpp:10: error: expected constructor, destructor, or type conversion before '.' token
load_struct.cpp:10: error: expected `,' or `;' before '.' token
load_struct.cpp:11: error: expected constructor, destructor, or type conversion before '.' token
load_struct.cpp:11: error: expected `,' or `;' before '.' token
load_struct.cpp:13: error: expected unqualified-id before "return"
load_struct.cpp:13: error: expected `,' or `;' before "return"
load_struct.cpp:15: error: expected declaration before '}' token
make: *** [load_struct.o] Error 1

The compiler doesn't appear to like the way I am doing the assignments. I don't know if this is because I have the improper syntax for the assignment, or if I have not passed the struct properly. It also appears that it is necessary to include the header file with the struct definition in all the src files, is that correct?

I have attached the src, including a make, if anyone is interested. Suggestions would be very much appreciated,

LMHmedchem
# 2  
Old 04-01-2011
You don't use "." for pointers, you use ->.

You should include external_funcs.h in load_struct.cpp and calc_struct.cpp too. Otherwise the compiler can't warn you when you create the functions differently than you specified in your header file -- that's a bug which can be a real pain to find the source of.

Beyond that, your code looks fine.
This User Gave Thanks to Corona688 For This Post:
# 3  
Old 04-01-2011
Quote:
Originally Posted by Corona688
You don't use "." for pointers, you use ->.

You should include external_funcs.h in load_struct.cpp and calc_struct.cpp too. Otherwise the compiler can't warn you when you create the functions differently than you specified in your header file -- that's a bug which can be a real pain to find the source of.

Beyond that, your code looks fine.
Thanks, I knew there were a few things I forgot.

I extended the exercise to have the calc function called by the loading function and was surprised to find that you don't use the & (if you want it to compile).

Code:
// main.cpp
#include <iostream>
#include <stdio.h>
#include "struct1.h"
#include "extern_funcs.h"

int main(int argc, char**argv) {

   STRUCT1 myStruct1;
   int answer = 0;
   int a, b;
   a = 1; b = 2; 
  
   // call functionto load data into stuct
   load_struct( &myStruct1, a, b, c, d, &answer );

   // print data from struct
   std::cout << "var_a main " << myStruct1.var_a << std::endl;
   std::cout << "var_b main " << myStruct1.var_b << std::endl;

   std::cout << "the answer is " << answer << std::endl;

   return 0;
}

Code:
// load_struct.cpp
#include "struct1.h"
#include "extern_funcs.h"

void load_struct( STRUCT1 *myStruct1, int var_a, int var_b, int *answer ) {

   // load struct with passed data
   myStruct1->var_a = var_a;
   myStruct1->var_b = var_b;

   // call to get answer
   *answer = calc_struct( myStruct1 );

   return;
}

Code:
// calc_struct.cpp
#include <stdio.h>
#include "struct1.h"
#include "extern_funcs.h"

int calc_struct( STRUCT1 *myStruct1 ) {
   int answer;
   // perform calcualtion
   answer = myStruct1->var_a + myStruct1->var_b;
   return answer;
}

Code:
// struct1.h
// structure definition

typedef struct STRUCT1 {
   int var_a;
   int var_b;
} STRUCT1;

Code:
// external_funcs.h
// prototypes for external functions

extern "C" {
   void load_struct( STRUCT1 *myStruct1, int var_a, int var_b, int *answer );
   int calc_struct( STRUCT1 *myStruct1 );
}

The call to load, passing the pointer to myStruct1, is set up as,
load_struct( &myStruct1, a, b, c, d, &answer );

where both myStruct1 and answer are pointers to a var declared in main().

The call to calc seems to be passing the same instance of struct by value,
*answer = calc_struct( myStruct1);

and doesn't compile if you try to pass it as a pointer,
*answer = calc_struct( &myStruct1);

Is that because the compiler already sees the value as pointer, and so would be trying to do **myStruct1? All of the programming I initially learned was in Fortran, where everything is passed as a pointer and there is usually only one way to do most things.

Would this work just as well if the prototypes were absent the extern "C" tag? In the past, I have had a few issues with things in header files where the compiler complained that something was declared in more than one place. I have also has some issues with the linker finding things when the src is spread across multiple src files. I make enough little errors that I can't always be sure if the issue is my choice of method, or its implementation. It appears that it is proper to have struct/class definitions, or function prototypes, in header files that are included in multiple places. Is that correct?

LMHmedchem
# 4  
Old 04-01-2011
Quote:
Originally Posted by LMHmedchem
Thanks, I knew there were a few things I forgot.

I extended the exercise to have the calc function called by the loading function and was surprised to find that you don't use the & (if you want it to compile).
The & operator turns a vartype into a vartype *. Your function already has a vartype *, using & on that turns it into a vartype **varname -- which actually ends up pointing to the local pointer variable inside your function. C++ notices you're trying to put a pointer of the wrong type into it and refuses to let you, which is good, since that'd probably crash. In C, this is only a warning.
Quote:
Is that because the compiler already sees the value as pointer, and so would be trying to do **myStruct1?
When you do a function declaration, int calc_struct( STRUCT1 *myStruct1 ) that "STRUCT *myStruct1" declares a local variable named myStruct1, of the the type "pointer". That's just a numeric variable with enough bits to hold a memory address on your architecture. You already have a pointer and really couldn't have anything else but a pointer if you gave it one -- pointer operations are always done explicitly, the compiler will never decide to make a pointer a not-pointer for you (or vice-versa).

In other words, pointers never do anything weird behind your back, don't use their contents for you, don't change into different types for you. They're just numbers, they just sit there. All that's different is their *, &, and [] operators.
Quote:
Would this work just as well if the prototypes were absent the extern "C" tag?
I think so.

What extern "C" does is it forces the function to have that exact same in the compiled program. Without it, C++ will give it some crazy hashed name, which lets you do operator overloading -- different functions with the same text name won't have the literal same name in the program, and so won't interfere with each other, as long as they take different parameters.
Quote:
In the past, I have had a few issues with things in header files where the compiler complained that something was declared in more than one place.
This is unrelated to extern "C". What it means is you put the actual function inside the header file, so it got compiled separately in every source file that used it. Or declared a variable in the header without declaring it as extern.
Quote:
I have also has some issues with the linker finding things when the src is spread across multiple src files. I make enough little errors that I can't always be sure if the issue is my choice of method, or its implementation. It appears that it is proper to have struct/class definitions, or function prototypes, in header files that are included in multiple places. Is that correct?
Yes, exactly. Don't define the contents of functions or variables or objects or members in headers -- all headers should do is state that they exist.

The same goes for variables if you want to share them between different files.

Code:
// In the header
extern int some_var; // Variables need extern here.
void function_name(void); // Functions don't, if you don't give them a code block.

// In ONE AND ONLY ONE source file
#include "var_header.h"
int some_var=32; // This actually creates the variable.

void function_name(void)
{
        printf("OMGWTFBBQ\n");
}


// Variable and function are available in every other source file
// when you link them all together.
#include "var_header.h"
printf("Var is %d\n", some_var);
function_name();


Last edited by Corona688; 04-01-2011 at 04:39 PM..
# 5  
Old 04-01-2011
Thanks again for your patient and thoughtful replies, they are a huge help.

I have a few instances where I have function definitions in header files. These are usually functions that are only included when specific things have been defined, #ifdef, etc. I guess it would be better to have the functions definitions in their own object and implement the abstraction in the make file by linking the additional objects under the specified conditions.

So for global variables, you declare those in a header file (as extern), and then include the .h in only one src file? Then you have to re-declare and initialize the var in the same src file where the header is included ? That is so different from Fortran when you have to include global (common) variables in every src file where they are used, and then if you re-declared it, you would get a compiler bonk.

I am still a bit confused about the function prototypes. Lets say we are not using extern "C", can I declare the function prototype (with no code block) in one and only one header file, or do I need to include the header file in every src file that will be using the function. The latter is my current understanding or how things work.

LMHmedchem
# 6  
Old 04-01-2011
Quote:
Originally Posted by LMHmedchem
Thanks again for your patient and thoughtful replies, they are a huge help.

I have a few instances where I have function definitions in header files. These are usually functions that are only included when specific things have been defined, #ifdef, etc. I guess it would be better to have the functions definitions in their own object and implement the abstraction in the make file by linking the additional objects under the specified conditions.
Depends what they are. If they're very short thing you might be able to make them either macros or inline functions, both of which are safe to put in headers.
Quote:
So for global variables, you declare those in a header file (as extern), and then include the .h in only one src file?
Sorry if that was unclear. You include the header in both the thing that declares it, and anything that uses it.
Quote:
Then you have to re-declare and initialize the var in the same src file where the header is included ?
It's a safety-check to make sure you're creating the same kind of variable your header says you are. C/C++ are, technically, low-level languages, so creating variables and function ends up being done in assembly language, and assembly language is all about memory and symbols.

You don't HAVE to include the header but it's a great idea to do so. I had to debug a library where there was an "internal" headerfile which was only used by the library and an "external" headerfile which was only used by things using the library. Very odd way to do things, especially considering the amount of extra work it took to do so.

One of the functions used a 'long int' parameter, but the external header said it was a 'uint32_t' -- a guaranteed 32-bit integer. On 32-bit machines a long is 32-bit, but on a 64-bit architecture, it's not! This caused extremely bizzare errors in 64-bit architectures, returning a nonsensical errorcode even when the function actually succeeded. Not even a debugger could tell what was going wrong. If they'd just included the external header, the compiler would have told them "your function isn't what your header says it is!" and refuse to go.
Quote:
That is so different from Fortran when you have to include global (common) variables in every src file where they are used, and then if you re-declared it, you would get a compiler bonk.
It's because of how C/C++ lets you compile each file completely separately. You can declare that a variable or function exists anywhere, and if it's not available at compile-time, it'll be able to find it when the objects are all linked together. But you only should declare what a variable or function is, once.
Quote:
I am still a bit confused about the function prototypes. Lets say we are not using extern "C", can I declare the function prototype (with no code block) in one and only one header file, or do I need to include the header file in every src file that will be using the function.
Include it everywhere, yes. It never implicitly includes anything. Each .c/.cpp file is compiled completely separately, one C file doesn't give a darn if you included so and so header in a file you compiled 900 microseconds ago.

---------- Post updated at 02:11 PM ---------- Previous update was at 01:52 PM ----------

Another way to put it would be that C or C++ requires you to explicitly declare everything, be it a library function, internal variable, external variable, or what have you. (C++ is stricter about this than C. C is willing to assume external functions exist if you try to use them, which is sometimes a problem.) It's very simple, very straightforward, and extremely simpleminded -- imagine a language where you're supposed to manually define all your library functions before you're allowed to use them! That's how C works. It does this because each C file is its own separate little universe when compiled, completely blind to any help from other source files until the final linking step.

Because doing that by hand is silly they put all of that mess into header files. But header files have no special behavior. Copy/pasting the raw contents of a header file into your source code would have the same effect as including it. So the rules remain the same: Explicitly declare the existence of every symbol you want to import into your source code. And just to be fair, explicitly declare the existence of every symbol you want to export too. "This symbol exists and I'm using it", or, "This symbol exists and I'm creating it".

Last edited by Corona688; 04-01-2011 at 05:18 PM..
Login or Register to Ask a Question

Previous Thread | Next Thread

10 More Discussions You Might Find Interesting

1. Shell Programming and Scripting

ksh While Loop - passing variables to functions

I'm reading a text file using a while loop but when I call a function from within this loop it exits that same iteration … even though there are many more lines in the file to be read. I thought it was something to do with the IFS setting but it appears that a function call (when run... (3 Replies)
Discussion started by: user052009
3 Replies

2. Shell Programming and Scripting

Python passing multiple parameters to functions

Hi, I am a beginner in python programming. In my python script have a main function which calls several other functions. The main function gets its input by reading lines from a input text file. I call the main function for every line in input text file through a loop. def main(line): var1... (6 Replies)
Discussion started by: ctrld
6 Replies

3. Programming

Using pointers to struct members as args to functions

In a well-known book on the C language, there is an example of an efficient method for using a struct member as an argument to a function. (I'm a C noob, but I believe the correct terminology might be: use call-by-reference instead of call-by-value.) The function is printf. Anyway, here's a... (5 Replies)
Discussion started by: uiop44
5 Replies

4. Shell Programming and Scripting

Passing variable to child instance of make

hi, I am trying to export a variable from the parent makefile to a child instance of my makefile within the same directory. the relevant code in my parent makefile is: libvar := $(notdir $(basename ../src/file1)) export libvar .PHONY: library library: make -f makechild libvar=file1... (0 Replies)
Discussion started by: bacpp
0 Replies

5. Homework & Coursework Questions

Passing pointers to struct

Hi, i'm trying to copy a struct into a binary file using the unix instruction write, so i declare and fill the struct "superbloque" in one function "initSB" and then i pass the pointer to another function called bwrite (for block write) which calls write. The problem is that i call the function... (2 Replies)
Discussion started by: ignatius3
2 Replies

6. UNIX for Dummies Questions & Answers

Passing struct through unix pipe -solved

EDIT: Nevermind, called a friend who is good at this stuff and he figured it out :D Hi all, So I'm trying to teach myself to write programs for unix in c. I am currently creating a program, and I need to pass a struct through a pipe, but I can't figure out how. The struct I want to pass... (0 Replies)
Discussion started by: twnsfn34
0 Replies

7. Homework & Coursework Questions

C++ struct pointers & functions

Hi All, My latest assignment (practice not coursework!) is to write prototype interactive exam/test console application. I've used structs to store the question information (not sure if this was the best way to do it?) and I have the following code that outputs each question and it's possible... (0 Replies)
Discussion started by: pondlife
0 Replies

8. UNIX for Advanced & Expert Users

Passing socket struct between kernel threads - module programming

I write kernel module with kernel threads using linux/kthread.h on 2.6.* kernel I tried to passing data between two kernel threads with data argument of kthread_run( fun, data , NAME ); but this is not work I dont know why. I tried many possibility and nothing works. So I thought that... (0 Replies)
Discussion started by: marcintom
0 Replies

9. Shell Programming and Scripting

Passing arrays between functions

Hi, I have a function that hold 3 arrayies. I need to pass them to another function as an input, for further use Could you please explain how to do that. Thanks (5 Replies)
Discussion started by: yoavbe
5 Replies

10. Shell Programming and Scripting

passing command line parameters to functions - sh

All, I have a sh script of the following tune: function a () { #functionality.. } function b () { #functionnlity.. } function check () { # this function checks for env and if all fine call build } function usage () { #sh usage details } function build () { #calls either a or b or... (5 Replies)
Discussion started by: vino
5 Replies
Login or Register to Ask a Question