I am not sure about all the details and possible gotchas, I only read about it what I needed to get it to work for my case. I think the first thing you should check is that the wrapper library is actually dynamically linked to the wrapped library. (I write linux commands because that is the only platform I currently use)
In my case I am wrapping the freetype library with a small wrapper that makes it easier to extract gylphs (with an api that is easier for me to work with).
So when you use a command like ldd libyourwrapper.so
(also try ldd -v ...
for more output) you should get a list of dynamic dependencies that includes your wrapped library and also its dependents. If that list does not show those libraries then maybe you are missing some (library) flags while you are building your wrapper library.
I can't give you a general guide towards those flags (I only know what I use, the rest is vague; also other people may know better ways to do things, however I hope it is useful anyway), here is what I use to build my wrapper library:
gcc $(pkg-config --cflags --libs freetype2) -Lfreetype -Wall -fPIC -c glyphloader.c
gcc -shared -Wl,-soname,libglyphloader.so -lfreetype -o libglyphloader.so glyphloader.o
The first line creates the object file, the second creates the shared library out of it.
In my case the output from ldd libglyphloader.so
is:
linux-vdso.so.1 (0x00007ffe339eb000)
libfreetype.so.6 => /usr/lib/libfreetype.so.6 (0x00007f6f7270d000)
libc.so.6 => /usr/lib/libc.so.6 (0x00007f6f72500000)
libz.so.1 => /usr/lib/libz.so.1 (0x00007f6f724e6000)
libbz2.so.1.0 => /usr/lib/libbz2.so.1.0 (0x00007f6f724d3000)
libpng16.so.16 => /usr/lib/libpng16.so.16 (0x00007f6f7249c000)
libharfbuzz.so.0 => /usr/lib/libharfbuzz.so.0 (0x00007f6f723ac000)
libbrotlidec.so.1 => /usr/lib/libbrotlidec.so.1 (0x00007f6f7239c000)
/usr/lib64/ld-linux-x86-64.so.2 (0x00007f6f72823000)
libm.so.6 => /usr/lib/libm.so.6 (0x00007f6f722b5000)
libgraphite2.so.3 => /usr/lib/libgraphite2.so.3 (0x00007f6f72290000)
libglib-2.0.so.0 => /usr/lib/libglib-2.0.so.0 (0x00007f6f72152000)
libbrotlicommon.so.1 => /usr/lib/libbrotlicommon.so.1 (0x00007f6f7212f000)
libpcre.so.1 => /usr/lib/libpcre.so.1 (0x00007f6f720b6000)
libpthread.so.0 => /usr/lib/libpthread.so.0 (0x00007f6f720b1000)
When I first tried getting this to work I think I didn't have the -lfreetype
in the second line and the ldd output was:
linux-vdso.so.1 (0x00007ffea517d000)
libc.so.6 => /usr/lib/libc.so.6 (0x00007fe84817c000)
/usr/lib64/ld-linux-x86-64.so.2 (0x00007fe8483d0000)
With that missing loading the wrapper library from racket fails with an error message (... inserted by me):
ffi-lib: could not load foreign library
path: /home/sze/development/.../libglyphloader.so
system error: /home/sze/development/.../libglyphloader.so: undefined symbol: FT_Done_Face
context...:
/usr/share/racket/collects/ffi/unsafe.rkt:131:0: get-ffi-lib
body of "/home/sze/development/.../glyphloader.rkt"
Hopefully it is a simple error like this and this information helps.
If it is something more complicated you should look into using other tools that can provide insights, like @LiberalArtist suggested, I think there are a lot of tools, but I only know of a few.
In cases like this everything that can give us hints towards what actually is happening is helpful.
Do you / the student get any kind of error when trying to load the library?
I think it is a standard feature of dynamic libraries to depend on other dynamic libraries, but as far as I know every compiler has different ways of being told to add that link information for those other libraries into the created library file, so they end up as dependencies in the shared libraries. Basically with c and c++ you have to tell the compiler what it should do, because there is no proper module system that keeps track of the dependencies. I imagine that there are other languages / build-systems that automatically manage this.
Another thing is, that with dynamic libraries the actual dynamic linking of the other dependencies only happens when the library is loaded, so that is why you can build a library, that looks as if it compiled correctly, but actually has missing dependencies that you only discover when you try to load it.
If you don't get any error (which seems surprising to me) it may make sense to use a debugger (I mean something like gdb or lldb here, not the racket one, but this mostly if racket doesn't give any insight/error message) to start the racket program that tries to load the library and see whether that can give any insight into what is happening and where the program fails.
But take all of this with a grain of salt, the last time I read something more in depth about this stuff was probably something like 15 years ago. So there may be a lot I have forgotten, or different new tools to handle things like this.