我在从Julia调用C函数时遇到问题。这可能是一个非常有用的问题,但我会在这里以我正在努力的具体环境来描述它。我正在尝试创建一个bson
对象:
BSONObject("{a:1}")
所以这个对象的构造函数被调用:
BSONObject(jsonString::String) = begin
jsonCStr = bytestring(jsonString)
bsonError = BSONError()
_wrap_ = ccall(
(:bson_new_from_json, libbson),
Ptr{Void}, (Ptr{Uint8}, Csize_t, Ptr{Uint8}),
jsonCStr,
length(jsonCStr),
bsonError._wrap_
)
_wrap_ != C_NULL || error(bsonError)
bsonObject = new(_wrap_, None)
finalizer(bsonObject, destroy)
return bsonObject
end
处理MongoDB查询所需的https://github.com/pzion/LibBSON.jl/blob/master/src/BSONObject.jl LibBSON包中的,但设置并不是特别重要。重要的是ccall
,它传递字符串jsonCStr
,此字符串的长度和bsonError._wrap_
。最后一个对象来自https://github.com/pzion/LibBSON.jl/blob/master/src/BSONError.jl并且是一个数组:
type BSONError
_wrap_::Vector{Uint8}
function BSONError()
return new(Array(Uint8, 512))
end
end
在BSONError
对象的上述构造函数中创建,是一个512 Uint8
的数组。此Julia bsonError._wrap_
引用C中的以下struct
typedef struct
{
uint32_t domain;
uint32_t code;
char message[504];
} bson_error_t;
见http://api.mongodb.org/libbson/current/bson_error_t.html,这个结构的长度为4 + 4 + 504 = 512,所以看起来还不错。
现在回到ccall
,其类型签名为Ok:Ptr{Uint8}
指向字符串,Csize_t
是其大小的类型,Ptr {Uint8}指向struct
。但是,后者返回错误消息:
LoadError: MethodError: `convert` has no method matching convert(::Type{Ptr{UInt8}}, ::Array{UInt8,1})
This may have arisen from a call to the constructor Ptr{UInt8}(...),
since type constructors fall back to convert methods.
Closest candidates are:
call{T}(::Type{T}, ::Any)
convert{T<:Union{Int8,UInt8}}(::Type{Ptr{T<:Union{Int8,UInt8}}}, !Matched::Cstring)
convert{T}(::Type{Ptr{T}}, !Matched::UInt64)
...
while loading In[2], in expression starting on line 1
in convert at /Users/szalmaf/.julia/v0.4/LibBSON/src/BSONError.jl:21
in call at /Users/szalmaf/.julia/v0.4/LibBSON/src/BSONObject.jl:33
显然,尝试将Array
转换为类型Ptr{UInt8}
。
朱莉娅手册http://julia.readthedocs.org/en/latest/manual/calling-c-and-fortran-code/#mapping-c-types-to-julia在“将C类型映射到朱莉娅&#39;部分&#39;比特类型&#39;朱莉娅Array{T,N}
应该作为Ptr{T}
传递的小节,在这种情况下T
是UInt8
。所以Julia ccall
看起来不错,但仍然存在错误信息。这是一个相当棘手的问题,因为它可以防止数据库中更复杂的查询。有关如何解决此ccall
问题的任何建议吗?
P.S。请注意,如果您安装Mongo软件包,它将随LibBSON软件包和libbson C库一起提供。
答案 0 :(得分:2)
问题与ccall
无关。它由this line引起,如堆栈跟踪中所示。
在0.4中,不再有convert{T}(::Type{Ptr{T}},Array{T})
函数。
ccall
调用使用(非导出的)unsafe_convert
方法转换其参数(这就是上述代码不会导致错误的原因)。如果您想在用户代码中使用Ptr
对象,最简单的方法是使用pointer
方法。
答案 1 :(得分:1)
事实证明BSONError.jl有一个错误,
return bytestring(convert(Ptr{Uint8}, bsonError._wrap_[9:end]))
应该是
return bytestring(bsonError._wrap_[9:end])
在BSONError.jl的convert
函数中。也就是说,错误无法打印出来,因为错误打印是错误的。
修复了从C表单收到的错误消息,结果证明正确的bson格式是
BSONObject(&#34; {\&#34; \&#34;:1}&#34)
创建一个bson对象。