Search code examples
crystal-lang

Program received and didn't handle signal IOT (6), when run Crystal program


I have program, that linked to C library "nats"

@[Link("nats")]
lib LibNats
  fun natsConnection_ConnectTo(connection: UInt64*, connstr: UInt8*)
  fun natsConnection_PublishString(connection: UInt64*, key: UInt8*, value: UInt8*)
  fun natsConnection_Subscribe(sub: UInt64*, connection: UInt64*, key: UInt8*, cb: (UInt64*, UInt64*, UInt64*) -> Void)
end

connection = uninitialized UInt64
s = uninitialized UInt64

LibNats.natsConnection_ConnectTo(pointerof(connection), "nats://localhost:4222")
LibNats.natsConnection_Subscribe(pointerof(s), pointerof(connection), "qwe", ->(c, s, m) {
  puts m
})
LibNats.natsConnection_PublishString(pointerof(connection), "qwe", "{}")

After run it, I receive error: Program received and didn't handle signal IOT (6)


Solution

  • Looking at the include file the first function is:

    NATS_EXTERN natsStatus
    natsConnection_ConnectTo(natsConnection **nc, const char *urls);
    

    Look at the double pointer there, whereas in your binding you just use one pointer.

    This is very common in C libraries: you have some struct with your data (natsConnection) and you usually pass it by reference (hence a pointer) but you receive a pointer to that pointer in a "constructor" function where you want to store that pointer, for which memory is usually allocated by the function itself.

    Anyways, the explanation is really long and I don't have time right now, but try with this:

    @[Link("nats")]
    lib LibNats
      type Conn = Void*
      type Sub = Void*
    
      alias Status = Int32
    
      fun natsConnection_ConnectTo(connection : Conn*, connstr : UInt8*) : Status
      fun natsConnection_PublishString(connection : Conn, key : UInt8*, value : UInt8*) : Status
      fun natsConnection_Subscribe(sub : Sub*, connection : Conn, key : UInt8*, cb : (UInt64*, UInt64*, UInt64*) -> Void) : Status
    end
    
    status = LibNats.natsConnection_ConnectTo(out connection, "nats://localhost:4222")
    abort "natsConnection_ConnectTo failed" if status != 0
    
    status = LibNats.natsConnection_Subscribe(out subscription, connection, "qwe", ->(c, s, m) {
      puts m
    })
    abort "natsConnection_Subscribe failed" if status != 0
    
    status = LibNats.natsConnection_PublishString(connection, "qwe", "{}")
    abort "natsConnection_PublishString failed" if status != 0
    

    Also read about the out keyword and make sure you check for errors.