Error while compiling and linking dll - c

I am trying to compile a simple dll following the cygwin tutorial. I have been able to successfully do all but the last step. When I execute the command:
gcc -o myprog myprog.c -L./ -lmydll
I get an error saying that hello() is not declared in that scope. I followed the tutorial verbatim, yet I am still not able to compile the simple project and am lost as to why.
The code for the individual files are as follows:
(myprog.c)
int main(void){
hello();
}
(mydll.c)
#include <stdio.h>
int hello(){
printf("Hello World!\n");
return 0;
}

The example is working fine for me in my Cygwin
armathew#3NJ2VQ1 /cygdrive/d/userdata/armathew/Desktop/WWWW
$ ls
mydll.c myprog.c
armathew#3NJ2VQ1 /cygdrive/d/userdata/armathew/Desktop/WWWW
$ gcc -c mydll.c
armathew#3NJ2VQ1 /cygdrive/d/userdata/armathew/Desktop/WWWW
$ gcc -shared -o mydll.dll mydll.o
armathew#3NJ2VQ1 /cygdrive/d/userdata/armathew/Desktop/WWWW
$ gcc -o myprog myprog.c -L./ -lmydll
armathew#3NJ2VQ1 /cygdrive/d/userdata/armathew/Desktop/WWWW
$ ./myprog.exe
Hello World!
What is the Cygwin version you are using? Mine is 1.7.5
armathew#3NJ2VQ1 /cygdrive/d/userdata/armathew/Desktop/WWWW
$ uname -r
1.7.5(0.225/5/3)

well, the statement for linking library may be incorrect.
It should be
-L<library path> -lyoulibrarymane
as there is no "./" after the library path.
here is an example that I used, it may be helpful. the -I/usr/local/include is the header file path
gcc -o hello-world helloopencv.c -I/usr/local/include -L/usr/local/lib -lopencv_highgui -lopencv_core -lopencv_imgproc

You need to add a declaration at the top of myprog.c:
int hello(void);
Or you could put this in a new mydll.h and #include that in myprog.c.

Related

How to link a simple program in Windows with Mingw GCC

I have a simple "Hello World!" c program, named hello.c on my desktop:
#include <stdio.h>
int main() {
printf("Hello world!\n");
return 0;
}
I run the following commands.
I pre-process it with : cpp hello.c > hello.i
I compile it with : gcc -S hello.i
I assemble it with : as -o hello.o hello.s
All good so far. But, i'm unable to link it. I've tried, among other commands, these:
ld -o hello.exe hello.o
ld -o hello.exe hello.o -lgcc
ld -o hello.exe hello.o -nostdlib -lgcc
Nothing works. The link errors i get in every single case are :
hello.o:hello.c:(.text+0x9): undefined reference to `__main'
hello.o:hello.c:(.text+0x15): undefined reference to `puts'
How can i link this assembled program hello.o in order to finally produce the executable program hello.exe? What am i missing? [Using Windows 8.1, Mingw version 0.6.2.] Thanks in advance.
Even if your answers to clarification questions are not particularly useful:
Try something like
ld hello.o -lmsvcrt -entry=_main -subsystem=console -o hello.exe
If you want to see the linker command line the standard gcc uses, invoke gcc like so:
gcc test.c -o test -Wl,-v
The last lines output is what you should be using...
If you want to compile something rather than experimenting with tools, don't link it using the linker directly. Use gcc, which will call the linker for you with the right options:
Compile step:
gcc -c hello.c
Link step:
gcc -o hello.exe hello.o
Or all in one:
gcc -o hello.exe hello.c
You can also use a simple Makefile, then run make:
all: hello.exe

C - programming a makefile and how they work

So given three files:
main.h
#include <stdio.h>
void printFunc(*char);
main.c
#include "main.h"
int main(){
printFunc("Hello World\n");
return 0;
}
printFunc.c
#include "main.h"
void printFunc(char *string){
printf("%s", string);
return;
}
You can compile using gcc on a linux machine as follows:
gcc -g -Wall -c file1.c //compile but do not link file
gcc -g -Wall -c file2.c //same
gcc file1.o file2.o -o main //executable "main"
or
gcc -g -Wall file1.c file2.c -o main
But I am concerned with how the header file gets included. I came across this when I was working on creating a "makefile" when I noticed that some tutorials will do something like this:
main : main.o printFunc.o
gcc -o main main.o printFunc.o
main.o : main.c
gcc -g -Wall -c -o main.o main.c
printFunc.o : printFunc.c
gcc -g -Wall -c -o printFunc.o printFunc.c
and others will include the header file as a dependent with:
main : main.o printFunc.o //main.h EDIT
//commands
main.o : printFunc.o main.h
//commands
Finally:
So, is it necessary to include the header file as a dependent to the executable? When does the include file get placed within the sources?
And also one could use this command:
executableName : dependencies.o //and a header file?
gcc -g -Wall -o executableSource.c
Which could be done with the line:
gcc -g -Wall -o executableName executableSource.c
Will the second command be run but the first is shorthand notation?
And finally, I thought the "-o" command was "send output to", if you will. If that way, it seems intuitive to run the command like:
gcc compileThisFile andSendOutputTo thisExecutableFile
gcc someSource.c -o executableFile
But with the notation listed above its more like:
gcc sendOutputTo thisExecutableFile fromThisSource
Is that correct?
main : main.o printFun.o main.h is definitely wrong. That's saying that the header is a prerequisite for linking. A header is a prerequisite for compilation.
Assuming what you really meant was to specify the header as a compilation dependency (e.g. printFunc.o : printFunc.c printFunc.h), this means that if the header changes, the object file will be automatically regenerated. If you don't, then it won't.
A dependency in Makefile is saying that whenever any of the listed files change, run the command again. It does not mean that the listed file will be included into the compilation or linking. You still need the regular #include "main.h" in your sources.
Thus, this works too:
printFunc.o : printFunc.c someReadmeFile.txt
gcc -g -Wall -c -o printFunc.o printFunc.c
Whenever printFunc.c or someReadmeFile.txt is updated, gcc -g -Wall .... will be executed again.
I hope it's clearer now.

When running a compiled GCC file in the terminal, nothing happens

I have Ubuntu 64 bit installed, and when I compile C files using the flags:
gcc -g -m32 -ansi -Wall -c -o *.o *.c
it compiles the files, but when I try to run them in the terminal, nothing happens.
So I decided to try to compile and run just one simple file without a makefile, with the following code:
#include <stdio.h>
int main()
{
printf("Hello World");
return 0;
}
The compilation succeeds but when I try to run the file I get nothing...
Note: I already tried to install lib32gcc1, libc6-i386, and g++-multilib.
How can I fix this problem?
Replace -o *.o by -o programname. The -o parameter receives the executable name of the program you're generating. And here is gcc manual:
http://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/Overall-Options.html#Overall-Options
For a simple test, leave every option out:
> cat test.c
#include <stdio.h>
int main()
{
printf("Hello World\n");
return 0;
}
> gcc test.c
> ./a.out
Hello World
and see if that works.
Let us assume you (already) have two object files a.o and b.o, their corresponding source file a.c and b.c and some common header ch.h; then your (incorrect) command line
gcc -g -m32 -ansi -Wall -c -o *.o *
might be expanded as:
gcc -g -m32 -ansi -Wall -c -o a.o b.o a.c b.c ch.h a.o b.o
(actually, that would be even worse, e.g. if you have some Makefile or some backup files from your editors like a.c~, as remarked by William Pursell)
which would compile but not link, the files b.o a.c b.c ch.h a.o b.o which does not means much.
You should understand that the shell is expanding first the arguments before executing any gcc program (in a new process). To understand what is expanded, consider replacing gcc by echo (or by gcc -v which would show what is really happening)
Then, you should read the GCC documentation about invoking GCC
Actually, you need to spend several hours in reading, e.g. Advanced Bash Scripting Guide (which does have some mistakes perhaps) and Advanced Linux Programming. Several wikipedia pages could also be useful to read.

Problems when linking shared library

Below are the steps of how I generate the executable file using shared library.
I have three files:
File libhello.c
/* hello.c - demonstrate library use. */
#include <stdio.h>
void hello(void)
{
printf("Hello, library world./n");
}
File libhello.h
/* hello.h - demonstrate library use. */
void hello(void);
File main.c
/* main.c -- demonstrate direct use of the "hello" routine */
#include "hello.h"
int main(void)
{
hello();
return 0;
}
I use the commands below to generate the shared library.
gcc -g -Wall -fPIC -c hello.c -o hello.o
gcc -shared -W,soname,-libhello.so.0 -o libhello.so.0.0.0 hello.o
Finally, I add the library path to the LD_LIBRARY_PATH variable and try to create the executable file using the shared library.
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
ln -s libhello.so.0.0.0 libhello.so.0
gcc -g -Wall -c main.c -o main.o -I.
gcc -o main main.o -lhello -L.
However, at the last step, there is one error: can't find -lhello. So, where am I wrong?
Thanks.
gcc looks for libhello.so when linking a new program. libhello.so.0 is used when the dynamic dependencies of an already linked program are searched.
In other terms: gcc -o main main.o -lhello -L. looks for libhello.so, and ./main looks for libhello.so.0. This allows to have multiple versions of a library available for legacy programs while precisely identifying the library that matches the installed headers.
A symlink libhello.so -> libhello.so.0.0.0 should do the trick.

gcc won't include libcurl on commandline for OS X

I'm trying to compile a C project I've been working on on a remote server that runs OS X. The project depends, in part, on libcurl. I only have access to the machine through my administrator account remotely.
When I attempt to make the project I keep getting errors relating to libcurl functions and constants not being defined. I conclude that libcurl is not being properly included by the compiler.
I'm using fink to install opensource software for all the dependencies ( postgres, curl, a few others ) and all the dependencies appear to work except curl.
My compiler command looks like:
gcc -ggdb -ansi -Wall -D_GNU_SOURCE -L `/sw/bin/pg_config --libdir` `/sw/bin/curl-config --cflags` -I `/sw/bin/pg_config --includedir` -lpq -lcurl -lpthread -lm `/sw/bin/curl-config --libs` -c Client.c
If I make a test file like so:
/sw/bin/curl http://www.google.com/ --libcurl test.c
And then attempt to compile it with:
gcc test.c `/sw/bin/curl-config --cflags` `/sw/bin/curl-config --libs` -o test.o
It also fails. Can anyone help me shed some light on this problem?
One compilation line is:
gcc -ggdb -ansi -Wall -D_GNU_SOURCE -L `/sw/bin/pg_config --libdir` \
`/sw/bin/curl-config --cflags` -I `/sw/bin/pg_config --includedir` \
-lpq -lcurl -lpthread -lm `/sw/bin/curl-config --libs` -c Client.c
This will take Client.c and generate Client.o, an object file. It doesn't need the library information; there is no linking taking place because of the -c option.
The other compilation line is:
gcc test.c `/sw/bin/curl-config --cflags` `/sw/bin/curl-config --libs` -o test.o
It is aconventional to end the names of executables with '.o'; it leads to confusion. However, if test.c only references functions from the standard libraries and libcurl, it should 'work'.
On my Mac, there is a copy of curl-config in /usr/bin.
Try this test program:
$ cat curltest.c
#include <stdio.h>
#include <curl/curl.h>
int main(void)
{
if (curl_global_init(0) == CURLE_OK)
{
printf("CURL version %s\n", curl_version());
curl_global_cleanup();
}
else
fprintf(stderr, "Failed to initialize CURL\n");
return 0;
}
$ cc -o curltest $(curl-config --cflags) curltest.c $(curl-config --libs)
$ file curltest
curltest: Mach-O 64-bit executable x86_64
$ otool -L curltest
curltest:
/usr/lib/libcurl.4.dylib (compatibility version 6.0.0, current version 6.1.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 125.2.11)
$ curltest
CURL version libcurl/7.19.7 OpenSSL/0.9.8r zlib/1.2.3
$
This is on MacOS X 10.6.8.

Resources