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

/* 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"?

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

// main.c

extern void my(void); //prototype

........

my(); //function call

// my.c

#include <stdio.h>
my(void)
{
printf"external function works!!!!!");
}

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.

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

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 <my.h>. 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 <my.c>, but it's not good to be that lazy.

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.

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.

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??

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.

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.

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!

>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".

>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!" );
}

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.

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"

>How do you link from the command line?
With gcc (or any other command line compiler, but gcc is the example) you can do it all in one swell foop:

$gcc main.c print.c

This compiles both files and links them together. To compile without linking you use the -c switch.

Usually, your compiler program also does the linking, ie invokes the linker. So in fact, all you need, is to write all your source files in the command line of the compiler, like this:

gcc source1.c source2.c -o executable

But if you compiled the sources separately, then you use the same compiler to link these files:

gcc source1.o source2.o -o executable

This is how the compiler finally runs, no matter whether invoked manually, by make or by ide. Ide is bad because it's confusing and difficult or sometimes impossible to use for bigger projects. But mostly makefiles are used to put together this compiler command line. Before the makefiles were used because it saved time, so that only the changed files had to be compiled, this is true for bigger projects also today, compiling of which may take some ten minutes. But the computers are fast today, so for smaller projects the makefiles would not make sense for that reason, and it may even be ok to use command line directly. But makefiles do also some other things, so some programs, like kernel modules, cannot be compiled without a special makefile, but other programs may configure better with makefiles, or such.

This article has been dead for over six months. Start a new discussion instead.