Skip to content
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

Merged
merged 4 commits into from
Dec 7, 2015
Merged

Improve compatibility between Cstring and Ptr. #14024

merged 4 commits into from
Dec 7, 2015

Conversation

maleadt
Copy link
Member

@maleadt maleadt commented Nov 17, 2015

This addresses #13974, and adds some convenience methods (pointer, and promotion rules) for working with Cstrings.

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.

@StefanKarpinski
Copy link
Member

The promotion fallback for == only applies to Numbers. Can you do this with just the two == methods without the promotion rule? For some reason this promotion strikes me as somewhat sketchy.

@stevengj
Copy link
Member

Yes, the promotion rule seems unnecessary here. Just define ==(x::Union{Cstring,Cwstring}, y::Ptr) = pointer(x) == y and vice versa. (Note that {T} is unnecessary here.)

@stevengj
Copy link
Member

Might also be nice to have a Cstring(p::Ptr{Void}) constructor so that you can do Cstring(C_NULL) rather than Cstring(Ptr{UInt8}(C_NULL)). It could throw an exception for p != C_NULL.

@maleadt
Copy link
Member Author

maleadt commented Nov 17, 2015

Okay, will address both tomorrow.

If this is merged, does it make sense to convert usages of Ptr{UInt8} to Cstring in base (where semantically applicable, of course), or is this too much churn for what it's worth?

@stevengj
Copy link
Member

@maleadt, the important thing is to convert ccall arguments where NUL-terminated strings are expected, and I think I already did this everywhere a check is needed (unless more have been added in the meantime). I don't think it is worthwhile converting other usages of Ptr{UInt8}.

@nalimilan
Copy link
Member

...but updating the manual is certainly a good idea.

@maleadt
Copy link
Member Author

maleadt commented Nov 18, 2015

@stevengj I've actually spotted quite some -- 26, to be exact -- places where Ptr{UInt8} strings (ie. should not contain NULL bytes) could be converted to Cstring. I'll push it here soon, I first want to see what the Windows bot thinks about my last commit.

@nalimilan What would you like to see added? The Cstring usage is pretty well-documented already, and I haven't changed any function signature.

@nalimilan
Copy link
Member

@nalimilan What would you like to see added? The Cstring usage is pretty well-documented already, and I haven't changed any function signature.

In #13974, you mentioned that this would allow using Cstring as a return type in addition to an argument type, so I thought the manual could be adapted to recommend this instead of Ptr{UInt8}. But there are still uses of Ptr{UInt8} as an argument type, which could have been converted to Cstring too, so that's not a new issue.

@maleadt
Copy link
Member Author

maleadt commented Nov 25, 2015

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")
Copy link
Member

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.

Copy link
Member

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.

Copy link
Contributor

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.

Copy link
Member

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.

Copy link
Member Author

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.
@maleadt
Copy link
Member Author

maleadt commented Dec 1, 2015

Rebased on top of master, and squashed the commits into three logical pieces (core changes, documentation, and adaptation of base).


julia> (Ptr{UInt8})
Copy link
Contributor

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?

Copy link
Member Author

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

Copy link
Contributor

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

Copy link
Member Author

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"))
Copy link
Contributor

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?

Copy link
Member Author

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 Cstrings... Any suggestion? The constructor was based on @stevengj's comment.

Copy link
Contributor

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 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 arbitrary Ptr{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 Cstrings... 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.

Copy link
Member Author

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.

@maleadt
Copy link
Member Author

maleadt commented Dec 1, 2015

I don't think the Travis error is caused by me, but I'm not sure. Is there any way to request a rebuild?

@tkelman
Copy link
Contributor

tkelman commented Dec 1, 2015

looks like someone restarted it. what was the error?

@maleadt
Copy link
Member Author

maleadt commented Dec 1, 2015

Something in test/spawn on the Travis bot running Mac.

@yuyichao
Copy link
Contributor

yuyichao commented Dec 1, 2015

I restarted it. The error was a Signal 2 and a Segfault during the test/spawn test in the serializer (dump.c).

@tkelman
Copy link
Contributor

tkelman commented Dec 1, 2015

that sounds new. i would've saved and gisted the log for that...

@stevengj
Copy link
Member

stevengj commented Dec 1, 2015

LGTM.

jakebolewski added a commit that referenced this pull request Dec 7, 2015
Improve compatibility between Cstring and Ptr.
@jakebolewski jakebolewski merged commit 52c1c67 into JuliaLang:master Dec 7, 2015
@maleadt
Copy link
Member Author

maleadt commented Dec 8, 2015

Thanks for merging.

@maleadt maleadt deleted the pr_cstring branch April 20, 2016 12:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants