Re: Shared library loading and static constructor
On Saturday, 23 March 2019 at 16:56:28 UTC, tchaloupka wrote: On Saturday, 23 March 2019 at 15:58:07 UTC, Sobaya wrote: What I am saying is that it can not be read when a code importing (a.d) a code including the static constructor (b.d) is compiled into shared library. Hi. I've tried to add your case to the repository and at it seems to be working for me. At least with dmd-2.085.0. When run with `make dynamicd`: ``` main shared static this +main() utils shared static this worker shared static this libworker.so is loaded entry_point1() function is found entry_point2() function is found ... -main() unloading libworker.so worker shared static ~this utils shared static ~this main shared static ~this ``` I understand the cause. Solved by passing b.d to dmd. Sorry for the stupid question.
Re: Calling D library from other languages on linux using foreign threads
On Saturday, 23 March 2019 at 15:28:34 UTC, Ali Çehreli wrote: On 03/22/2019 12:34 PM, tchaloupka wrote: > I've searched a lot at it should be working at least on linux, but > apparently is not or I'm doing something totally wrong.. > > Our use case is to call shared D library from C# (.Net Core) and from > different threads. We needed to do the same from Java. I opened this discussion: https://forum.dlang.org/thread/p0dm8f$ij5$1...@digitalmars.com and abandoned this pull request: https://github.com/dlang/druntime/pull/1989 We didn't need to pursue this further because the person who was pushing for D was leaving the company, so he rewrote the library in C++ before doing so. I don't think it's possible to call into D's GC from another thread in a safe way. If I remember correctly, there is no absolute way in POSIX (or just Linux?) of knowing that a foreign thread has died. D's GC would be holding on to an already dead thread. Ali That's pretty unfortunate. I know about your thread and PR, that's why I've tried to solve this by calling thread_attachThis()/thread_detachThis() in every worker function call. But that doesn't work in compilers > dmd-2.078.1. Actually after fiddling with this some more, I've discovered that when I call this method: ```D void* entry_point2(void*) { printf("+entry_point2\n"); scope (exit) printf("-entry_point2\n"); // This thread gets registered in druntime, does some work and gets // unregistered to be cleaned up manually if (!thread_isMainThread()) // thread_attachThis will hang otherwise { printf("+entry_point2 - thread_attachThis()\n"); thread_attachThis(); rt_moduleTlsCtor(); } // simulate GC work auto x = new int[100]; GC.collect(); if (!thread_isMainThread()) { printf("+entry_point2 - thread_detachThis()\n"); rt_moduleTlsDtor(); thread_detachThis(); } return null; } ``` from the main thread, it works too. I've observed, that: * auto x = new int[100]; needs to be there as it doesn't work otherwise * but it works only with some array lengths (I guess due to some GC decision when to kick in) - so is unreliable * it still hangs sometimes on thread_detachThis() I've no idea what should be done with C's main thread as it can't be attached because it'll hang. In one of forum threads I've also read the idea to not using foreign threads with GC but somehow delegate their work to D's thread. Can this work somehow? But `new Thread()` would still be needed to call from C side or static this() but from C's thread.
Re: Shared library loading and static constructor
On Saturday, 23 March 2019 at 15:58:07 UTC, Sobaya wrote: What I am saying is that it can not be read when a code importing (a.d) a code including the static constructor (b.d) is compiled into shared library. Hi. I've tried to add your case to the repository and at it seems to be working for me. At least with dmd-2.085.0. When run with `make dynamicd`: ``` main shared static this +main() utils shared static this worker shared static this libworker.so is loaded entry_point1() function is found entry_point2() function is found ... -main() unloading libworker.so worker shared static ~this utils shared static ~this main shared static ~this ```
Re: Shared library loading and static constructor
On Saturday, 23 March 2019 at 09:37:16 UTC, Andre Pany wrote: On Friday, 22 March 2019 at 17:52:34 UTC, Sobaya wrote: On Friday, 22 March 2019 at 11:00:32 UTC, Andre Pany wrote: On Friday, 22 March 2019 at 10:51:58 UTC, Sobaya wrote: [...] As far as I know different to windows, linus will not search current working directory for a.so. if this is the issue here, you have different possibilities. You could determine the current working directory and use std.path: buildPath to create an absolute path to a.so. This path you can then use for Runtime.loadLibrary. Or you can set the environment variable LD_LIBRARY_PATH. I do not know what is the correct way on linux. Kind regards Andre This is not a problem of path, I think. Because when I do not write static constructor in b.d, that code works. This problem occurs only when static constructor is used. Did you noticed this thread? https://forum.dlang.org/post/eumnxgxtjrvvkhxpw...@forum.dlang.org The author has an example for shared static this and it seems it works for him although he has some other issues with gc. Kind regards Andre I read his code(https://github.com/tchaloupka/dlangsharedlib). But in his code the static constructor is written directly in worker.d. Such code works just fine with me. What I am saying is that it can not be read when a code importing (a.d) a code including the static constructor (b.d) is compiled into shared library.
Re: Matching an array-type of a C++ function signature in D, without using a D-array-type, because the compiler crashes otherwise
On Saturday, 23 March 2019 at 13:04:10 UTC, kinke wrote: On Saturday, 23 March 2019 at 11:35:45 UTC, Simon wrote: Is there any way to end up with the correct mangled function signature, using only pointer types? The problem is that the C++ compiler uses head-const for the array param (`float * const`), which cannot be represented in D. What you can do is specify the mangle manually, e.g.: pragma(mangle, "?ColorEdit4@ImGui@@YA_NPEBDQEAMH@Z") extern(C++) bool ColorEdit4(const(char)* label, float* col, int flags = 0); I didn't know specifying the mangle was possible, thanks!
Re: Calling D library from other languages on linux using foreign threads
On 03/22/2019 12:34 PM, tchaloupka wrote: > I've searched a lot at it should be working at least on linux, but > apparently is not or I'm doing something totally wrong.. > > Our use case is to call shared D library from C# (.Net Core) and from > different threads. We needed to do the same from Java. I opened this discussion: https://forum.dlang.org/thread/p0dm8f$ij5$1...@digitalmars.com and abandoned this pull request: https://github.com/dlang/druntime/pull/1989 We didn't need to pursue this further because the person who was pushing for D was leaving the company, so he rewrote the library in C++ before doing so. I don't think it's possible to call into D's GC from another thread in a safe way. If I remember correctly, there is no absolute way in POSIX (or just Linux?) of knowing that a foreign thread has died. D's GC would be holding on to an already dead thread. Ali
Re: Matching an array-type of a C++ function signature in D, without using a D-array-type, because the compiler crashes otherwise
On Saturday, 23 March 2019 at 11:35:45 UTC, Simon wrote: Is there any way to end up with the correct mangled function signature, using only pointer types? The problem is that the C++ compiler uses head-const for the array param (`float * const`), which cannot be represented in D. What you can do is specify the mangle manually, e.g.: pragma(mangle, "?ColorEdit4@ImGui@@YA_NPEBDQEAMH@Z") extern(C++) bool ColorEdit4(const(char)* label, float* col, int flags = 0);
Re: Calling D library from other languages on linux using foreign threads
On Saturday, 23 March 2019 at 09:47:55 UTC, Andre Pany wrote: On Friday, 22 March 2019 at 19:34:14 UTC, tchaloupka wrote: Just to make sure, could you test it with dmd 2.78? Actually when I remove the explicit GC call within unregistered thread (which is fixed in https://github.com/dlang/druntime/commit/42b4e0a9614ac794d4549ed5b2455fd0f805e123) then it works with dmd-2.078.1 but not with 2.079.1. Well almost. Because sometimes it just hangs for me on: ``` #0 0x7fd5887d48ee in sigsuspend () from /usr/lib64/libc.so.6 #1 0x004526ec in core.thread.thread_suspendHandler(int).op(void*) () #2 0x0045274c in core.thread.callWithStackShell(scope void(void*) nothrow delegate) () #3 0x00452679 in thread_suspendHandler () #4 #5 0x7fd588b1aacb in __pthread_timedjoin_ex () from /usr/lib64/libpthread.so.0 #6 0x004277ad in D main () at main.d:89 ``` So thread is unregistered with: ``` rt_moduleTlsDtor(); thread_detachThis(); ``` But hangs on pthread_join. Isn't it suspended by GC? Manu's https://issues.dlang.org/show_bug.cgi?id=18815 seems to be related but for me it passes thread_attachThis() fine, but crash on GC during the work.
Matching an array-type of a C++ function signature in D, without using a D-array-type, because the compiler crashes otherwise
Hi, I experienced some trouble with DMD today, while trying to declare an external C++ function in D, that gets linked from a C++ compiled object file. The C++ function that I want to link against is declared as follows: bool ColorEdit4(const char* label, float col[4], int flags = 0); Yielding the following signature in the .obj (using a demangler): BOOL __cdecl ImGui::ColorEdit4(char const * __ptr64,float * __ptr64 const,int) The Function is declared in D as follows: extern(C++, ImGui) bool ColorEdit4(const(char)* label, float[4] col, int flags = 0); Which unfortunately crashes the compiler, which tells me I can't use a D array-type here, and should use a pointer. If you want to know the full story, you can look into the bug-report: https://issues.dlang.org/show_bug.cgi?id=19759 So as a workaround until this is fixed, I somehow need to end up with the same mangled function signature, while using a pointer type for the second argument. I tried: extern(C++, ImGui) bool ColorEdit4(const(char)* label, const float* col, int flags = 0); which yields: BOOL __cdecl ImGui::ColorEdit4(char const * __ptr64,float * __ptr64,int) so the 2nd argument is of type "float * __ptr64", when it should be "float * __ptr64 const". Trying "const float* col" or "const(float)* col" doesn't yield the correct result either ("float const * __ptr64 const" and "float const * __ptr64"), and I didn't find any other combinations I could try. Is there any way to end up with the correct mangled function signature, using only pointer types? Another workaround would of course be to switch to C-Linkage, so the names don't get mangled at all, but the C++-object file has function overloads, so I would like to avoid that. If this isn't possible, I might just wait for the dmd update.
Re: Calling D library from other languages on linux using foreign threads
On Friday, 22 March 2019 at 19:34:14 UTC, tchaloupka wrote: I've searched a lot at it should be working at least on linux, but apparently is not or I'm doing something totally wrong.. [...] I just noticed another issue which might be related but I doubt. https://issues.dlang.org/show_bug.cgi?id=18815 Just to make sure, could you test it with dmd 2.78? 2 years ago I think I got it working calling a D dll from C# (windows). It should work in general. Kind regards Andre
Re: Shared library loading and static constructor
On Friday, 22 March 2019 at 17:52:34 UTC, Sobaya wrote: On Friday, 22 March 2019 at 11:00:32 UTC, Andre Pany wrote: On Friday, 22 March 2019 at 10:51:58 UTC, Sobaya wrote: [...] As far as I know different to windows, linus will not search current working directory for a.so. if this is the issue here, you have different possibilities. You could determine the current working directory and use std.path: buildPath to create an absolute path to a.so. This path you can then use for Runtime.loadLibrary. Or you can set the environment variable LD_LIBRARY_PATH. I do not know what is the correct way on linux. Kind regards Andre This is not a problem of path, I think. Because when I do not write static constructor in b.d, that code works. This problem occurs only when static constructor is used. Did you noticed this thread? https://forum.dlang.org/post/eumnxgxtjrvvkhxpw...@forum.dlang.org The author has an example for shared static this and it seems it works for him although he has some other issues with gc. Kind regards Andre
Re: Build AA from two simple array
On Saturday, 23 March 2019 at 09:25:52 UTC, Andrey wrote: Hello, I have got 2 simple arrays with the same length: int[] values = [1, 2, 3, 4, 5]; char[] keys = ['a', 'b', 'c', 'd', 'e']; auto result = buildAA(keys, values); // [a: 1, b: 2, c: 3, d: 4, e: 5] I want to build AA "result" using "values" and "keys". How to do it? for example via assocArray https://dlang.org/library/std/array/assoc_array.html
Build AA from two simple array
Hello, I have got 2 simple arrays with the same length: int[] values = [1, 2, 3, 4, 5]; char[] keys = ['a', 'b', 'c', 'd', 'e']; auto result = buildAA(keys, values); // [a: 1, b: 2, c: 3, d: 4, e: 5] I want to build AA "result" using "values" and "keys". How to do it?
Re: Another Tuesday (Friday?), Another GtkDcoding Blog Post
On Friday, 22 March 2019 at 23:34:08 UTC, Ron Tarrant wrote: It's fixed now. The first one :), now there's still the other one "Here’s a second code file for you."