Been working on trying to get C Bindings for sunvox, and I’m looking for a little guidance on how to fix an issue.
I installed sunvox.so into /usr/lib, and also installed the header, sunvox.h, into /usr/include. I proved I can link it by compiling one of the sample programs included, I noticed it is both a C++ file and a C file, so I used gcc to force C compiliation using gcc -x c sunvox.c -o sunvox -lm -ldl -lsunvox . This works, and it plays the sounds and everything just fine.
I then ran the crystal_lib tool on the header to generate a binding, sunshine.cr. When trying to crystal run ./src/sunshine.cr I get this:
ian@gaming-computer:~/Documents/crystal/sunshine$ crystal run ./src/sunshine.cr
_main.o: In function `__crystal_main':
/home/ian/Documents/crystal/sunshine/src/sunshine.cr:146: undefined reference to `sv_load_dll'
collect2: error: ld returned 1 exit status
Error: execution of command failed with code: 1: `cc "${@}" -o '/home/ian/.cache/crystal/crystal-run-sunshine.tmp' -rdynamic -lsunvox -lpcre /usr/bin/../lib/crystal/lib/libgc.a -lpthread /usr/sha
re/crystal/src/ext/libcrystal.a -levent -lrt -ldl -L/usr/bin/../lib/crystal/lib -L/usr/lib -L/usr/local/lib`
Why doesn’t crystal see sunvox.so? What am I doing wrong?
I do not use this feature of crystal much so I imagine other people will be able to help more.
I noticed in your example you are using gcc. Have you tried compiling with llvm?
I don’t think that should make that big of a difference but it might.
Also, As of 0.28.0 there is an enviroment varible you can set called CRYSTAL_LIBRARY_PATH that you can use to point to the .so files. Crystal will still try to find .so files but will use this env variable first. I would look into it if you are having trouble with crystal finding libraries.
Here is a link to the RFC
Is sunvox.so compiled for C or C++? If it’s for C++ I think it won’t work.
What you can do is do @[Link(ldflags: "sunvox.o")] if you can compile the library to an .o file (you can make that path relative to the file where the lib is by doing @[Link(ldflags: "#{__DIR__}/sunvox.o")])
I think it’s compiles for both. When I use the gcc flag -x c to force compilation in C, it works fine. Is .o the only supported type? I don’t have access to the source code of the sunvox library, it’s closed source and all we have is the .so file. Is there a way to check to see if the so is C++ or C only? I would imagine it’s both, since the header is written in a way to denote both would work.
Although I am a noob when it comes to some of the C++/C stuff, not really my forte too much.
I don’t know how to do it, but maybe there’s a command or way to list all exported symbols in a. so file. Then you can see if the function/symbol you want to use is there. C++ uses strange names when it compiles names (this is called mangling) and that might be the cause Crystal can’t find the function you want.
That’s a good idea, I’ll definitely look into a tool to do it. I did test compile using -x c which forces the compiler to use C, from my understanding.
Hey so I used radare2 to get a better idea of what’s going on, and I found out something interesting, the sv_load_dll function isn’t even defined in my symbols, depsite the fact that it’s defined in my header file. I tried another function and it did work, so I guess problem solved. There isn’t really much in the way of documentation on this thing, the only thing I have to go by is the comments in the .h file.
Upon closer inspection I noticed the sv_load_dll function has some ifdef for Windows, but I don’t see why the function wouldn’t be defined in the unix version.