Skip to content

Instantly share code, notes, and snippets.

@tailriver
Created November 18, 2015 04:21
Show Gist options
  • Save tailriver/30bf0c943325330b7b6a to your computer and use it in GitHub Desktop.
Save tailriver/30bf0c943325330b7b6a to your computer and use it in GitHub Desktop.
A sample of using dlopen library.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
int main(int argc, char** argv)
{
void *handle;
void (*func_print_name)(const char*);
if (argc != 2) {
fprintf(stderr, "Usage: %s animal_type\n", argv[0]);
return EXIT_FAILURE;
}
if (strcmp(argv[1], "dog") == 0) {
handle = dlopen("./libdog.so", RTLD_LAZY);
} else if (strcmp(argv[1], "cat") == 0) {
handle = dlopen("./libcat.so", RTLD_LAZY);
} else {
fprintf(stderr, "Error: unknown animal type: %s\n", argv[1]);
return EXIT_FAILURE;
}
if (!handle) {
/* fail to load the library */
fprintf(stderr, "Error: %s\n", dlerror());
return EXIT_FAILURE;
}
*(void**)(&func_print_name) = dlsym(handle, "print_name");
if (!func_print_name) {
/* no such symbol */
fprintf(stderr, "Error: %s\n", dlerror());
dlclose(handle);
return EXIT_FAILURE;
}
func_print_name(argv[1]);
dlclose(handle);
return EXIT_SUCCESS;
}
#pragma once
void print_name(const char* type);
#include "animal.h"
#include <stdio.h>
void print_name(const char* type)
{
printf("Tama is a %s.\n", type);
}
#include "animal.h"
#include <stdio.h>
void print_name(const char* type)
{
printf("Pochi is a %s.\n", type);
}
app = dlopen_sample
lib = libcat.so libdog.so
CFLAGS = -Wall -ansi -pedantic
LDFLAGS = -ldl
all: $(app) $(lib)
lib%.so: %.c
$(CC) -shared -fPIC $(CFLAGS) -o $@ $<
clean:
$(RM) $(app) $(lib)
run: all
./$(app) cat
./$(app) dog
-./$(app) bear
$(lib): animal.h
@cirosantilli
Copy link

@etale-cohomology
Copy link

@cirosantili I like yours betters (not that this one is bad!)

@harieamjari
Copy link

Awesome! BTW, Tama and Pochi reminds me of an anime. Something like Death march kara hajimaru.

@apurba-101010
Copy link

I am not able to compile the code. I am getting error. Please help.
[s]$ gcc dlopen_sample.c -o a
/tmp/cc3t29je.o: In function main': dlopen_sample.c:(.text+0x67): undefined reference to dlopen'
dlopen_sample.c:(.text+0x98): undefined reference to dlopen' dlopen_sample.c:(.text+0xd8): undefined reference to dlerror'
dlopen_sample.c:(.text+0x110): undefined reference to dlsym' dlopen_sample.c:(.text+0x121): undefined reference to dlerror'
dlopen_sample.c:(.text+0x149): undefined reference to dlclose' dlopen_sample.c:(.text+0x170): undefined reference to dlclose'
collect2: error: ld returned 1 exit status
[s]$

@tailriver
Copy link
Author

@apurba-101010 You need to link libdl.so, so add -ldl (see LDFLAGS in my Makefile).

@zhouronghua
Copy link

default LDFLAGS with wrong position, add code in Makefile like this:
dlopen_sample: dlopen_sample.c
$(CC) $(CFLAGS) dlopen_sample.c $(LDFLAGS) -o dlopen_sample

@TKNgu
Copy link

TKNgu commented May 10, 2022

Why need (void*)(&func_print_name) = dlsym(handle, "print_name");
When can use func_print_name = (void()(const char))(dlsym(handle, "print_name")); ?

Sorry for my English.

@harieamjari
Copy link

Why need (void*)(&func_print_name) = dlsym(handle, "print_name"); When can use func_print_name = (void()(const char))(dlsym(handle, "print_name")); ?

Sorry for my English.

@TKNgu From the man https://man7.org/linux/man-pages/man3/dlopen.3.html emphasis mine:

           cosine = (double (*)(double)) dlsym(handle, "cos");

           /* According to the ISO C standard, casting between function
              pointers and 'void *', as done above, produces undefined results.
              POSIX.1-2001 and POSIX.1-2008 accepted this state of affairs and
              proposed the following workaround:

                  *(void **) (&cosine) = dlsym(handle, "cos");

              This (clumsy) cast conforms with the ISO C standard and will
              avoid any compiler warnings.

              The 2013 Technical Corrigendum 1 to POSIX.1-2008 improved matters
              by requiring that conforming implementations support casting
              'void *' to a function pointer.  Nevertheless, some compilers
              (e.g., gcc with the '-pedantic' option) may complain about the
              cast used in this program. */

Now you know a thing or two.

@mboyar
Copy link

mboyar commented Aug 9, 2023

Thx for your example but just there is an addition; you can add the lines below to your Makefile to resolve the "undefined reference" error:

$(app): 
	$(CC) $(app).c -fPIC $(CFLAGS) $(LDFLAGS) -o $@ $<

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment