Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning C structs by-value to Julia

Tags:

c

struct

julia

I am trying to pass a C struct to Julia using ccall

Here is my file in C:

#include <stdio.h>

typedef struct {
    float a;
    float b;
} TestStruct;

TestStruct getStruct() {
    TestStruct s = {3.0f, 5.0f};
    printf("Created struct a: %f b: %f\n", s.a, s.b);
    return s;
}

Then I compile this into a shared library to use with Julia.

Here is my Julia file:

immutable TestStruct
    a::Cfloat
    b::Cfloat
end

struct = ccall((:getStruct, "libteststruct"), TestStruct, ())
println("Got struct a: ", struct.a, " b: ", struct.b)

When I run this file I would expect to get

Created struct a: 3.000000 b: 5.000000
Got struct a: 3.0 b: 5.0

However, I am instead getting

Created struct a: 3.000000 b: 5.000000
Got struct a: 3.0 b: 0.0

a is always correct but b is always 0.

This works when I use doubles in the struct instead of floats, but I need to use floats.

Thank you.

like image 476
Zach Avatar asked Mar 31 '15 18:03

Zach


2 Answers

This works fine for me on Julia master (0.4-dev) -- on Windows to boot. Full by-value struct support was only recently merged into master. It might appear to (kind of) work on 0.3 but is not officially supported and should probably be an error.

like image 150
Isaiah Norton Avatar answered Nov 11 '22 14:11

Isaiah Norton


If you are on Julia v0.3.x, ccall does not handle returning structs via the calling convention correctly. You can try changing the ccall usage to this:

struct_buffer = Array(TestStruct)
ccall((:getStruct, "libteststruct"), Void, (Ptr{TestStruct},), struct_buffer)
struct = struct_buffer[]

This issue may be fixed on Julia master (0.4-dev), so you can also try that and see how it goes.

like image 30
StefanKarpinski Avatar answered Nov 11 '22 16:11

StefanKarpinski