Wrapping C function returning struct containing character array (Cstring)

Example code, but essentially what the C library that I am wrapping returns:

#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#define BUFSIZE 128
struct C {
    int a;
    double b;
    char c[BUFSIZE];
};

struct C returns_struct() {
    struct C retval;
    retval.a = 1;
    retval.b = 2.2;
    strncpy(retval.c, "hi there", BUFSIZE);
    return retval;
}

int main(int argc, char *argv) {
    struct C thing = returns_struct();
    printf("thing.a = %d\n", thing.a);
    printf("thing.b = %f\n", thing.b);
    printf("thing.c = %s\n", thing.c);
    return EXIT_SUCCESS;
}

Although it has a main function (for testing), I compile it with gcc -fPIC -shared stuff.c -o libstuff.so. In Julia I try to wrap it with:

struct C
    a::Cint
    b::Cdouble
    c::Cstring # <-- the problem appears to be this
end

stuff = @ccall "./libstuff.so".returns_struct()::C

If I remove the string from the struct, things seem to work well … any idea what I am missing?

Cstring is essentially a pointer whereas your C struct contains a fixed size array. Try with

struct C
    a::Cint
    b::Cdouble
    c::NTuple{128, Cchar}
end
2 Likes
stuff = @ccall "./libstuff.so".returns_struct()::C
C(1, 2.2, (104, 105, 32, 116, 104, 101, 114, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))

… I think I can work with that, thanks!
I can use this clunky expression to get the Julia representation of it:

join(convert.(Char, filter(x -> x > 0, stuff.c)))

There’s probably a better solution but this is at least less clunky:

String(UInt8[c for c in stuff.c])