Skip to content

Instantly share code, notes, and snippets.

@tailriver
Created November 18, 2015 04:21
Show Gist options
  • Select an option

  • Save tailriver/30bf0c943325330b7b6a to your computer and use it in GitHub Desktop.

Select an option

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
Copy Markdown

@etale-cohomology
Copy link
Copy Markdown

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

Copy link
Copy Markdown

ghost commented Jul 18, 2020

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

@apurba-101010
Copy link
Copy Markdown

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
Copy Markdown
Author

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

@zhouronghua
Copy link
Copy Markdown

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
Copy Markdown

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.

Copy link
Copy Markdown

ghost 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.

@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
Copy Markdown

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 $@ $<

@c-auger
Copy link
Copy Markdown

c-auger commented Aug 25, 2025

This code relies on unspecified behavior according to POSIX standard: at least one of RTLD_GLOBAL and RTLD_LOCAL should be specified in dlopen().

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