LNK 2019 while compiling main.c - c

I am just a beginner in C and Visual Studio and I have this weird error.
I declared a function in cipher.h and defined it in cipher.c (I have included cipher.h in cipher.c). I include cipher.h in main.c and used the function. But it gives me this error while compiling main.c:
unresolved external symbol test_encrypt referenced in function _main
Here are the codes:
cipher.h:
#pragma once
#include <stdio.h>
#include <stdbool.h>
void test_encrypt(char message[]);
cipher.c:
#include "cipher.h"
void test_encrypt(char message[])
{
message[0] = '0';
}
main.c:
#include <stdio.h>
#include "cipher.h"
int main(void)
{
// open a text file and read the text into an array called buffer
// the text is "54321"
test_encrypt(buffer);
printf(buffer);
}
Everything works fine if I remove the line that use test_encrypt function.
Thanks in advance.

Think about the C compilation stages.
First C sources are built into objects. Those are compiled files which are like building blocks of your final executable. When you call cipher in your main, the compiler looks at the included headers and see if it finds anything that matches it. Since you have defined the function prototype, the compiler knows that such function exists somewhere, but it does not know where, at this stage.
The main.o object will have a reference to cipher declared as "external". After this stage of compilation, it's the linker job to be sure that the symbols you have are somewhere. From here it looks either in the other object files or in some libraries, and if it can't find it anywhere, it throws the error you are seeing.
What I can imagine it's happening here is that you didn't specify "cipher.c" to be part of you VS project, hence "cipher.o" is not being built, resulting in the error from the linker.

Related

How to call functions from a pre-compiled C library within Rust

Long story short, I want to call C code from Rust... I've seen crates like cc and cmake which (to my understanding, which might be wrong) can compile C code for use with the Rust language. Though I am capable of producing a compiled .lib file using the CLion IDE. Now I would like to simply link to said .lib file from Rust and just call the code within, is this possible? I have tried a few things, but they just do not seem to link at all...
project structure:
my_rust_project/
my_c_project/
cmake_build_debug/
...
my_c_project.lib
...
...
a_c_file.h
a_c_file.c
...
src/
main.rs
cargo.roml
build.rs
...
build.rs:
fn main() {
println!("cargo:rustc-link-search=my_c_project/cmake-build-debug/");
println!("cargo:rustc-link-lib=static=my_c_project/cmake-build-debug/my_c_project");
}
main.rs:
#[link(name = "my_c_project/cmake-build-debug/my_c_project", kind = "static")]
extern "C" {
fn hello();
}
fn main() {
unsafe {
//hello(); /* if commented the project compiles... */
}
}
Note how you could comment out any of the two prinln!'s in build.rs as well as the #link directive from main.rs in any combination you could think of (i.e. commenting out #link and leaving the println's, or commenting out one println and leaving the #link, and so on...) and the project will continue to compile, though as soon as you uncomment hello(); from fn main() in main.rs, the project will not compile and produce the following error:
LNK2019: unresolved external symbol hello referenced in function blah blah blah ...
I think there is two possible causes, either the library is not link at all, which seems to be the most logical issue to me, which raises the question: what exactly do the println!'s and #link do in this specific scenarion, they do not cause a panic! or error so they must definitly be doing something right? Whatever it is, it cannot be linking the project.
The other issue I can imagine is that there is in fact proper linking going on-ish? But Rust just doesn't understand where exactly to find the function hello within my_c_project.lib...
For clarity I will provide the contents of my_c_project:
a_c_file.h:
#ifndef MY_C_PROJECT_A_C_FILE_H
#define MY_C_PROJECT_A_C_FILE_H
void hello();
#endif //MY_C_PROJECT_A_C_FILE_H
a_c_file.c:
#include "a_c_file.h"
#include <stdio.h>
void hello() {
printf("Hello, World!\n");
}
I really want to stress that I want to stay away from cc and cmake (crates) since I have the .lib file ready to go... The question remains, how to call the C functions from a .lib file from within a Rust program?
Thanks for the help!
newly tried thing...
changed build.rs to:
fn main() {
println!("cargo:rustc-link-search=my_c_project/cmake-build-debug/");
println!("cargo:rustc-link-lib=static=my_c_project");
}
changed main.rs to:
extern {
fn hello();
}
fn main {
}
renamed my_c_project.lib to libmy_c_project.lib...
This still produces an error:
LINK : fatal error LNK1181: cannot open input file 'libmy_library.lib'
I guess it does not require a .a file per se as it says .lib in the message above.
If anyone ever has this problem... I solved this by continuing the project on Linux using cross compilers to generate the executable for windows.
The matter is to compile everything (source code and libraries/dependencies) for the target platform using the correct compilers ofcourse.

'undefined reference to function' while trying to build a program with header that redefines function names

I'm having the exact same problem as a person that asked this question: How to hide the exported symbols name within a shared library
I decided to follow instructions given by Alexander (3rd answer) but after including a generated header to my main program in C, i get the error undefined reference to function
head.h
#define SecretFunc1 abab
application.c
#include <stdio.h>
#include "head.h"
int main(){
SecretFunc1();
return 0;
}
libdyn.c
#include <stdio.h>
int SecretFunc1(){
return 2
}
I've built the dynamic library into .so file, then after trying to build the app with:
gcc app.c -L<path> -ldyn -o sample
In function main undefined reference to abab
I don't really know what to do.
After (partial) preprocessing, your application.c would look like this:
#include <stdio.h>
int main(){
abab();
return 0;
}
This should, first of all, give you a warning, that abab is declared implicitly, which usually is not a good idea. You should declare the function (in a header file shared by application.c and libdyn.c):
int SecretFunc1(void);
When compiling to an object file, this object file will have a reference to the symbol abab.
After compiling libdyn.c to an object file, it will provide a symbol named SecretFunc1. Therefore, the linker will not match it to the reference abab in application.o.
You need to rename the function in all files using it, e.g. by including head.h in libdyn.c as well or better putting both the renaming macro and the declaration in a libdyn.h that is included in both libdyn.c and application.c.

CLion not finding header in main.c for use in external .c file

So my situation is something like this, I have three files:
main.c:
#include <stdio.h>
#include "hello.h"
int main() {
hello();
}
hello.h:
void hello();
hello.c:
void hello() {
printf("Hello");
}
My Cmake file looks something like this:
cmake_minimum_required(VERSION 3.3)
project(test)
set(SOURCE_FILES main.c hello.c)
add_executable(test ${SOURCE_FILES})
The code runs fine. However CLion doesn't recognise the printf() function in hello.c, and wants me to add it as a header file. Is there a way to make it see the #include <stdio.h> in the main.c file, and stop giving me a hard time?
So I fixed this to my own satisfaction by making the functions defined in my .c files return values rather than calling printf inside those functions. Then printing the values returned in main.c
hello.c and main.c are independent compilation units and as such needs to have #include <stdio.h> in both. Actually in your example having #include <stdio.h> in main.c accomplishes nothing as nothing forward declared there is being used in hello.h nor main.c.
You should actually be seeing warnings when compiling hello.c on its own.
When the compiler finds a function it does not know (has not been declared yet), it assumes it has the signature int function_X(void). So for your case it will be wrong for printf which has int printf(char const*, ...). But you are lucky, due to the way that arguments are passed in your platform, everything works out.
So you basically need to forward declare functions to ensure that when compiling the compiler knows where to place the arguments so that the called function can find it.
There is more to it but this short explanation should be enough for a beginner and if you read one of the books in the link I provided in the comments you should be able to understand it better.

"Already defined in object file" and "one or more multiply defined symbols found"

Going through the RPC tutorial at MSDN,
I have just created a project with two .c files as following::
/* file hellop.c */
#include <stdio.h>
#include <windows.h>
void HelloProc(char * pszString)
{
printf("%s\n", pszString);
return ;
}
and
/* file: hello.c */
#include "hellop.c"
void main(void)
{
char * pszString = "Hello, World";
HelloProc(pszString);
return ;
}
Problem:: Error LNK2005 and fatal Error LNK1169
Why and where is the compiler seeing the multiple symbol definition or declaration of HelloProc(char*) ?
EDIT:: As concluded in this SO_Question, including .h file is the best solution obviously. But does that leave us with no implementation of design where we can include a .c file into another .c file?
Weird Behavior:: First time compilation runs fine but rebuild of solution breaks with the above mentioned errors. You can check the multiple first time compilation by changing the file name from .c to .cpp and vice-versa. Why does it exhibit this behavior? (I am not sure if anybody else have also experienced this with the given example)
You compiling HelloProc twice, as you include the whole definition of of this function in hello.c file by #include "hellop.c", while you only need declaration of it. You should put function prototype in header file.
#ifndef HELLOP_H
#define HELLOP_H
#include <stdio.h>
#include <windows.h>
void HelloProc(char * pszString);
#endif
And include header file both in hellop.c and in hello.c
Edit: #include is not cut-paste as you said, it is more copy-paste
# include "q-char-sequence" new-line
causes the replacement of that directive by the entire contents of the
source file identified by the specified sequence between the "
delimiters
so you get to linkage with two definitions of HelloProc one in hellop.c and another one in hello.c. Another way to solve it is to compile only hello.c file, this way there is no duplicate of HelloProc. See how to do it in VisualStudio here

How to prevent multiple definitions in C?

I'm a C newbie and I was just trying to write a console application with Code::Blocks. Here's the (simplified) code:
main.c:
#include <stdio.h>
#include <stdlib.h>
#include "test.c" // include not necessary for error in Code::Blocks
int main()
{
//t = test(); // calling of method also not necessary
return 0;
}
test.c:
void test() {}
When I try to build this program, it gives the following errors:
*path*\test.c|1|multiple definition of `_ test'|
obj\Debug\main.o:*path*\test.c|1|first defined here|
There is no way that I'm multiply defining test (although I don't know where the underscore is coming from) and it seems highly unlikely that the definition is somehow included twice. This is all the code there is.
I've ruled out that this error is due to some naming conflict with other functions or files being called test or test.c. Note that the multiple and the first definition are on the same line in the same file.
Does anyone know what is causing this and what I can do about it? Thanks!
You actually compile the source code of test.c twice:
The first time when compiling test.c itself,
The second time when compiling main.c which includes all the test.c source.
What you need in your main.c in order to use the test() function is a simple declaration, not its definition. This is achieved by including a test.h header file which contains something like:
void test(void);
This informs the compiler that such a function with input parameters and return type exists. What this function does ( everything inside { and } ) is left in your test.c file.
In main.c, replace #include "test.c" by #include "test.h".
A last point: with your programs being more complex, you will be faced to situations when header files may be included several times. To prevent this, header sources are sometimes enclosed by specific macro definitions, like:
#ifndef TEST_H_INCLUDED
#define TEST_H_INCLUDED
void test(void);
#endif
The underscore is put there by the compiler and used by the linker. The basic path is:
main.c
test.h ---> [compiler] ---> main.o --+
|
test.c ---> [compiler] ---> test.o --+--> [linker] ---> main.exe
So, your main program should include the header file for the test module which should consist only of declarations, such as the function prototype:
void test(void);
This lets the compiler know that it exists when main.c is being compiled but the actual code is in test.c, then test.o.
It's the linking phase that joins together the two modules.
By including test.c into main.c, you're defining the test() function in main.o. Presumably, you're then linking main.o and test.o, both of which contain the function test().
You shouldn't include other source files (*.c) in .c files. I think you want to have a header (.h) file with the DECLARATION of test function, and have it's DEFINITION in a separate .c file.
The error is caused by multiple definitions of the test function (one in test.c and other in main.c)
I had similar problem and i solved it following way.
Solve as follows:
Function prototype declarations and global variable should be in test.h file and you can not initialize global variable in header file.
Function definition and use of global variable in test.c file
if you initialize global variables in header it will have following error
multiple definition of `_ test'|
obj\Debug\main.o:path\test.c|1|first defined here|
Just declarations of global variables in Header file no initialization should work.
Hope it helps
Cheers
Including the implementation file (test.c) causes it to be prepended to your main.c and complied there and then again separately. So, the function test has two definitions -- one in the object code of main.c and once in that of test.c, which gives you a ODR violation. You need to create a header file containing the declaration of test and include it in main.c:
/* test.h */
#ifndef TEST_H
#define TEST_H
void test(); /* declaration */
#endif /* TEST_H */
If you have added test.c to your Code::Blocks project, the definition will be seen twice - once via the #include and once by the linker. You need to:
remove the #include "test.c"
create a file test.h which contains the declaration:
void test();
include the file test.h in main.c
If you're using Visual Studio you could also do "#pragma once" at the top of the headerfile to achieve the same thing as the "#ifndef ..."-wrapping. Some other compilers probably support it as well ..
.. However, don't do this :D Stick with the #ifndef-wrapping to achieve cross-compiler compatibility. I just wanted to let you know that you could also do #pragma once, since you'll probably meet this statement quite a bit when reading other peoples code.
Good luck with it
Ages after this I found another problem that causes the same error and did not find the answer anywhere. I thought to put it here for reference to other people experiencing the same problem.
I defined a function in a header file and it kept throwing this error. (I know it is not the right way, but I thought I would quickly test it that way.)
The solution was to ONLY put a declaration in the header file and the definition in the cpp file.
The reason is that header files are not compiled, they only provide definitions.

Resources