C Interop Pointer C

Hello guys,

I’m trying the C interop to link a lib C to my Crystal code.

To simplify the comprehension of the work, I have created a miniature representation of the issue.

I have this C code

#ifndef __NEURATRON_H__
#define __NEURATRON_H__

struct Foo {
  int* array;
  int size;
};

struct Foo* init_foo();
int* give_42();


#endif // __NEURATRON_H__

#include "neuratron.h"
#include <stdlib.h>

struct Foo* init_foo() {
  struct Foo* foo = malloc(sizeof(struct Foo));
  foo->array = malloc(sizeof(int) * 5);
  foo->array[0] = 0;
  foo->array[1] = 5;
  foo->array[2] = 2;
  foo->array[3] = 1;
  foo->array[4] = 9;
  foo->size = 5;

  return foo;
}

int* give_42() {
  int* foo = malloc(sizeof(int));
  (*foo) = 40;
  return foo;
}

And the following Crystal code

@[Link("neuratron")]
lib LibLibrary
  struct Foo
    array : Pointer(Int32)
    size : Int32
  end

  fun give_me_42 = give_42() : Int32*
  fun foo = init_foo() : Pointer(Foo)
end

class Giver42
  @value : Int32
  @value2 : LibLibrary::Foo

  def initialize
    @value = LibLibrary.give_me_42.value
    @value2 = LibLibrary.foo.value
  end

  def give
    @value
  end

  def give2
    @value2
  end
end

pp LibLibrary.give_me_42.value

pp Giver42.new.give

foo = Giver42.new.give2
pp foo.value

This give me the error

undefined reference to `init_foo’

If you have any idea on how to fix it, I would love it :rocket:

It works for me if I put the C file in neuratron.c, compile it with clang -c -o neuratron.o neuratron.c and then link it using @[Link(ldflags: "#{__DIR__}/neuratron.o")].

It’s probably failing because the neuratron that the compiler finds doesn’t have the init_foo function. Maybe you have an older version put where the compiler searches that? (I can’t remember where is that, it’s the usual lib place where C also searches things).

Also, comment out the last line in your example because it gives a different error.

1 Like

Great, with the correct ldflags everythings works.

I think it used the old version of the lib.

Thanks @asterite, I will use a local ldflags until the project is finished.