Create a valid shared library in C - c

I'm doing some test to learn how to create shared library.
The template for shared libraries in Code::Blocks is this
library.c
// The functions contained in this file are pretty dummy
// and are included only as a placeholder. Nevertheless,
// they *will* get included in the shared library if you
// don't remove them :)
//
// Obviously, you 'll have to write yourself the super-duper
// functions to include in the resulting library...
// Also, it's not necessary to write every function in this file.
// Feel free to add more files in this project. They will be
// included in the resulting library.
// A function adding two integers and returning the result
int SampleAddInt(int i1, int i2)
{
return i1 + i2;
}
// A function doing nothing ;)
void SampleFunction1()
{
// insert code here
}
// A function always returning zero
int SampleFunction2()
{
// insert code here
return 0;
}
I tried to compile it, and it compiled without any error or warning. But when i tried to use it with the ctyped.cdll.LoadLibrary("library path.dll") in python 3(that actually should work like the C function), it said that it wasn't a valid win32 application. Both python and code::blocks are 32 bit (code:blocks compile with gcc, and i tryed to use an installed version of mingw on my system, but it gives some error about a missing library) while i'm working on win 7 64bit
Do you know what the problem can be, or if i'm doing something wrong?
EDIT1:
i'm on windows 7 64bit, in the specs file of the compiler is wrote: "Thread model: win32, gcc version 3.4.5 (mingw-vista special r3)"
and i used as command
gcc.exe -shared -o library.dll library.c
in python i used
from ctypes import *
lib = cdll.LoadLibrary("C:\\Users\\Francesco\\Desktop\\C programmi\\Python\\Ctypes DLL\\library.dll")
and the error was
WindowsError: [Error 193] %1 is not a valid Win32 application
i installed both python3.1 and mingw from the binary package and not compiling them on my system
EDIT2:
After reading Marc answer.
main.h
#ifndef __MAIN_H__
#define __MAIN_H__
#include <windows.h>
#ifdef BUILD_DLL
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif
#ifdef __cplusplus
extern "C"
{
#endif
DLL_EXPORT int MySimpleSum(int A, int B);
#ifdef __cplusplus
}
#endif
#endif // __MAIN_H__
main.c
#include "main.h"
// a sample exported function
DLL_EXPORT int MySimpleSum(int A, int B)
{
return A+B;
}
compiling options
gcc -c _DBUILD_DLL main.c
gcc -shared -o library.dll main.o -Wl,--out-implib,liblibrary.a
with gcc 4.5.2
still get the same error..

I believe in the windows environment you need to use the __declspec annotation. How to create a shared library and the use of __declspec is described here: DLL Creation in MingW.

Related

multiple definitions of main --> how to add only some functions from another header?

In C I get the linker error multiple definition of `main'. Yes, that is true but:
Why does the linker try to include the second (ext.c) main function although I have just included the header ext.h? I'd expect, the linker only links the functions whose prototypes have been found or which are needed by the initial main?
How can I solve this that
a) test compiles and gets linked without issues (just use the func() from ext.c) and
b) also ext.c can be compiled and linked as separate application?
The (example) code:
//file: test.c
#include "/home/stefanm/test/test.h"
void main (int argc, char * argv[])
{
uint8_t var = 123;
printf ("main(): var= %i\n", var);
func (var);
}
//file: test.h
#ifndef TEST_H
#define TEST_H
#include <the rest>
#include "/home/stefanm/test/ext.h"
#endif
...and the external module:
//file: ext.c
#include "/home/stefanm/test/ext.h"
uint8_t func (uint8_t i){
printf ("func(): Variable i is %i", i);
return 0;
}
void main () {
printf ("ext main func");
}
//file: ext.h
#ifndef EXT_H
#define EXT_H
#include "all needed headers"
uint8_t func (uint8_t);
#endif
I call the compiler with gcc test.c ext.c -o test
Your external module should not have main() because it's a module and not an application. You should just move main() from your module to a separate file:
//file: app.c
#include "/home/stefanm/test/ext.h" // <-- BTW, using absolute paths is not a good idea
void main () {
//use function from ext here
printf ("app main func");
}
And then compile your application like this:
gcc app.c ext.c
and your test like this:
gcc test.c ext.c
In C, you can only have one definition of a function in all of the files you link into your executable. There's no good way to tell the compiler "I want to use this main() and not all the others". (There's a bad way, using macros, but it would be messy).
If you want to use a function with two different main() functions, put it in a separate file.
I suppose your compile/link call goes like
gcc test.c ext.c
In this case, test.c and ext.c (resp., to be exact, the .o files created out of them) are peers, i. e. on the same level. How should the linker know which version of the symbol main to take and which to discard? The linker doesn't know about the include files used.
In the case of a main function, the correct way to go is to have exactly one of them in your project.
For any other function where you have this requirement, there are several ways to go:
Either, you could declare one of them as "weak". It will be discarded when there is a "strong one".
Or you put your function into a library, e. g. libext.a. If you link that with -ext, only the object files which define symbols which are undeined are taken out of it. But then again, name clashes can occur if another name defined by that object file is defined already. So it is the best to only define as few symbols per object file as possible.

How to conditional compile main() in C?

I'm working on a small open source project in C where I'm trying to use a test framework with C (the framework is min_unit).
I have a foo.h file with prototypes, and foo.c, with the implementation.
In my test file, tests.c, I have
#include "../test_framework/min_unit.h"
#include "foo.c"
... test cases ...
the problem is, because I have a main() function in foo.c (which I need to compile it), I can't compile tests.c because I get an error that states
note: previous definition of ‘main’ was here
int main() {
My question is, is there a way to make it so that the main() function in foo.c is conditional, so that it does not compile when I'm running tests.c? It's just annoying to have to remove and add main over and over.
The easiest way to use conditional compilation is to use #ifdef statements. E.g., in foo.c you have:
#ifdef NOT_TESTING //if a macro NOT_TESTING was defined
int main() {
//main function here
}
#endif
While in test.c, you put:
#ifndef NOT_TESTING //if NOT_TESTING was NOT defined
int main() {
//main function here
}
#endif
When you want to compile the main function in foo.c, you simply add the option -DNOT_TESTING to your compile command. If you want to compile the main function in test.c, don't add that option.
Haven't you try the use of pre-processor compiler conditions? May be you've tried but it doesn't work, hum?
Anyway, you probably should:
1- Define a token at top of "tests.c" class file like:
#defined foo_MIN_UNIT_TEST
2- Surround your "main() { ... } " method in "foo.c" class file with #ifndef / #endif like:
#ifndef foo_MIN_UNIT_TEST //consider using #ifndef not #ifdef!!!
int main()
{ ... }
#endif
3- This way, when you compile your unit test files, the main() method of foo.c will not be included in compile time and the only main() method of tests will be available to compiler.
For further reading: http://www.cprogramming.com/
Regards.

How to use external macro in function body?

I'm writing a function that should have two versions: a debug version and non-debug version. Which one of the two functions is used should be decided by the caller.
I want something like this:
caller.c
// comment out the following line when not necessary anymore
#define MY_FUNC_DEBUG
#include "my_func.h"
// some code that calls my_func()
my_func.h
void my_func(void);
my_func.c
void my_func()
{
// lots of code
#ifdef MY_FUNC_DEBUG
// debug code
#endif
// more code
}
This obviously won't work, because my_func.c is compiled separately from caller.c, therefore it can't know what macros it defined.
How can I make this work easily? I wouldn't want to write the two versions of my_func separately, because they share most of their code.
Assuming that you are using gcc, this problem can be easily solved by defining the macro at compile time via the -D option in both files.
In your example you could compile both files using -D MY_FUNC_DEBUG when you want the debug code to be activated and nothing otherwise. There is not need for defining MY_FUNC_DEBUG in caller.c.
Make the debugging code in my_func() switchable at run-time.
my_func.h
#ifndef MY_FUNC_H_INCLUDED
#define MY_FUNC_H_INCLUDED
extern int my_func_debug(int level);
extern void my_func(void);
#endif
my_func.c
#include "my_func.h"
static int debug = 0;
int my_func_debug(int level)
{
int rv = debug;
debug = level;
return rv;
}
void my_func(void)
{
...
#ifdef MY_FUNC_DEBUG
if (debug)
...debug...
#endif
...
}
caller.c
void consumer(void)
{
int old = my_func_debug(9);
my_func();
my_func_debug(old);
}
Discussion
The outline code means that you can have one copy of the source for my_func.c, but it can be compiled with debug included, or with it excluded. The consumer code (caller.c) can request the level of debugging it wants, but whether that does anything useful depends on whether the copy of my_func.o (my_func.obj on Windows) was compiled with debug included. You get one source file; you get to choose which variant of the object file is included in the program with caller.o. And at runtime you can request debugging.
Note that my_func_debug() is unconditionally defined; it just doesn't do anything very useful if the my_func.c code is not compiled with -DMY_FUNC_DEBUG.

File Global Define

I am making a small, library, and I want to give the user the option to disable the parts they do not require.
lib.h
#ifndef ONLY_BASICS
void complexFunction(void);
#endif
lib.c
#ifndef ONLY_BASICS
void complexFunction(void) {
printf("damn, this is complex alright!\n");
}
#endif
main.c
#define ONLY_BASICS
#include "lib.h"
I have seen this being done in other libraries, what am I missing?
You can make users control the build using the prepossessing macros from the compiler without editing the code. If you use GCC use the switch -D followed by the macro name. On Microsoft compiler use the /D option.
For example using GCC, I have:
#include <stdio.h>
int main(int argc, char **argv) {
#ifdef SAYHI
#ifdef CAPITAL
printf("HI\n");
#else
printf("hi\n");
#endif
#elif SAYHELLO
#ifdef CAPITAL
printf("HELLO\n");
#else
printf("hello\n");
#endif
#else
#ifdef CAPITAL
printf("SAY SOMETHING\n");
#else
printf("say something\n");
#endif
#endif
return 0;
}
The user can enable and disable what he want via -DMACRO without editing the code, example:
$ gcc main.c
$ a.exe
say something
$
$ gcc main.c -DCAPITAL
$ a.exe
SAY SOMETHING
$
$ gcc main.c -DSAYHI -DCAPITAL
$ a.exe
HI
$
$ gcc main.c -DSAYHELLO
$ a.exe
hello
$
It seems you're misunderstanding what a library is and what it's used for. Most (all?) linkers already do what you're trying by not including unreferenced symbols from libraries - it's why with gcc, for instance, you need to put the libraries at the end of the command line after the list of source files that contain references to library functions.
What you're doing seems to be confusing this behaviour with compile-time options for the library itself. In that case, you can use the #ifndef blocks as you have in lib.h and lib.c, but you shouldn't need to do anything in main.c - the library will already have been built without complexFunction. You may want to have your library build process generate a header that describes which functionality is available.

Including a typedef in two header files

I have this in ball.h:
#ifndef BALL_H_
#define BALL_H_
...
typedef void *PBALL ;
...
#endif
in paddle.h I have:
#ifndef PADDLE_H_
#define PADDLE_H_
...
int contact_made(struct pppaddle*, PBALL);
...
#endif
I get an error in paddle.h because it doesn't know about PBALL. So if I add:
#ifndef BALL_H_
#include "ball.h"
#endif
to paddle.h (with or without the if statement) it works in my Cygwin environment. But in Linux when I go to compile I get: "multiple definition of `newPBALL'" error on the source file that uses PBALL and also on the functions defined in ball.h. How can I get paddle.h to understand PBALL without running into these problems in Linux?
My ball.c file:
struct newball {
int x_pos, x_dir, y_pos, y_dir, y_delay, y_count, x_delay, x_count;
char symbol;
};
typedef struct newball *ball_struct_ptr;
struct newball the_ball;
#include "ball.h"
PBALL newPBALL() {
the_ball.y_pos = Y_INIT;
the_ball.x_pos = X_INIT;
the_ball.y_count = the_ball.y_delay = Y_DELAY;
the_ball.x_count = the_ball.x_delay = X_DELAY;
the_ball.y_dir = 1;
the_ball.x_dir = 1;
the_ball.symbol = DFL_SYMBOL; //Set the symbol of the ball
PBALL ptr = &the_ball;
return ptr;
}
Well instead of trying to import one header file into another (which worked in Cygwin but not Linux) or not importing the header into the other header (which worked for Linux but not Cygwin) I did this in both header files:
#ifndef TYPEDEF_PBALL_DECLARED_
#define TYPEDEF_PBALL_DECLARED_
typedef void *PBALL ;
#endif
Now it's working in both environments. I'll leave this open for a little while in case there is a better solution than having to declare typedef twice in two header files.
I don't know what precisely is the problem, but I might be able to tell you how to figure it out.
Build your program as usual. Capture the command line of the failing compilation step. This might be something like:
gcc -c -o foo/bar.o baz.c
So baz.c presumably #includes the "bad" header files. And you get the compilation error. Now, track it down by just preprocessing your sources:
gcc -E -o foo/bar.c baz.c
-E being the option to stop after preprocessing, before actual compilation. Now try to compile the preprocessed file:
gcc -c -o foo/bar.o bar.c
You should find a similar error as before. Now look at the preprocessed source in bar.c from step 2 and you might easier find the cause. Start with just searching for the identifier that the compiler is complaining about--is it in fact declared multiple times? If so, why? Could it be in another header? Or perhaps there is a #define somewhere that is messing with your names?

Resources