-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve compatibility between Cstring and Ptr. #14024
Conversation
The promotion fallback for |
Yes, the promotion rule seems unnecessary here. Just define |
Might also be nice to have a |
Okay, will address both tomorrow. If this is merged, does it make sense to convert usages of |
@maleadt, the important thing is to convert |
...but updating the manual is certainly a good idea. |
@stevengj I've actually spotted quite some -- 26, to be exact -- places where @nalimilan What would you like to see added? The |
In #13974, you mentioned that this would allow using |
Rebase and force push in order to kickstart appveyor (I don't think the previous failure was caused by me). I'll update the docs too. |
@@ -101,16 +101,16 @@ alignment_of(A::FakeArray) = Int32(0) | |||
# FFTW's api/import-wisdom-from-file.c file]. | |||
|
|||
function export_wisdom(fname::AbstractString) | |||
f = ccall(:fopen, Ptr{Void}, (Cstring,Ptr{UInt8}), fname, "w") | |||
f = ccall(:fopen, Ptr{Void}, (Cstring,Cstring), fname, "w") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that Ptr{UInt8}
is safe for things like this because we know that the literal string "w"
contains no embedded NUL chars. So in my initial Cstring
PR I left these as-is as an optimization (albeit probably pointless).
It looks like just about all of the Ptr{UInt8}
-to-Cstring
substitutions that you made in argument lists are of this form.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, though if you have the time/will to add a short comment explaining this, it wouldn't hurt, and will avoid repeating this next time somebody bumps on it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that Cstring
generates much longer code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A cleaner solution: change these arguments to symbols. convert
already skips null checking for them since they cannot contain NULLs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, will be changing to symbols where appropriate, and back to Ptr{UInt8}
otherwise. The IR generated by the Cstring
conversions is remarkably long indeed, but performance seemed to be okay. Will have a closer look.
Main use case: use Cstring as return value of ccall's which potentially return C_NULL.
Rebased on top of master, and squashed the commits into three logical pieces (core changes, documentation, and adaptation of base). |
|
||
julia> (Ptr{UInt8}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
guess these could be doctests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK. Do I need to do anything after converting the block to .. doctest::
? The file doesn't seem to get picked up by make -C doc doctest
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh strange, maybe it's not a big enough deal to be worth worrying about then
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My mistake, I didn't realize ::
started a literal block. Will update the documentation commit in a sec.
convert{T<:Union{Int8,UInt8}}(::Type{Cstring}, p::Ptr{T}) = box(Cstring, p) | ||
convert(::Type{Cwstring}, p::Ptr{Cwchar_t}) = box(Cwstring, p) | ||
convert{T<:Union{Int8,UInt8}}(::Type{Ptr{T}}, p::Cstring) = box(Ptr{T}, p) | ||
convert(::Type{Ptr{Cwchar_t}}, p::Cwstring) = box(Ptr{Cwchar_t}, p) | ||
|
||
# construction from untyped pointers | ||
convert{T<:Union{Cstring,Cwstring}}(::Type{T}, p::Ptr{Void}) = | ||
p==C_NULL ? box(Cstring, p) : throw(ArgumentError("cannot convert non-null void pointer to C string")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is ther any problem with converting non-NULL Ptr{Void}
to Cstring
? Also, isn't this always returning Cstring
even when called with Cwstring
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then how would bytestring(Cstring)
behave? Currently, it only checks for ptr != C_NULL
, relying on the fact that ptr
points to a NULL-terminated array of chars. I'm not sure what the advantage would be of allowing Cstring
to contain an arbitrary Ptr{Void}
And yes, it only constructs Cstring
s... Any suggestion? The constructor was based on @stevengj's comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then how would
bytestring(Cstring)
behave? Currently, it only checks forptr != C_NULL
, relying on the fact thatptr
points to a NULL-terminated array of chars.
I don't see why does this matter. In another word, I don't think it is necessary to make this convert
method only defined for invalid pointers. reinterpret
already works and if you are adding another method to do the conversion you might as well make them the same. I don't think you will gain any safety by not allowing a non-NULL pointer to be converted to Cstring
anyway.
I'm not sure what the advantage would be of allowing
Cstring
to contain an arbitraryPtr{Void}
Much easier to inline, less code to write, less code to generate, in the cases the current version is inlined, less work for compiler to remove useless code.
And yes, it only constructs
Cstring
s... Any suggestion? The constructor was based on @stevengj's comment.
Just replace box(Cstring, p)
with box(T, p)
as what you would usually do with a parametrized method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, fine by me. I've pushed a commit removing the check and related test.
I don't think the Travis error is caused by me, but I'm not sure. Is there any way to request a rebuild? |
looks like someone restarted it. what was the error? |
Something in |
I restarted it. The error was a Signal 2 and a Segfault during the |
that sounds new. i would've saved and gisted the log for that... |
LGTM. |
Improve compatibility between Cstring and Ptr.
Thanks for merging. |
This addresses #13974, and adds some convenience methods (
pointer
, and promotion rules) for working withCstring
s.I've already defined proper promotion rules, but haven't found out how to get a commutative equality operator without defining two versions. If somebody could give some hints about that, I'll still fix that.