Calling C functions


#1

I am trying to wrap a C library (VapourSynth). It is the first time I try to do something like this, so I’m struggling a bit.

The wrapped API has something like this:

struct VSAPI
    createCore::Ptr{Cvoid}
    freeCore::Ptr{Cvoid}
    getCoreInfo::Ptr{Cvoid}
    ...
end

Where createCore, freeCore, getCoreInfo are functions which are defined like this in the header file:

struct VSAPI {
    VSCore *(VS_CC *createCore)(int threads) VS_NOEXCEPT;
    void (VS_CC *freeCore)(VSCore *core) VS_NOEXCEPT;
    const VSCoreInfo *(VS_CC *getCoreInfo)(VSCore *core) VS_NOEXCEPT;
    ...

Then I try to run something like this:

julia> api = ccall((:getVapourSynthAPI, "./vapoursynth/.libs/libvapoursynth.so"), Ptr{VSAPI}, (Cint,), 3)
Ptr{VSAPI} @0x00007f45f971a780

julia> api.createCore(0)
ERROR: type Ptr has no field createCore
Stacktrace:
 [1] top-level scope at none:0

which fails.

How could I call those functions within VSAPI?


#2

In accordance with the documentation, unsafe_load gets an instance from the pointer returned by ccall:

julia> pointer = ccall((:getVapourSynthAPI, "./vapoursynth/.libs/libvapoursynth.so"), Ptr{VSAPI}, (Cint,), 3)
Ptr{VSAPI} @0x00007f45f971a780
julia> api = unsafe_load(pointer)
VSAPI(Ptr{Nothing} @0x00007f45f96d7650, Ptr{Nothing} @0x00007f45f96d7630, Ptr{Nothing} @0x00007f45f96d7620, Ptr{Nothing} @0x00007f45f96d77d0, Ptr{Nothing} @0x00007f45f96d7740, 
...
julia> typeof(api)
VSAPI
julia> api.createCore(0)
ERROR: MethodError: objects of type Ptr{Nothing} are not callable
Stacktrace:
 [1] top-level scope at none:0

So now I am able to get access to the functions within the instance, but they still don’t work.

Maybe the function type is not properly defined?

I have:

struct VSAPI
    createCore::Ptr{Cvoid}

where the header says:

struct VSAPI {
    VSCore *(VS_CC *createCore)(int threads) VS_NOEXCEPT;

#3

You cannot call the pointers to functions directly as if they were Julia functions. Julia has no idea what arguments this function takes, not what it’s return type. Instead, pass api.createCore as the first argument to another ccall.


#4

Could you draft an example, so I can follow the pattern? (I’m not a programmer)


#5

Understood!
I did:

julia> abstract type VSCORE
       end
julia> core = ccall(api.createCore, Ptr{VSCORE}, (Cint,), 0)
Ptr{VSCORE} @0x000055f18e0252b0

Thanks as lot!