954,505 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

Need help understanding external functions

Can someone please explain to me and show a sample of using external function?

Let say I have my main file: main.c
and other file only with function: print.c

I know I should prototype print function in my main.c, define it in print.c and call it from main.c. (at least I think that's how it is)

when I do it, the compiler refuses to work, that's why I need some sample which I could not find anywhere (ebooks, google, textbook) - really weird.

Thanks in advance

DeathEvil
Light Poster
49 posts since Jul 2007
Reputation Points: 10
Solved Threads: 0
 
/* main.c */
extern void foo ( void );

int main ( void )
{
  foo();
  return 0;
}
/* print.c */
#include <stdio.h>

void foo ( void )
{
  puts ( "foo!" );
}

That's all it takes. In fact, you don't even need the extern keyword for the prototype (but it aids clarity). If that's what you're doing, can you explain how the compiler "refuses to work"?

Narue
Bad Cop
Administrator
15,460 posts since Sep 2004
Reputation Points: 6,464
Solved Threads: 1,401
 

thanks for quick reply, yes this is what I do and it fails. when I compile it is says linker erros undefined reference to'my()'

where my() is the function in print.c file

DeathEvil
Light Poster
49 posts since Jul 2007
Reputation Points: 10
Solved Threads: 0
 

How are you compiling and linking your files?

Narue
Bad Cop
Administrator
15,460 posts since Sep 2004
Reputation Points: 6,464
Solved Threads: 1,401
 

// main.c

extern void my(void); //prototype

........

my(); //function call

// my.c

#include
my(void)
{
printf"external function works!!!!!");
}

DeathEvil
Light Poster
49 posts since Jul 2007
Reputation Points: 10
Solved Threads: 0
 

Well first, your prototype and definition don't match. If you omit the return type, that's call implicit int and an int return type will be assumed, not void. Second, I asked how you're compiling and linking, not to post your code.

Narue
Bad Cop
Administrator
15,460 posts since Sep 2004
Reputation Points: 6,464
Solved Threads: 1,401
 

I'm using visual studio 2005, but I just tried gcc, devc++, and they fail too

DeathEvil
Light Poster
49 posts since Jul 2007
Reputation Points: 10
Solved Threads: 0
 

Okay, then post your exact code so that I can try it out.

Narue
Bad Cop
Administrator
15,460 posts since Sep 2004
Reputation Points: 6,464
Solved Threads: 1,401
 

You likely don't link your my.c anyhow. It depends on your compiler, like gcc main.c my.c -o main both compiles the modules, and links them, producing the executable main. This is similar for all compilers, but the problem is when you use some graphical ide, which is bad anyhow, but if you do, you must add your my.c in project, so that the ide knows what files need to be linked. Usually, the function prototypes and global variables defined in one file,would be declared not in that file, but in include file, like my.h, which would be included to both files, with #include . It works also otherwise, but this is a good habbit, so that you don't always have to write your declarations separately in every file. If you are very lazy, your program would certainly compile if you would include your c file to the main file, with #include , but it's not good to be that lazy.

TkTkorrovi
Junior Poster
170 posts since Mar 2005
Reputation Points: 85
Solved Threads: 13
 

It works fine for me in Visual Studio 2005 after correcting the syntax errors, setting the correct return type for your external function, and compiling as C++ because that's clearly what you're doing. Post the errors you get when you build.

Narue
Bad Cop
Administrator
15,460 posts since Sep 2004
Reputation Points: 6,464
Solved Threads: 1,401
 

Oh sorry, something with my attention, <> in include statement means that the files would be included from a system directory, there are some default include directories for every compiler. But you need to put the file name between the "", if it is in your project's directory. So #include "my.h" or #include "my.c". Sorry again.

TkTkorrovi
Junior Poster
170 posts since Mar 2005
Reputation Points: 85
Solved Threads: 13
 

errors I'm getting

Error 1 error LNK2019: unresolved external symbol "void __cdecl test(void)" (?test@@YAXXZ) referenced in function _main Full Working aligned VS20051.obj

Error 2 fatal error LNK1120: 1 unresolved externals C:\Users\DeathEvil\Documents\Visual Studio 2005\Projects\DeathEvil\Debug\DeathEvil.exe

what syntax errors have you detected?

when calling test() i just added void in front of it and now it compiles, but I still don't see "The function works!!!!" print??

DeathEvil
Light Poster
49 posts since Jul 2007
Reputation Points: 10
Solved Threads: 0
 

I can't help if I can't reproduce the problem. Your code works fine once I clear up the compilation errors, which suggests that your files are somehow not set up properly in the project.

Narue
Bad Cop
Administrator
15,460 posts since Sep 2004
Reputation Points: 6,464
Solved Threads: 1,401
 

You need to write for functions, prototypes (except where you define it if it is before the other functions which use it, but good if they are there even then), and for global variables, declarations, and exactly the same prototypes or declarations both in the file where you define function or give a value to a global variable, and in the file where you use them. If the linker finds that the declarations are the same in two or more modules, it considers that they refer to the same function or variable. That's all, as simple as that, just do it correctly.

TkTkorrovi
Junior Poster
170 posts since Mar 2005
Reputation Points: 85
Solved Threads: 13
 

Try changing it to:-

/* main.c */
#include "print.c"

int main ( void )
{
  foo();
  return 0;
}



I used gcc and that worked.

/* print.c */
#include <stdio.h>

void foo ( void )
{
  puts ( "foo!" );
}


output

>g++ -Wall main.c

>./a.out
>foo!
iamthwee
Posting Expert
5,950 posts since Aug 2005
Reputation Points: 1,543
Solved Threads: 439
 

>I used gcc and that worked.
Well yea, of course it would work because #include just pastes the text of the print.c into main.c. It's also dangerous if you decide to do this in multiple files. You'll get more linker errors about multiple definitions. It's better to learn to do it the right way than to hack something that "just works".

Narue
Bad Cop
Administrator
15,460 posts since Sep 2004
Reputation Points: 6,464
Solved Threads: 1,401
 

Why is it dangerous if no duplicate definitions of foo exist?

iamthwee
Posting Expert
5,950 posts since Aug 2005
Reputation Points: 1,543
Solved Threads: 439
 

>Why is it dangerous if no duplicate definitions of foo exist?
Include the file one more time and duplicate definitions do exist. The only way to defend against that kind of error is to name the file something obviously different from *.c or *.h:

#include "print.def"

int main ( void )
{
  foo();
  return 0;
}

That way it catches your eye, but you're still relying on the user of the file to do the right thing. It's much much safer to do the header/implementation setup:

#include "print.h"

int main ( void )
{
  foo();
  return 0;
}
#ifndef PRINT_H
#define PRINT_H

void foo ( void );

#endif
#include <stdio.h>
#include "print.h"

void foo ( void )
{
  puts ( "foo!" );
}
Narue
Bad Cop
Administrator
15,460 posts since Sep 2004
Reputation Points: 6,464
Solved Threads: 1,401
 

It is dangerous if you include the same c file in more than one file. The linker doesn't complain about multiple declarations but it complains about multiple definitions. This is why the definitions and declarations are usually split into two files, the *.c file for definitions, and *.h file for declarations, then we can safely include the *.h file everywhere, both where we defined these things, and to every file where we use them.

TkTkorrovi
Junior Poster
170 posts since Mar 2005
Reputation Points: 85
Solved Threads: 13
 

I don't get it? Where do ya put this:-

#ifndef PRINT_H
#define PRINT_H

void foo ( void );
#endif



Plus I still don't see the difference between doing a #include "somthing.c" and a #include "something.h"

iamthwee
Posting Expert
5,950 posts since Aug 2005
Reputation Points: 1,543
Solved Threads: 439
 

This article has been dead for over three months

Post: Markdown Syntax: Formatting Help
You