Re: mir.algebraic: Visitor cannot be called
On Thursday, 10 December 2020 at 05:49:12 UTC, 9il wrote: On Wednesday, 9 December 2020 at 14:34:18 UTC, Andre Pany wrote: [...] For .member access mir.algebraic checks at compile time that all underlying types (except typeof(null)) can be called with provided arguments. It is kind of API protection. Alternatives: With compile-time known type ``` v.get!A.foo(3); // will throw if it isn't A v.trustedGet!A.foo(3); // will assert if it isn't A ``` Without compile-time known type ``` v.tryGetMember!"foo"(3); // will throw if it isn't A v.optionalGetMember!"foo"(3); // will return null Nullable!void of it isn't A ``` tryGetMember and optionalGetMember are alternative visitor handlers in mir.algebraic. Kind regards, Ilya Fantastic, thanks a lot! Kind regards André
Re: mir.algebraic: Visitor cannot be called
On Wednesday, 9 December 2020 at 14:34:18 UTC, Andre Pany wrote: Hi, I want to port some Python coding and try have as much similiar coding as possible. I thought I can have a mir variant which stores either class A or B and I can call at runtime a method like this: ``` /+ dub.sdl: name "app" dependency "mir-core" version="1.1.51" +/ import std.stdio: writeln; import mir.algebraic; class A { void foo(int i){writeln("A.foo");} } class B { void foo(int i, string s){writeln("B.foo");} } void main() { Variant!(A,B) v = new A(); v.foo(3); } ``` But it fails with: Error: static assert: "Algebraic!(A, B): the visitor cann't be caled with arguments (B, int)" The error message seems strange. Is the behavior I want somehow possible? (At runtime I know whether I have an object of A or B and will only call with the correct method signature). Kind regards André For .member access mir.algebraic checks at compile time that all underlying types (except typeof(null)) can be called with provided arguments. It is kind of API protection. Alternatives: With compile-time known type ``` v.get!A.foo(3); // will throw if it isn't A v.trustedGet!A.foo(3); // will assert if it isn't A ``` Without compile-time known type ``` v.tryGetMember!"foo"(3); // will throw if it isn't A v.optionalGetMember!"foo"(3); // will return null Nullable!void of it isn't A ``` tryGetMember and optionalGetMember are alternative visitor handlers in mir.algebraic. Kind regards, Ilya
Re: where is the memory corruption?
On Wednesday, 9 December 2020 at 21:21:58 UTC, ag0aep6g wrote: D's wchar is not C's wchar_t. D's wchar is 16 bits wide. The width of C's wchar_t is implementation-defined. In your case it's probably 32 bits. In D, C's wchar_t is available as `core.stdc.stddef.wchar_t`. http://dpldocs.info/experimental-docs/core.stdc.stddef.wchar_t.1.html
Re: where is the memory corruption?
On 09.12.20 21:35, Jack wrote: I'm on linux/opensuse, trying to pass a wchar_* from C to D but I'm getting only the first letter of that string. Could someone help figure out why? this is the piece of D code: extern(C) export void sayHello(const (wchar) *s) [...] and below the piece of C code where I call the lib's function, compiled with clang -std=c11 -m64 dll.c -ldl [...] const wchar_t *s2 = L"hello!"; void (*fp)(const wchar_t*) = dlsym(lh, "sayHello"); char *de = dlerror(); if(de) { fprintf(stderr, "slsym error:%s\n", de); return EXIT_FAILURE; } fp(s2); the output is "h" rather "hello". What am I missing? D's wchar is not C's wchar_t. D's wchar is 16 bits wide. The width of C's wchar_t is implementation-defined. In your case it's probably 32 bits. Because of that size mismatch, sayHello sees your L"hello!" string as "h\0e\0l\0l\0o\0!\0"w. And the conversion correctly stops at the first null character. My C isn't very good, but I think char_16t is the correct analog to D's wchar. https://en.cppreference.com/w/c/string/multibyte/char16_t
Re: where is the memory corruption?
On Wednesday, 9 December 2020 at 20:35:21 UTC, Jack wrote: the output is "h" rather "hello". What am I missing? In the sayHello function, you are converting a pointer to utf16 character into utf8 string, not utf16 string to utf8 string. Convert the C wstring to a D `wstring` first (std.string.fromStringz).
where is the memory corruption?
I'm on linux/opensuse, trying to pass a wchar_* from C to D but I'm getting only the first letter of that string. Could someone help figure out why? this is the piece of D code: extern(C) export void sayHello(const (wchar) *s) { import std.stdio : writeln; import std.conv : to; import core.runtime : rt_init, rt_term; rt_init(); scope(exit) rt_term(); writeln("+sayHello()"); auto s2 = to!string(s); writeln("s2 = ", s2); writeln("-sayHello()"); } build with dub, using "targetType": "dynamicLibrary" in dub.json. and below the piece of C code where I call the lib's function, compiled with clang -std=c11 -m64 dll.c -ldl const char *libpath = "path/to/library.so"; void *lh = dlopen(libpath, RTLD_LAZY); if(!lh) { fprintf(stderr, "dlopen error: %s\n", dlerror()); return EXIT_FAILURE; } const wchar_t *s2 = L"hello!"; void (*fp)(const wchar_t*) = dlsym(lh, "sayHello"); char *de = dlerror(); if(de) { fprintf(stderr, "slsym error:%s\n", de); return EXIT_FAILURE; } fp(s2); the output is "h" rather "hello". What am I missing?
Re: How to make Create Window Work?
On Wednesday, 9 December 2020 at 17:57:49 UTC, Adam D. Ruppe wrote: C will cast 0 to null implicitly, D will not. If there's ever a case where you need to pass a number as a handle (like some HBRUSHe among others), you then explicitly cast it like `cast(HANDLE) -1`. (HANDLE is an alias to void* too so that would also work) Thank you. Now it works.
Re: How to make Create Window Work?
On Wednesday, 9 December 2020 at 17:45:18 UTC, Ruby The Roobster wrote: 0, // window menu here, that's the only int you do and I'm pretty sure that's supposed a be a HMENU which is a HANDLE, which is a void* rather than an int. C will cast 0 to null implicitly, D will not. If there's ever a case where you need to pass a number as a handle (like some HBRUSHe among others), you then explicitly cast it like `cast(HANDLE) -1`. (HANDLE is an alias to void* too so that would also work) But for 0 you almost certainly just want to get in the habit of using the built in `null` instead 0. re NULL vs null, both are OK here, but since NULL can actually be overridden by other libs (it is just a library constant) you're better off consistently using `null` for those too.
Re: How to make Create Window Work?
Also, here is the error in full: E:\Users\User\Desktop\tet.d|100| cannot pass argument `0` of type `int` to parameter `void* i`|
Re: How to make Create Window Work?
On Wednesday, 9 December 2020 at 17:42:50 UTC, Adam D. Ruppe wrote: On Wednesday, 9 December 2020 at 17:37:16 UTC, Ruby The Roobster wrote: It's not the 'NULL' that's the error. I know. It doesn't compile because of the '0' . That is what I need to fix, since I want to make a WM_COMMAND for that button. Use lowercase `null` instead. I did. Still gives an error: LRESULT WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) nothrow { scope (failure) assert(0); HDC hdc; PAINTSTRUCT ps; RECT rect; switch (message) { case WM_CREATE: CreateWindow("BUTTON".toUTF16z, // window class name "The Hello Program", // window caption WS_CHILD | WS_VISIBLE, // window style CW_USEDEFAULT,// initial x position CW_USEDEFAULT,// initial y position 250,// initial x size 250,// initial y size hwnd, // parent window handle 0, // window menu handle null,// program instance handle null); return 0; case WM_COMMAND: case WM_DESTROY: PostQuitMessage(0); return 0; default: } return DefWindowProc(hwnd, message, wParam, lParam); }
Re: How to make Create Window Work?
On Wednesday, 9 December 2020 at 17:37:16 UTC, Ruby The Roobster wrote: It's not the 'NULL' that's the error. I know. It doesn't compile because of the '0' . That is what I need to fix, since I want to make a WM_COMMAND for that button. Use lowercase `null` instead.
Re: How to make Create Window Work?
On Wednesday, 9 December 2020 at 17:32:57 UTC, Adam D. Ruppe wrote: On Wednesday, 9 December 2020 at 17:25:10 UTC, Ruby The Roobster wrote: CreateWindow("BUTTON".toUTF16z, // window class name fyi for a string literal like this you can just do "BUTTON"w.ptr // note the w This gives an error saying: Cannot pas argument of type 'int' to argument of type 'void*'. How is this fixed? Use lowercase `null` instead. It's not the 'NULL' that's the error. It doesn't compile because of the '0' . That is what I need to fix, since I want to make a WM_COMMAND for that button.
Re: How to make Create Window Work?
On Wednesday, 9 December 2020 at 17:25:10 UTC, Ruby The Roobster wrote: CreateWindow("BUTTON".toUTF16z, // window class name fyi for a string literal like this you can just do "BUTTON"w.ptr // note the w This gives an error saying: Cannot pas argument of type 'int' to argument of type 'void*'. How is this fixed? Use lowercase `null` instead.
How to make Create Window Work?
Here is the code im using: extern(Windows) LRESULT WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) nothrow { scope (failure) assert(0); HDC hdc; PAINTSTRUCT ps; RECT rect; switch (message) { case WM_CREATE: CreateWindow("BUTTON".toUTF16z, // window class name "The Hello Program", // window caption WS_CHILD | WS_VISIBLE, // window style CW_USEDEFAULT,// initial x position CW_USEDEFAULT,// initial y position 250,// initial x size 250,// initial y size hwnd, // parent window handle 0, // window menu handle NULL,// program instance handle NULL); return 0; case WM_COMMAND: case WM_DESTROY: PostQuitMessage(0); return 0; default: } return DefWindowProc(hwnd, message, wParam, lParam); } This gives an error saying: Cannot pas argument of type 'int' to argument of type 'void*'. How is this fixed?
Re: To use or not immutable?
On Wednesday, 9 December 2020 at 16:47:43 UTC, Jack wrote: Do you use it in your code base? are there some design flaws, like there's in C++'s const, which I'm not aware of? There are downsides, Jonathan Davis has written about them: http://www.jmdavisprog.com/articles/why-const-sucks.html But the downside of D's `const` or `immutable` are mainly that you can't use them everywhere you might wish to. A good rule of thumb is that if you can get it to pass compilation as `const` or `immutable` without any hacks, there is no problem going ahead with it.
To use or not immutable?
I'm coding with visual studio code and now it shows a yellow mark on variables that is never modified and that could be marked as const or immutable. I think that makes sense, so I think I'll be using it. Do you use it in your code base? are there some design flaws, like there's in C++'s const, which I'm not aware of?
mir.algebraic: Visitor cannot be called
Hi, I want to port some Python coding and try have as much similiar coding as possible. I thought I can have a mir variant which stores either class A or B and I can call at runtime a method like this: ``` /+ dub.sdl: name "app" dependency "mir-core" version="1.1.51" +/ import std.stdio: writeln; import mir.algebraic; class A { void foo(int i){writeln("A.foo");} } class B { void foo(int i, string s){writeln("B.foo");} } void main() { Variant!(A,B) v = new A(); v.foo(3); } ``` But it fails with: Error: static assert: "Algebraic!(A, B): the visitor cann't be caled with arguments (B, int)" The error message seems strange. Is the behavior I want somehow possible? (At runtime I know whether I have an object of A or B and will only call with the correct method signature). Kind regards André