This blog is a “Hello World” example of Julia calling C.
We start of by at bit of C code we want to call from Julia. We write the following in calc_mean.c
double mean(double a, double b) { return (a+b) / 2; }
To build the library, we need to create a Makefile
CC=gcc CFLAGS=-c -Wall -fPIC SOURCES=calc_mean.c OBJECTS=$(SOURCES:.c=.o) .c.o: $(CC) $(CFLAGS) $< -o $@ lib: $(OBJECTS) $(CC) -shared -fPIC -o libmean.so $(OBJECTS) clean: rm *.o *.so
The option fPIC
and -shared
are essential for Julia to be able to resolve the function in our library. Now we are almost ready to build our library. From the bash
terminal we invoke:
make lib
This will generate a libmean.so
file.
In Julia we call the function in our c library by
x=ccall((:mean,"libmean"),Float64,(Float64,Float64),2.0,5.0) println(x) 3.5
For this to work,
Julia
must be running either on the same path wherelibmean.so
resides,- the path to
libmean.so
is inLD_LIBRARY_PATH
, or - the path to the library is
push
ed toLibdl.DL_LOAD_PATH
via
…
push!(Libdl.DL_LOAD_PATH,"path_to_libmean.so")
P.S. Thanks to Christopher Rackauckas for tips on Julia
highlighting.
Hi Perfectionatic’s
I’m studying julia and I liked the site. An error occurred while running “make”:
Makefile:9: *** missing separator. Stop.
How to solve?
Hello João,
It is just a formating issue. You need to replace the spaces in beginning of lines 9, 12, and 15 by a tab, and everything should work fine afterwards. You can also download the following gist
https://gist.github.com/mbeltagy/654098a7183f18560622c1df4006bff3
Hello,
thank you for your post si very helpfull. I’ve already created the library and i’m g¡having this error.
julia> x=ccall((:mean,”libmean”),Float64,(Float64,Float64),2.0,5.0)
ERROR: error compiling anonymous: could not load library “libmean”
I think it’s a problem with the thing that you mentioned at the end but i did
push!(Libdl.DL_LOAD_PATH,”path_to_libmean.so”) and it still doesnt work. I think i’m doing a stupid thing but i dont know what:
Could you please help me?
Thank you very much
Sara
Hello Sara,
Just to be sure ”path_to_libmean.so” in the example command is just a string pointing to where your libmean.so lives. For example on a Linux systems, this would look something like “/home/sara/juliacode/meanlib/”. So the basic steps are:
1. Make sure that “libmean.so” was actually created
2. Find its full path
3. Use that path in push!(Libdl.DL_LOAD_PATH,”path_to_libmean.so”)
Hope this helps.
Am using macOs High Sierra. Tried your example, including push!(Libdl.DL_LOAD_PATH,”path_to_libmean”).
Got. ERROR: error compiling anonymous: could not load library “libmean” dlopen(libbar.dylib, 1): image not found. Relinked as: “gcc -shared -fPIC -dynamiclib -o libmean.dylib calc_mean.o”. After using “ccall((:mean,”libmean”),Float64,(Float64,Float64),2.0,5.0)”; got result: ERROR: ccall: could not find function mean in library libmean . It seems that the library was found but not the function. Is it possible for Julia to call user defined c functions on a macintosh? Though, I was able to call libc functions from Julia on a Macintosh.
my regards,
Ihor Jakowec
I found an answer to my own question. The following works on macOs High Sierra (Darwin).
Instead of creating a library with the “.so” extension, create a dynamically linked library with
the “.dylib” extension. The c and the Julia code, posted by perfectionatic, does not need any
modification. However, the makefile with the following modifications, will work with Darwin:
CC=gcc
CFLAGS=-c -Wall -fPIC
SOURCES=calc_mean.c
OBJECTS=$(SOURCES:.c=.o)
.c.o:
$(CC) $(CFLAGS) $< -o $@ lib: $(OBJECTS) $(CC) -shared -fPIC -dynamiclib -o libmean.so $(OBJECTS) clean: rm *.o *.dylib I found this blog really useful. my regards, Ihor Jakowec