Джулия: ошибка финализатора Ptr{Void}

Я изучаю Джулию и пытаюсь написать оболочку libpq (библиотека PostgreSQL C).

Функция C PQconnectdb запускает соединение с PostgreSQL и возвращает указатель на структуру соединения. Структура соединения не раскрывается libpq, поскольку она бесполезна. Когда соединение завершается, оно должно быть закрыто с помощью функции C PQfinish, которая, среди прочего, заботится об освобождении памяти структуры.

Поэтому я думаю, что мне следует вызвать функцию PQfinish, когда соединение будет завершено сборщиком мусора, что и является целью следующего кода (версия Джулии: 0.3.0-744~ubuntu13.10.1):

module LibPQ

  typealias PGconn Ptr{Void}

  function pgconn_finalizer(x::PGconn)
    ccall( (:PQfinish, "libpq"), Void, (PGconn,), x )
    println("finalized")
  end

  c = ccall( (:PQconnectdb, "libpq"), PGconn, (Ptr{Uint8},), "connection params" )

  finalizer(c, pgconn_finalizer)

  println(c)

  gc()

end

Но я получаю эту ошибку:

$ julia libpq.jl
ERROR: objects of type Ptr{None} cannot be finalized
 in finalizer at base.jl:103
 in include at boot.jl:240
while loading ./libpq.jl, in expression starting on line 12

Думаю, мне следует использовать другой тип для псевдонима типа PGconn, но я не могу понять, какой именно. Есть идеи?


person mdesantis    schedule 28.01.2014    source источник
comment
Способ C сделать это состоит в том, чтобы объявить прямую ссылку на структуру, которую вы не определите позже. Итак, вы делаете что-то вроде extern struct PGConn; typedef struct PGConn PGConn;. Это дает вам именованный дескриптор типа вместо указателя void, но вы ничего не можете с ним сделать, кроме как передать его.   -  person Craig Ringer    schedule 28.01.2014
comment
Да, но вопрос о Юлии   -  person mdesantis    schedule 28.01.2014
comment
Конечно; Однако подходы на одном языке часто несколько полезно переводятся на другой или, по крайней мере, предлагают путь вперед. Я не говорил, что вы можете сделать то же самое (иначе это был бы ответ).   -  person Craig Ringer    schedule 29.01.2014
comment
О, хорошо, если я понял, что вы имеете в виду (у меня плохое знание английского), концепция, которую вы выразили, на самом деле является решением, то есть type PGconn ...   -  person mdesantis    schedule 29.01.2014


Ответы (1)


Согласно сообщению списка рассылки julia-dev, Решение состоит в том, чтобы объявить новый тип с дескриптором указателя, который будет освобожден PQfinish, как в коде, показанном ниже:

module LibPQ

  type PGconn
    handle::Ptr{Void}
  end

  function pgconn_finalizer(c::PGconn)
    if c.handle != C_NULL
      ccall( (:PQfinish, "libpq"), Void, (Ptr{Void},), c.handle )
      c.handle = C_NULL
    end
    println("finalized")
  end

  c = ccall( (:PQconnectdb, "libpq"), PGconn, (Ptr{Uint8},), "connection params" )

  finalizer(c, pgconn_finalizer)

  println(c)

  gc()

end
person mdesantis    schedule 28.01.2014