Yeah I think the least painful option in the long run is to wrap the native C++ in a C++/CLI class library, and do the actual UI in C# with WPF, interfacing with the class library. Or if the native code actually has a C interface, you could do pure C# with P/Invoke. Or if it for some reason has a COM interface you could maybe use that. But writing a UI straight in C++/CLI will be constant jumping through syntactical hoops.
|
|
# ? Jan 17, 2018 13:16 |
|
|
# ? Apr 28, 2024 16:38 |
|
hackbunny posted:Since I don't see a Windows thread, I guess I'll ask here I've recommended ImGui before. Not native-looking, but very light-weight, easy to deploy, easy to learn.
|
# ? Jan 17, 2018 14:02 |
|
nielsm posted:Yeah I think the least painful option in the long run is to wrap the native C++ in a C++/CLI class library, and do the actual UI in C# with WPF, interfacing with the class library. Or if the native code actually has a C interface, you could do pure C# with P/Invoke. Or if it for some reason has a COM interface you could maybe use that. But writing a UI straight in C++/CLI will be constant jumping through syntactical hoops. I'm very wary about C++/CLI, because last time I used it, it seemed buggy and distinctly "second class". I'll use it to write a managed wrapper for the C++ core, and as little else as possible. hackbunny fucked around with this message at 17:21 on Jan 17, 2018 |
# ? Jan 17, 2018 14:12 |
|
Absurd Alhazred posted:I've recommended ImGui before. Not native-looking, but very light-weight, easy to deploy, easy to learn. Very cute, and this: quote:Dear ImGui allows you create elaborate tools as well as very short-lived ones. On the extreme side of short-liveness: using the Edit&Continue feature of modern compilers you can add a few widgets to tweaks variables while your application is running, and remove the code a minute later! is just what I had been looking for, although not for this particular project. I'll certainly keep it in mind
|
# ? Jan 17, 2018 14:15 |
|
hackbunny posted:Visual Studio 2017 is the only hard requirement. Ease of deployment a plus, so I'd like to avoid gigantic frameworks with their own installer (unless the gigantic framework is .NET). Other than that, go hog wild There's always C++/WinRT which is "pure" C++, comes with VS 2017 as of 15.3 and doesn't really require anything weird to deal with. There's a github you can browse if you want a better idea of what you'd be dealing with. https://github.com/Microsoft/cppwinrt
|
# ? Jan 18, 2018 20:11 |
|
Slurps Mad Rips posted:There's always C++/WinRT which is "pure" C++, comes with VS 2017 as of 15.3 and doesn't really require anything weird to deal with. There's a github you can browse if you want a better idea of what you'd be dealing with. What does it interface with, though? WPF? UWP? Can you make desktop apps with it? I'm afraid my Windows development knowledge is a little outdated Besides, we have committed to C# and WPF. It seemed the least painful choice in terms of tool support, finding people who can work in it, third party component availability, native look & feel, etc.
|
# ? Jan 18, 2018 20:51 |
|
rjmccall posted:The clever things you can do in the STL with iterators are cute but the usability (and safety) of the entire library is just godawful because of it. Iterator ranges let you have both, but really iterators are just overrated as a collection design primitive. The STL does have its warts, but it's still the best thing that happened to C++ in the last 25 years. I read the original STL paper when it was published internally at HP, and it was a revelation. It was just So Much Better than everything else we had at the time. Of course, it then took like ten years until we actually got a compiler on HP-UX that we could use it with, but still.
|
# ? Jan 18, 2018 22:28 |
|
What is the deal with std::basic_ios::rdbuf? Specifically, version 1 here: http://en.cppreference.com/w/cpp/io/basic_ios/rdbuf I believe there ought to be two versions of the method. The const version should return a const std::basic_streambuf<CharT, Traits>* rather than a std::basic_streambuf<CharT, Traits>*. Then there should be a non-const version of the method that returns std::basic_streambuf<CharT, Traits>*. My reasoning is that istream's seekg method, which repositions the underlying streambuf, is non-const. So why should the const rdbuf() method give an object that allows for a manipulation that is forbidden by another part of the constness contract? Here is some sample code emphasizing the weirdness: code:
code:
|
# ? Jan 18, 2018 23:07 |
|
For UI libraries I saw a presentation of a Rust wrapper of libui (I think). It seemed simple enough / get poo poo done, so maybe that's a good option. On the other hand it might be "simplistic" moreso than "simple."
|
# ? Jan 18, 2018 23:38 |
|
hackbunny posted:What does it interface with, though? WPF? UWP? Can you make desktop apps with it? I'm afraid my Windows development knowledge is a little outdated Oh totally glanced over you'd already gone with C# and WPF. C++/WinRT lets you write UWP apps, and I believe anything that would interface with UWP can call into the C++ code with little work.
|
# ? Jan 19, 2018 02:26 |
|
Slurps Mad Rips posted:Oh totally glanced over you'd already gone with C# and WPF. Probably because I asked in this thread and the .NET thread at the same time and I keep forgetting what I said in which thread
|
# ? Jan 19, 2018 09:41 |
|
If I have a binary compiled with /EHa, is there a way to tell whether a catch (...) block has been entered because of SEH or standard c++ exception? I already figured out how to disambiguate CLR exceptions. Ultimately I want something like this: C++ code:
|
# ? Jan 20, 2018 11:01 |
|
Xarn posted:If I have a binary compiled with /EHa, is there a way to tell whether a catch (...) block has been entered because of SEH or standard c++ exception? I already figured out how to disambiguate CLR exceptions. You can use _set_se_translator to translate an SEH exception to whatever you want.
|
# ? Jan 20, 2018 11:11 |
|
Do my homework for me! Well, not really. I'm staring at a typedef struct on a wiki page. It really doesn't seem right. I feel it should be some kind of union or something. Even then I'm not really sure how to use it. link: https://www.riscosopen.org/wiki/documentation/show/iic_transfer or excerpt for the lazy: code:
So is it usable? If not, how can it be made to dance? I guess also, if it is, how do I use it? It probably seems silly to most, but I'm really not used to doing things this way.
|
# ? Jan 22, 2018 05:29 |
|
Reading and writing to those fields will generate instructions that will mask off only those bits and read/write to them. The bit order within memory is compiler-dependent though, so don't rely on it for a network protocol or something. (In practice if you only have one platform it's probably fine - I'm sure this example is that case given that it's .) So 8 bits will be used for the addr bitfield, that could just be a uint8_t itself. 21 bits are used reserved and not for you to use - nothing you write using this struct will set those bits no matter what. 1 bit is used for the retry field - reading from it will return 1 or 0. You have to know more about the iic protocol to use it I think but yeah, that looks like a fine message header struct/bitfield example to me.
|
# ? Jan 22, 2018 05:37 |
|
Jeffrey of YOSPOS posted:Reading and writing to those fields will generate instructions that will mask off only those bits and read/write to them. The bit order within memory is compiler-dependent though, so don't rely on it for a network protocol or something. (In practice if you only have one platform it's probably fine - I'm sure this example is that case given that it's .) So 8 bits will be used for the addr bitfield, that could just be a uint8_t itself. 21 bits are used reserved and not for you to use - nothing you write using this struct will set those bits no matter what. 1 bit is used for the retry field - reading from it will return 1 or 0. So, does C throw code in for bit shifting or something? eg, can I just write 1 or 0 to "nostart"? or do I need to shift first before writing to it. I'm not concerned about the IIC aspect. I just didn't get the typedef. What I want to do is just make sure I'm doing things right by talking to some devices I have (We are talking Raspberry Pi here) to make sure I'm doing it right. Then just slap a slightly more user friendly wrapper around the involved structures and SWIs and add it to the GPIO library I wrote a while ago. The GPIO library actually deals with the hardware directly, but presents a more friendly interface. When I wrote it GPIO access SWIs weren't included with RISC OS, so I just did a normal C library. e: I found some info that actually answered that. No, I don't need to do any bit fiddling and apparently it doesn't allow larger values than can fit in the bitfield. Somehow I feel that last part is implementation specific. General_Failure fucked around with this message at 07:56 on Jan 22, 2018 |
# ? Jan 22, 2018 06:03 |
|
Yeah the compiler will generate code to do the shifting and write to just those bits. You can just write 1 to nostart. The reason people stick typedefs around structs is so they can declare them with one identifier - in the future you can declare one with just "iic_transfer foo;" instead of "struct iic_header foo;" because you have the typedef around it. It's basically saying "create an alias for struct iic_transfer { unsigned bunchofthings:69; } called iic_transfer.
|
# ? Jan 22, 2018 07:53 |
|
Also the comment says this:code:
|
# ? Jan 22, 2018 07:58 |
|
Jeffrey of YOSPOS posted:Also the comment says this: The direction is part of the address.
|
# ? Jan 22, 2018 08:14 |
|
b0lt posted:You can use _set_se_translator to translate an SEH exception to whatever you want. Thanks, that looks fairly close to what I want.
|
# ? Jan 22, 2018 08:51 |
I'm trying to understand when pointer casts in C are safe, and I'm having trouble finding good resources on this topic. For example:C++ code:
|
|
# ? Jan 25, 2018 01:12 |
|
My understanding is that compilers are allowed to assume pointers to fundamentally different types never alias, except for char*, void*, and other pointers to bytes. Since f1, f2, and f3 casts a char* (or void*) to a Foo* and then uses that Foo*, it would be undefined behavior. If it was the other way around (casting a Foo* to char*), I think it would be fine. Here's a Stack Overflow link with excerpts from the C and C++ standards: https://stackoverflow.com/a/7005988 I don't know of any good specifically C resources, but this cppreference link also summarizes these rules (look under the type aliasing section): http://en.cppreference.com/w/cpp/language/reinterpret_cast You should be able to find more information about this by looking up "type aliasing", "strict aliasing", or "type punning".
|
# ? Jan 25, 2018 03:46 |
|
please use -fno-strict-aliasing
|
# ? Jan 25, 2018 04:54 |
qsvui posted:My understanding is that compilers are allowed to assume pointers to fundamentally different types never alias, except for char*, void*, and other pointers to bytes. Since f1, f2, and f3 casts a char* (or void*) to a Foo* and then uses that Foo*, it would be undefined behavior. If it was the other way around (casting a Foo* to char*), I think it would be fine. Thanks. I have googled those things but it's still a little unclear. For example, it seems like you are allowed to "round-trip" things, casting a Foo * to a void * and back (and then using it). See e.g. this libgit2 function, intended to be used like this. But what if the pointer was never a Foo * to begin with, and was instead just some opaque bytes (perhaps read from a file)? And what if you use a char * instead, or first cast your void * to a uintptr_t in order to do math with it?
|
|
# ? Jan 25, 2018 04:56 |
|
Interpreting a sequence of bytes as a struct is like, C's core competency and gently caress if I'm gonna use a union to do it!!!
|
# ? Jan 25, 2018 05:04 |
|
alignment is the other problem you're going to run into, char[] isn't guaranteed to be aligned sufficiently for whatever you're interpreting it as.
|
# ? Jan 25, 2018 05:06 |
b0lt posted:alignment is the other problem you're going to run into, char[] isn't guaranteed to be aligned sufficiently for whatever you're interpreting it as. Hmmm, that makes sense. So if my main looked like this: C++ code:
|
|
# ? Jan 25, 2018 05:20 |
|
VikingofRock posted:Thanks. I have googled those things but it's still a little unclear. For example, it seems like you are allowed to "round-trip" things, casting a Foo * to a void * and back (and then using it). See e.g. this libgit2 function, intended to be used like this. But what if the pointer was never a Foo * to begin with, and was instead just some opaque bytes (perhaps read from a file)? And what if you use a char * instead, or first cast your void * to a uintptr_t in order to do math with it? The whole idea in the first place is built on the idea that structures of different types always occupy mutually exclusive memory regions, and the only exception that it allows is accesses via char pointers. As long as the memory regions don't actually overlap, pointer conversion doesn't matter at all. You can allocate memory as one type and use it as another type, it doesn't matter, it only matters if you try to access the same memory as two different types. There are some exceptions built into most compilers, namely that accesses via a union may alias, and some stuff I forgot relating to structures starting with the same initial members. Pointer conversion in C++ is a whole different can of worms, since pointer casts can cause the address to change, it has some special cases like dynamic_cast<void*>, and C-style casts may have different results depending on whether or not the classes being cast to and from are defined (which is part of why you should never use C-style cases in C++). OneEightHundred fucked around with this message at 05:27 on Jan 25, 2018 |
# ? Jan 25, 2018 05:24 |
|
Jeffrey of YOSPOS posted:please use -fno-strict-aliasing No. Use memcpy.
|
# ? Jan 25, 2018 08:50 |
|
Xarn posted:No. Use memcpy. Better yet, do both, since you know you have code that's invalid with -fstrict-aliasing
|
# ? Jan 25, 2018 10:27 |
|
Xarn posted:No. Use memcpy.
|
# ? Jan 25, 2018 16:38 |
|
Jeffrey of YOSPOS posted:So you get a packet full of structs, your system has already copied it once out of the network card buffer, and you're gonna copy it again instead of interpreting it like the struct it is? Maybe I'm poisoned by my domain but that's a little insane to me in this, the language-for-interpreting-bytestrings-as-structs. Casting a pointer to char to a pointer to a struct is not a violation of strict aliasing. This is not where memcpy is needed.
|
# ? Jan 25, 2018 17:41 |
eth0.n posted:Casting a pointer to char to a pointer to a struct is not a violation of strict aliasing. This is not where memcpy is needed. But you might not have any alignment guarantees then.
|
|
# ? Jan 25, 2018 17:43 |
|
eth0.n posted:Casting a pointer to char to a pointer to a struct is not a violation of strict aliasing. This is not where memcpy is needed. Alignment is an issue on some platforms. GCC aligned types and attribute packed can help here, but yeah, the compiler will happily convert "aligned pointers" to normal unconstrained pointers without warning by default, so being careful when using those is warranted. In general you should know your own platform here and minimize unaligned accesses but trying to eliminate them completely is pretty extreme if you're, say, handling a network protocol that sends unaligned integers as part of normal operation.
|
# ? Jan 25, 2018 17:54 |
|
Jeffrey of YOSPOS posted:So you get a packet full of structs, your system has already copied it once out of the network card buffer, and you're gonna copy it again instead of interpreting it like the struct it is? Maybe I'm poisoned by my domain but that's a little insane to me in this, the language-for-interpreting-bytestrings-as-structs.
|
# ? Jan 25, 2018 18:35 |
|
Jeffrey of YOSPOS posted:But it seems very easy to require it, no? There's plenty of reasons you might need to actually access it as a character array first and then access it as a struct? Maybe I'm misunderstanding something about aliasing rules but my understanding was that, if you use it and access it as a character array, you cannot also access it as a struct, and thus should turn off the silly option. You can just create it as a struct object, then recv into it directly. You can even access it via a char pointer if you need byte-level access for some reason, freely interleaved with accesses to the struct itself, at least without running afoul of strict aliasing. Basically, undefined behavior is bad, and you should avoid it wherever possible. Turning off one compiler feature which might misbehave with that UB is a workaround for crap code, not a justification for writing new crap code. You keep talking about performance, but do you actually know if the performance gains you think you are getting are real compared to correct code, and that they aren't outweighed by the performance lost because the compiler loses optimization opportunities with that feature off? The strict aliasing rule exists so compilers can optimize in certain ways. eth0.n fucked around with this message at 19:38 on Jan 25, 2018 |
# ? Jan 25, 2018 19:35 |
|
The behavior isn't undefined if your compiler defines how it will behave - conforming to ISO C in this case makes your code worse, not better. My real answer is that I agree with Linus that, while I understand how the aliasing rules came to be, I think they are boneheaded as written and ought to be worked around if you need to view the same memory in multiple ways. They could have specified the language such that the degradation of aliasing assumptions could be controlled by the user, but they didn't bother doing that. The ISO C spec is not a religious text, you're allowed to question it and I think it'd be irresponsible to manage any large C project without at the very least thinking carefully about discarding the existing aliasing rules, especially if what you're doing involves receiving binary data from external sources. Casting between pointer types in your function is a good sign that the strict aliasing assumptions are not true within that function, my complaint pretty much would go away if the spec was written such that it gave up its aliasing assumptions once that happened.
|
# ? Jan 25, 2018 21:09 |
|
Jeffrey of YOSPOS posted:Casting between pointer types in your function is a good sign that the strict aliasing assumptions are not true within that function, my complaint pretty much would go away if the spec was written such that it gave up its aliasing assumptions once that happened. That would complicate compiler design since you'd be adding a "look for a cast between pointer types in this scope" to your parser. Easiest way would be to add a nostrict or norestrict (to mimic C) keyword specifier for functions that could tell the compiler to not use strict aliasing in that scope. Submit a proposal to the C++ committee and see what happens!
|
# ? Jan 25, 2018 22:49 |
|
I've also read that as of C99, writing an object to a union member and then accessing that object with the other member of the union is a safe operation. This is not true for C++ though.
|
# ? Jan 26, 2018 03:05 |
|
|
# ? Apr 28, 2024 16:38 |
|
The fact that the "reinterpret the opaque sequence of bytes as a different type" function is called "memcpy" is an unfortunate historical oddity, but it still does what you're actually trying to accomplish in most cases. Essentially, you can write correct code that also happens to be optimally fast if your compiler works the way you expect it to, or you can write fast code that is only correct if your compiler works the way you expect it to. So what makes the second one preferable to you, again?
|
# ? Jan 26, 2018 03:26 |