How to automatically run user-code upon loading Fortran module - c

In C using GCC, one can use the following function to have some code called upon loading a shared library:
static void __attribute__((constructor)) _my_initializer(void)
{
...
}
After some search on the web, I could not find the equivalent in Fortran using GCC (i.e. gfortran). For sure that this feature must exist in gfortran since it comes from GCC (thus it should be available in all languages supported by GCC). Any pointers?

"For sure that this feature must exist in gfortran since it comes from GCC" That is clearly false. It simply does not have to exist. gfortran does support the !GCC$ ATTRIBUTES directive, but the number of attributes supported is limited.
You can write your constructor in C and let it be part of the same library and call any Fortran code you want.
Example:
library.f90:
subroutine sub() bind(C)
write(*,*) "Hello!"
end subroutine
init_library.c:
void sub(void);
static void __attribute__((constructor)) _init(void)
{
sub();
}
load_library.c:
#include <stdio.h>
#include <unistd.h>
#include <dlfcn.h>
typedef void (*foo)(void);
int main(int argc, char* argv[])
{
void *lib = dlopen("library.so", RTLD_NOW);
if(lib == NULL)
return printf("ERROR: Cannot load library\n");
dlclose(lib);
}
compile and run:
> gfortran -c -fPIC init_library.c
> gfortran -c -fPIC library.f90
> gfortran -shared library.o init_library.o -o library.so
> gfortran load_library.c -ldl
> ./a.out
Hello!

Related

Linking to an executable on OSX

On Windows it is possible to dynamically link to an executable with exported symbols. For example following code:
// main.c
void __declspec(dllexport) interface_function() {}
int main() {}
// ext.c
void interface_function();
void extension_function() {
interface_function();
}
With
cl.exe main.c
cl.exe ext.c /LD /link main.lib
would produce an executable main.exe, a static library main.lib for implicit linking, and a dynamic library ext.dll.
Similar behavior can be achieved in OSX with shared libraries:
// main.c
void interface_function() {}
int main() {}
// ext.c
void interface_function();
void extension_function() {
interface_function();
}
With
gcc main.c -o main
gcc ext.c -bundle -bundle_loader main -o ext.bundle
it is virtually equivalent to the Windows setup.
But for dynamiclib:
> gcc ext.c -dynamiclib -o ext.dylib
and shared:
> gcc ext.c -shared -o ext.so
I cannot get them to work because of undefined symbols on one hand and unable to load an executable with -l flag on the other.
I can let them resolve undefined symbols in runtime with -undefined dynamic_lookup. But this is not a sustainable way because all the link errors are now happening in run-time instead.
Is there a way to provide the list of symbols to dynamically load from an executable when linking as -shared and -dynamiclib?
Yes this is possible, but then you'll want to create a bundle rather than a shared library (see this answer for more detail).
If you have a main application like so:
#include <stdio.h>
#include <dlfcn.h>
int func(void)
{
return 42;
}
int main(void)
{
void *dl = dlopen("plugin.so", RTLD_LOCAL);
if(!dl) return -1;
int (*derp)(void) = dlsym(dl, "derp");
if(!derp) return -1;
printf("derp(): %i\n", derp());
return 0;
}
clang -o main main.c -Wall -Wl,-export_dynamic
Then you can compile bundles against it like so:
int func(void);
int derp(void)
{
return -func();
}
clang -o plugin.so plugin.c -Wall -bundle -bundle_loader ./main

Only link certain symbols from a library

I am developing an embedded system with GCC, and would like to only use a few symbols from libc. For instance, I would like to use the basic memcpy, memmove, memset, strlen, strcpy, etc. However, I would like to provide my own (smaller) printf function, so I do not want libc to privide printf. I don't want dynamic allocation in this platform, so I do not want malloc to resolve at all.
Is there a way to tell GCC "only provide these symbols" from libc?
edit: To be clear, I am asking if there is a way I can only provide a few specific symbols from a library, not just override a library function with my own implementation. If the code uses a symbol that is in the library but not specified, the linker should fail with "unresolved symbol". If another question explains how to do this, I haven't yet seen it.
This should happen "automatically" as long as your libc and linker setup supports it. You haven't told what your platform is, so here is one where it does work.
So, let's create a silly example using snprintf.
/*
* main.c
*/
#include <stdio.h>
int main(int argc, char **argv) {
char l[100];
snprintf(l, 100, "%s %d\n", argv[0], argc);
return 0;
}
try to compile and link it
$ CC=/opt/gcc-arm-none-eabi-4_7-2013q3/bin/arm-none-eabi-gcc
$ CFLAGS="-mcpu=arm926ej-s -Wall -Wextra -O6"
$ LDFLAGS="-nostartfiles -L. -Wl,--gc-sections,-emain"
$ $CC $CFLAGS -c main.c -o main.o
$ $CC $LDFLAGS main.o -o example
/opt/gcc-arm-none-eabi-4_7-2013q3/bin/../lib/gcc/arm-none-eabi/4.7.4/../../../../arm-none-eabi/lib/libc.a(lib_a-sbrkr.o): In function `_sbrk_r':
sbrkr.c:(.text._sbrk_r+0x18): undefined reference to `_sbrk'
collect2: error: ld returned 1 exit status
It needs _sbrk because newlib *printf functions use malloc which needs a way to allocate system memory. Let's provide it a dummy one.
/*
* sbrk.c
*/
#include <stdint.h>
#include <unistd.h>
void *_sbrk(intptr_t increment) {
return 0;
}
and compile it
$ $CC $CFLAGS -c sbrk.c -o sbrk.o
$ $CC $LDFLAGS -Wl,-Map,"sbrk.map" main.o sbrk.o -o with-sbrk
$ /opt/gcc-arm-none-eabi-4_7-2013q3/bin/arm-none-eabi-size with-sbrk
text data bss dec hex filename
28956 2164 56 31176 79c8 with-sbrk
Well, that's the reason you'd like to get rid of printf and friends, isn't it? Now, replace snprintf with our function
/*
* replace.c
*/
#include <stdio.h>
#include <string.h>
int snprintf(char *str, size_t size, const char *format, ...) {
return strlen(format);
}
then compile
$ $CC $CFLAGS -c replace.c -o replace.o
$ $CC $LDFLAGS -Wl,-Map,"replace.map" main.o replace.o -o with-replace
$ /opt/gcc-arm-none-eabi-4_7-2013q3/bin/arm-none-eabi-size with-sbrk
text data bss dec hex filename
180 0 0 180 b4 with-replace
Note that we did not use the _sbrk stub at all. As long as you don't provide _sbrk, you can be sure that malloc is not (can't be) linked and used.
The simplest solution is probably to use a wrapper which defines the symbols and resolves them at runtime using dlfcn:
#include <dlfcn.h>
void* (*memcpy)(void *dest, const void *src, size_t n);
char* (*strncpy)(char *dest, const char *src, size_t n);
...
void init_symbols (void) {
void *handle = dlopen("/lib/libc.so.6", RTLD_LAZY);
memcpy = dlsym(handle, "memcpy");
strncpy = dlsym(handle, "strncpy");
...
}
and link your binary with -nostdlib. This gives you the best control on which symbols to use from which source.

Calling functions from a shared library

I'm trying to call a "core" function from a shared library's function but I get:
./a.out: symbol lookup error: ./libtest.so: undefined symbol: testf
The code I'm using is very basic because I'm just getting into writing shared libraries and it's just for testing purposes:
main.h
extern void testf();
main.c
#include <stdio.h>
#include <dlfcn.h>
extern void testf()
{
printf("bla bla\n");
}
int main () {
void *handle = NULL;
void (*testlib)(void) = NULL;
handle = dlopen("./libtest.so" ,RTLD_LAZY);
testlib = dlsym(handle, "testfunc");
if ( testlib == NULL )
{
printf("Error: %s \n", dlerror());
}
else
{
testlib();
}
}
libtest.c
#include <stdio.h>
#include "main.h"
void testfunc() {
printf("Test plugin\n");
testf();
}
And the commands I compile it with:
gcc -fPIC -g -c -Wall libtest.c
gcc -shared -Wl,-soname,libtest.so.1 -o libtest.so libtest.o -lc
gcc main.c -ldl
Is it possible to achieve this? Tried to find the answer, but don't really know how to form the question right so I can search better for it.
Thanks!
here you are trying to call a function of a executable from the library. I think you actually required reverse of this.
Sorry, managed to find the answer:
I was compiling the main program with wrong parameters, should use:
gcc main.c -ldl -rdynamic

How to access the global variable of executable in shared library (c - linux)

I want to access the global variable of executable in shared library? I have tried to compile using option -export-dynamic but no luck.
I have tried with extern key word. this also not working.
Any help or suggestion would be appreciable.
Environment c - Linux
executable:-
tst.c
int tstVar = 5;
void main(){
funInso();
printf("tstVar %d", tstVar);
}
lib:-
tstLib.c
extern int tstVar;
void funInso(){
tstVar = 50;
}
Since my code is very big, I just gave the sample which I have used in my program.
It should work. BTW, your tst.cis lacking a #include <stdio.h>. And its main should return an ìnt and end with e.g. return 0;.
With
/* file tst.c */
#include <stdio.h>
int tstVar = 5;
extern void funInso(void);
int main(){
funInso();
printf("tstVar %d\n", tstVar);
return 0;
}
and
/* file tstlib.c */
extern int tstVar;
void funInso(){
tstVar = 50;
}
I compiled with gcc -Wall -c tst.c the first file, I compiled with gcc -Wall -c tstlib.c the second file. I made it a library with
ar r libtst.a tstlib.o
ranlib libtst.a
Then I linked the first file to the library with gcc -Wall tst.o -L. -ltst -o tst
The common practice is to have with your library a header file tstlib.h which would contain e.g.
#ifndef TSTLIB_H_
#define TSTLIB_H_
/* a useful explanation about tstVar. */
extern int tstVar;
/* the role of funInso. */
extern void funInso(void);
#endif /*TSTLIB_H */
and have both tst.c and tstlib.c contain an #include "tstlib.h"
If the library is shared, you should
compile the library file in position independent code mode
gcc -Wall -fpic -c tstlib.c -o tstlib.pic.o
link the library with -shared
gcc -shared tstlib.pic.o -o libtst.so
Note that you can link a shared object with other libraries. You could have appended -lgdbm to that command, if your tstlib.c is e.g. calling gdbm_open hence including <gdbm.h>. This is one of the many features shared libraries give you that static libraries don't.
link the executable with -rdynamic
gcc -rdynamic tst.o -L. -ltst -o tst
Please take time to read the Program Library Howto
your tstVar variable could be defined in the lib. and you can share this variable via functions:
setFunction: to edit this variable
void setFunction (int v)
{
tstVar = v;
}
getFunction: to return the variable
int getFunction ()
{
return tstVar
}

What's wrong in creating/using a shared library with gcc here?

In libname.h:
int add_libname(int, int);
In libname.c:
#include "libname.h"
int add_libname(int a, int b)
{
return a+b;
}
I can build the shared library this way:
gcc -shared -fPIC libname.c -o libname.so
But I can't use it in another programe test.c:
#include <stdio.h>
#include "libname.h"
int main(int argc, char* argv[])
{
printf("%d\n", add_libname(1,5));
}
Reporting undefined reference to add_libname when I try to build it..
What's wrong here?
Because add_libname takes (int, int) you're giving it (1+5 = 6) or just (int)
I think you meant
add_libname(1, 5);
Also to compile it correctly you must use gcc like so
gcc -o myapp test.c -L. -lname
the lib part of libname is ignored as it is implicit
To create a shared library use these
gcc -fPIC -c libname.c
it gives warning: position independent code and libname.o file is generated.
and now type these command,
gcc -shared libname.so libname.o
libname.so ( the shared library is created with .so extension). To use the shared library
gcc -I/give the path of libname.h sourcefile.c /give the path of your .so file
example if your c file is file.c and the header file libname.h is in c:\folder1\project and your libname.so (shared library) is in c:\folder\project2
then
gcc -I/cygdrive/c/folder1/project file.c /cygdrive/c/folder/project/libname.so
this is the gcc command to be used while using the shared library.
Thank you.

Resources