Crystal: cant take address of input[0]. For array of Float64

Created on 4 Nov 2018  路  8Comments  路  Source: crystal-lang/crystal

input = [0,1,2,3]
pointerof(input[0])

Resulting

cant take address of input[0]

All 8 comments

input = [0,1,2,3]
pointer = (input.to_unsafe + 0)
p pointer.value

You can't take pointerof a call. Assign it to a local variable first:

input = [0,1,2,3]
value = input[0]
pointerof(value) # Pointer(Int32)@0x7ffea1e5fb7c

@z64
My usecase

ann = Genann.genann_init(2, 1, 2, 1)
input = [[0, 0], [0, 1], [1, 0], [1, 1]];
output = [0, 1, 0, 0];

300.times { |i|
    Genann.genann_train(ann, input[0], output[0], 3);
    Genann.genann_train(ann, input[1], output[1], 3);
    Genann.genann_train(ann, input[2], output[2], 3);
    Genann.genann_train(ann, input[3], output[3], 3);
}

@kostya Your example does works. Where can i learn more about pointer in crystal?
I currently learning binding a c library, and the library is passing a lot of pointer through parameter, which is confusing me a lot.
Let me know if there is a source code example or an article addressing this.

can you show fun declaration of genann_train?

It is based of https://github.com/codeplea/genann/blob/master/genann.h
I don't know if i'm correct

@[Link(ldflags: "#{__DIR__}/genann/genann.o")]

lib Genann 
  struct GenannActfun
    ann: Genann*
    a: Float64
  end
  struct Genann
    inputs : Int32
    hidden_layers : Int32
    hidden : Int32
    outputs : Int32
    activation_hidden : GenannActfun
    activation_output : GenannActfun
    total_weights : Int32
    total_neurons : Int32
    weight : Pointer(Float64)
    output : Pointer(Float64)
    delta : Pointer(Float64)
  end
  fun genann_init(inputs : UInt32, hidden_layers : UInt32, hidden : UInt32, outputs : UInt32): Genann*
  fun genann_train(ann : Genann*, inputs : Void*, desired_outputs : Float64*, learning_rate : Float64)
  fun genann_run(ann : Genann*, inputs: Float64): Float64*
end

Tried https://github.com/crystal-lang/crystal_lib, but errored out on parsing typedef double (*genann_actfun)(const struct genann *ann, double a);

why inputs : Void*, it should be Float64*
this should work:

Genann.genann_train(ann, input[0].to_unsafe, output[0].to_unsafe, 3);

Whether the function wants input.to_unsafe + 0 or value = input[0]; pointerof(value) depends on how the C library is programmed. If you don't know how to work it out, you shouldn't be writing C bindings. You should understand C, pointers and the stack at the minimum before writing C bindings. It's easy to generate segfaults.

The error here is correct.

Also for a nice binding you actually want to hide all the pointers within your binding, the user should get Crystal datastructures & primitives or wrappers from your binding.

Was this page helpful?
0 / 5 - 0 ratings