Lanting Guo
Lanting Guo

Reputation: 805

Julia get wrong value when I try to unsafe_load a pointer from C

The C code:

typedef struct __kstring_t {
    size_t l, m;
    char *s;
} kstring_t;

kstring_t * get_ptr_of_kstr(int num){
    char * ch = (char *)malloc(num);
    kstring_t kstr = {0, num, ch};
    kstring_t *p = &kstr;
    printf("In C, kstr.l: %zu\n", p->l);
    printf("In C, kstr.m: %zu\n", p->m);
    printf("In C, kstr.s: %p\n", p->s);
    printf("In C, pointer to kstr: %p\n", p);
    return p;
};

The Julia code

type KStr
l::Csize_t
m::Csize_t
s::Ptr{Cchar}
end

Problem

When I use ccall to call get_ptr_of_kstr and get a pointer of kstring_t in Julia, use unsafe_load to get its value, but the value seems wrong. The messages are below:

In C, kstr.l: 0
In C, kstr.m: 100000
In C, kstr.s: 0x37b59b0
In C, pointer to kstr: 0x7fffe7d80b90
kstr = Ptr{HT.KStr} @0x00007fffe7d80b90
unsafe_load(kstr).s = Ptr{Int8} @0x00007fffe7d80b90

The value of unsafe_load(kstr).s is same as kstr. Why? how to fix it?

Upvotes: 2

Views: 446

Answers (2)

Matthieu
Matthieu

Reputation: 3117

Regarding the C part (I don't know the bindings between Julia and C):

kstring_t kstr = {0, num, ch};

That would allocate kstr on the stack in the get_ptr_of_kstr() context. And the pointer to it you return is invalid right after the function exits. You can't use anymore after that, not in C or any other program you might pass it to.

As @LutfullahTomak hinted, you should either:

  • allocate it from the heap by malloc()/calloc(),
  • pass a pre-allocated pointer to the function and fill its members,
  • declare it as static in the body of the function, which makes it a global variable which scope is reduced to the function only. Note that it is not good practice though.

Also, note that your C compiler will align each struct member to an address, depending on its options and #pragma pack (if used), so the offset of each field might not be what you or Julia expects.

Upvotes: 6

Lutfullah Tomak
Lutfullah Tomak

Reputation: 761

As far as I know C, you stack allocating kstr and p is its address in the stack. After get_ptr_of_kstr returns, do not expect the values stay the same. I think you should allocate your struct in the heap.

Upvotes: 6

Related Questions