I have implemented an algorithm for image segmentation, and I am trying to interface the C++
compiled shared library through Julia
. The code seems to be working properly on a test.cpp
file which uses the same C-API (provided below) and links to the shared object file. However, I get a signal (11): Segmentation fault
from Julia
. I assume I am messing up with the ccall
, since test.cpp
works fine.
I would appreciate if you spotted the bug and helped me.
Below is the API header.
#ifndef API_H_
#define API_H_
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
struct rgb {
uint8_t comp1, comp2, comp3;
};
struct lab_f {
float comp1, comp2, comp3;
};
struct lab_d {
double comp1, comp2, comp3;
};
void palc_rgb_f(const rgb *pixels, int32_t h, int32_t w, int64_t *L,
const float *E, int64_t k, float s1, float s2, float C);
void palc_rgb_d(const rgb *pixels, int32_t h, int32_t w, int64_t *L,
const double *E, int64_t k, double s1, double s2, double C);
#ifdef __cplusplus
}
#endif
#endif
with the following API implementation, where superpixel::algorithm::palc
is a templated C++
function:
#include "api.h"
#include "algorithm/palc.cpp"
using namespace superpixel;
extern "C" {
void palc_rgb_f(const rgb *pixels, int32_t h, int32_t w, int64_t *L,
const float *E, int64_t k, float s1, float s2, float C) {
algorithm::palc(pixels, h, w, L, E, k, s1, s2, C);
}
void palc_rgb_d(const rgb *pixels, int32_t h, int32_t w, int64_t *L,
const double *E, int64_t k, double s1, double s2, double C) {
algorithm::palc(pixels, h, w, L, E, k, s1, s2, C);
}
}
Finally, I try to use it in the following test-mwe.jl
file:
import Base: convert
immutable MyRGB
r::UInt8
g::UInt8
b::UInt8
function (::Type{MyRGB})(r::Integer, g::Integer, b::Integer)
new(r, g, b)
end
function (::Type{MyRGB})(px::UInt32)
new((px >> 16) & 0xff, (px >> 8) & 0xff, px & 0xff)
end
end
function convert(::Type{UInt32}, m::MyRGB)
r, g, b = UInt32.((m.r, m.g, m.b))
return (r << 16) + (g << 8) + b
end
const libhandle = Libdl.dlopen(joinpath(pwd(), "libpalc"))
const palc_rgb_f = Libdl.dlsym(libhandle, :palc_rgb_f)
const palc_rgb_d = Libdl.dlsym(libhandle, :palc_rgb_d)
function palc!(pixels::Matrix{MyRGB}, L::Matrix{Int64}, E::Matrix{Float32},
k::Int64, s1::Float32, s2::Float32, C::Float32)
ccall(palc_rgb_f, Void, (Ref{MyRGB}, Cint, Cint, Ref{Clong}, Ref{Cfloat},
Clong, Cfloat, Cfloat, Cfloat), pixels, size(pixels,1), size(pixels,2),
L, E, k, s1, s2, C)
return L
end
function palc!(pixels::Matrix{MyRGB}, L::Matrix{Int64}, E::Matrix{Float64},
k::Int64, s1::Float64, s2::Float64, C::Float64)
ccall(palc_rgb_d, Void, (Ref{MyRGB}, Cint, Cint, Ref{Clong}, Ref{Cdouble},
Clong, Cdouble, Cdouble, Cdouble), pixels, size(pixels,1), size(pixels,2),
L, E, k, s1, s2, C)
return L
end
smallimg = fill(MyRGB(1,100,150), 5, 5)
L = Matrix(reshape(1:length(smallimg), size(smallimg)))
E = zeros(size(smallimg))
palc!(smallimg, L, E, 5, 0.2, 40.0, 4.0)
EDIT. The Julia
code edited to take into account @yuyichao’s comment on MyRGB
type definition.
I receive the following error:
signal (11): Segmentation fault
while loading no file, in expression starting on line 0
palc<rgb, int, double, long int> at /home/aytekin/Documents/My_Gits/Other/va-playground/src/algorithm/palc.cpp:168
palc_rgb_d at /home/aytekin/Documents/My_Gits/Other/va-playground/src/api.cpp:14
palc! at /home/aytekin/Documents/My_Gits/Other/va-playground/test-mwe.jl:36
unknown function (ip: 0x7f15d2f5421c)
jl_call_fptr_internal at /root/Julia/src/julia_internal.h:339 [inlined]
jl_call_method_internal at /root/Julia/src/julia_internal.h:358 [inlined]
jl_apply_generic at /root/Julia/src/gf.c:1926
do_call at /root/Julia/src/interpreter.c:75
eval at /root/Julia/src/interpreter.c:242
jl_interpret_toplevel_expr at /root/Julia/src/interpreter.c:34
jl_toplevel_eval_flex at /root/Julia/src/toplevel.c:577
jl_toplevel_eval_in at /root/Julia/src/builtins.c:496
eval at ./boot.jl:235
unknown function (ip: 0x7f15e2cc35ef)
jl_call_fptr_internal at /root/Julia/src/julia_internal.h:339 [inlined]
jl_call_method_internal at /root/Julia/src/julia_internal.h:358 [inlined]
jl_apply_generic at /root/Julia/src/gf.c:1926
eval_user_input at ./REPL.jl:66
unknown function (ip: 0x7f15e2d4718f)
jl_call_fptr_internal at /root/Julia/src/julia_internal.h:339 [inlined]
jl_call_method_internal at /root/Julia/src/julia_internal.h:358 [inlined]
jl_apply_generic at /root/Julia/src/gf.c:1926
macro expansion at ./REPL.jl:97 [inlined]
#1 at ./event.jl:73
unknown function (ip: 0x7f15d2f3937f)
jl_call_fptr_internal at /root/Julia/src/julia_internal.h:339 [inlined]
jl_call_method_internal at /root/Julia/src/julia_internal.h:358 [inlined]
jl_apply_generic at /root/Julia/src/gf.c:1926
jl_apply at /root/Julia/src/julia.h:1424 [inlined]
start_task at /root/Julia/src/task.c:267
unknown function (ip: 0xffffffffffffffff)
Allocations: 1675501 (Pool: 1674243; Big: 1258); GC: 1
fish: “julia” terminated by signal SIGSEGV (Address boundary error)
Am I doing something wrong during the ccall
?
And aside, do I still need to use Cint
and Clong
even when I am using fixed-size C-types as in the example, or can I simply use UInt8
or UInt64
inside ccall
in place of uint8_t
and uint64_t
, respectively?