Thread overview | ||||||||
---|---|---|---|---|---|---|---|---|
|
December 09, 2020 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? |
December 09, 2020 Re: where is the memory corruption? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jack | 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).
|
December 09, 2020 Re: where is the memory corruption? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jack | 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 |
December 09, 2020 Re: where is the memory corruption? | ||||
---|---|---|---|---|
| ||||
Posted in reply to ag0aep6g | 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 |
December 10, 2020 Re: where is the memory corruption? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Paul Backus | On Wednesday, 9 December 2020 at 21:28:04 UTC, Paul Backus wrote:
> 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
Don't use wchar_t in C. It has variable size depending of implementation. On Posix machines (Linux, BSD etc.) it's 32 bit wide UTF-32, on Windows it 16 bit UTF-16.
|
December 10, 2020 Re: where is the memory corruption? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jack | On Wednesday, 9 December 2020 at 20:35:21 UTC, 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? > > [...] May be this help to you: auto s2 = to!string(s); to auto s2 = fromWChar( s ); wstring fromWChar( const wchar* s ) { import std.conv : to; return s[ 0 .. wcslen( s ) ].to!wstring; } Example: https://run.dlang.io/is/PkCeTZ |
Copyright © 1999-2021 by the D Language Foundation