Wrapping c code and packaging the wrapper

Hey everybody!
I want to wrap a .so library file which provides access to the cameras of a certain vendor (ZWO ASI). For a start I need it for home use with possible distribution later. However, I don’t manage to create a package which I can import to other projects. I took a look into BinDeps, BinaryBuilder, BinaryProvider and what not and my head is already dizzy - I think this is all way over the top, as my .so file resides on my disk.
My current folder structure looks like this:

LibASICamera (this is the package i want to have)
  |    LibASICamera.jl
  |--gen (contents auto-generated by Clang.jl)

ASICamera2 (this is where the c code resides)
  |    ASICamera2.h

Here an example function from LibASICamera_api.jl:

function ASIGetNumOfConnectedCameras()
    ccall((:ASIGetNumOfConnectedCameras, libASICamera2), Cint, ())

One can see that the variable libASICamera2 is undefined at this point. So I thought it is best to point Libdl to the library folder and define the variable in LibASICamera.jl:

module LibASICamera

import Libdl
using CEnum

push!(Libdl.DL_LOAD_PATH, "/home/.../ASICamera2/lib/x64")
libASICamera2 = "libASICamera2"

include(joinpath(@__DIR__, "..", "gen", "ctypes.jl"))
include(joinpath(@__DIR__, "..", "gen", "LibASICamera_common.jl"))
include(joinpath(@__DIR__, "..", "gen", "LibASICamera_api.jl"))

export ...

end # module

This does not work. When I load the package by “using LibASICamera” and call the example function from above I get an error:

TypeError: in ccall: first argument not a pointer or valid constant expression, expected Ptr, got Tuple{Symbol,String} ASIGetNumOfConnectedCameras() at LibASICamera_api.jl:6

On the contrary, when I use the REPL and interactively push the load path and call the function, everything works as expected. Therefore I assume that the library was not loaded correctly and/or that I have a misconception about how loading libraries works.

What do I have to change to make it work? :slight_smile:

1 Like

I would start with

const libASICamera2 = "libASICamera2"

Then I would skip the DL_LOAD_PATH and use a full path directly for libASICamera2.

1 Like

Thank you! For some reason I don’t understand declaring the variable const did the trick.

ccall is a part of the low-level infrastructure of Julia and despite the looks not an ordinary function. The need for const here is a consequence of that.