-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Proposal: New pointer type for C pointers #1059
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
Comments
I like the first alternative you listed, leaving the implementation in userland, because it separates the C interop from the language. Adding another pointer variant for one part of one feature is a lot when it can be implemented with a simple function. Converting between all the pointers might get confusing too. I like the explicitness of a function call. |
Another thing I just realized is that pointer of unknown length to opaque type does not make sense. And forward-declared structs, which are very common in .h files, are translated as opaque types. So we can translate this case as single-item pointers. That solves a big chunk of the issue here, but it does leave integers and float values requiring the cast. |
This also means that translate-c has to detect when a pointer to opaque is happening, and use `*` instead of `[*]`. See #1059
What would the pointer turn into when unwrapping the null? Edit: Also, since |
Implicitly casting There are plans to add a
are a b and c equivalent?
EDIT: Removed noise |
What's the downside of allowing implicitly casting |
It's good to know whether youre passing one item or multiple items... I guess its the same downside as having only one type of pointer. |
That's an important question. If we can't come up with any code examples where this could lead to bugs, then we can just allow this cast and that solves the problem perfectly. |
Currently I can think of a great example of why this is dangerous: if the After #265 is implemented, this may be less of an issue, but there could be other situations like this. |
That's a bit of a weird example imho as you have exactly the same problem with any arbitrary [*]T |
Is this workflow documented and supported? I'd like to do this for SDL's .h file(s). I'd also like to consider looking into some kind of userland function that does pattern matching to automate this pointer annotation process. This may play into the code generation ideas i batted around in #383 (comment) . |
I'm not sure what you're asking with regards to support. translate-c is pretty heavily tested and it's the same code that |
@thejoshwolfe I did a translation of SDL2 to Zig a little while ago which may be a useful start for you: https://github.com/tiehuis/zig-sdl2 |
I'm going to accept this, for the same reason that we have Proposal Edit: nevermind the part about |
Inspired by #1831, what is the benefit of having (To give background, the special case is that If you're writing embedded code, and you actually have an object at address 0, Zig's assumptions would be violated by taking a pointer to that object. I looked into whether C has this problem or not, and it's one of those "technically x, but in practice y" complicated situations. And "does C have this problem?" is different from "does LLVM have this problem?", and I don't know the answer to the latter. C's concept of "null pointers" is important for compatibility with C, but why does Zig have a special case concept of "null pointers" that are different from null everything else in Zig? The more I read about null pointers in C, the more horrified I am by the semantics. For example, a C null pointer is not necessarily represented by the value zero, which means that technically sometimes doing a pointer<->integer conversion in C requires branching logic to special case null pointers maybe sometimes maybe. I'm starting to think Zig should have a special semantics for C null pointers to insulate the rest of the Zig language from this nonsense. This is another one of those "technically x, but in practice y" situations, but it might be a good idea to protect ourselves early on. |
As @thejoshwolfe notes, the actual value of NULL is kind of a nightmare. What are the use cases within Zig for translated C pointers? It seems like you are going to need to know that there is a special value, C's NULL or C++'s nullptr, and deal with it. How painful is it to write wrappers to deal with this case? I.e. have code that checks the value of the C pointer:
Where If the use case is to make Zig's null handling interoperate with C data, then this would not work, but I question whether that is going to be a large part of the code. |
|
when the int has more bits than pointers See #1059
and update self hosted compiler for C pointers See #1059
Latest Progress
Given any C function prototype, a human can look at it and properly decide between which Zig pointer type should be used. Is it a
*
pointer to a single-item? Or is it a[*]
pointer to multiple things?Unfortunately, Zig has no way to automatically distinguish, and when translating from C, it must pick one or the other. To always pick
*
makesc.printf(c"hello")
give a compile error, and to always pick[*]
makesc.scanf("%d", &value)
give a compile error.Currently I've chosen
[*]
and you can see in this commit that updates the Tetris example that I had to make a workaround functionc.ptr
and use it everywhere we pass the result of address-of to a C function:andrewrk/tetris@afdc72e
Given that one of Zig's goals is to beat C at its own game - even at interfacing with C code, interop with the result of
@cImport
should be better than this.So, just like we have integer types that are only intended to be used for C interop, I propose adding a new pointer with this syntax:
[*c]T
This pointer would be the pointer type that translate-c (and therefore
@cImport
) chooses. It has the same semantics as pointers in C:It can benull
. Adding?
in front would be an additionalnull ability on top of the fact that the pointer might
== null
.[*c]c_void
.In other words, it's a type that should only ever be used when using
@cImport
.And@cImport
should only be used when a .h file is unstable and provided by the system. For many cases, one can use translate-c one time, and then manually improve the API by changing[*c]
pointers to (possibly nullable) zig pointers, and then committing the generated and manually adjusted code to the source repository.Here are a couple simple alternatives to this proposal:
@cImport
@ptrToMany
builtin which is considered a safe (but explicit) cast to get from*T
to[*]T
. For example:@ptrToMany(&variable)
.*T
to[*]T
The text was updated successfully, but these errors were encountered: