digitalmars.D - Dll support: testers needed
- Benjamin Thaut (28/28) Jan 06 2018 I'm currently back on dll support and I'm applying finishing touches to
- Rubn (3/3) Jan 06 2018 Looks good. If you want testers though, providing binaries would
- Benjamin Thaut (6/8) Jan 07 2018 I made a binary distribution. I updated
- rikki cattermole (10/10) Jan 06 2018 +infinity
- Benjamin Thaut (27/33) Jan 07 2018 Because the DIP says that -useshared and -fPIC are loosley comparable.
- MrSmith (2/6) Jan 07 2018 Does the implementation support dynamically loaded dlls?
- Benjamin Thaut (5/6) Jan 07 2018 Yes. There is even a test for it
- solidstate1991 (3/31) Jan 07 2018 I would volunteer, but I don't know how much I can do in my exam
- Benjamin Thaut (6/10) Jan 08 2018 Just do some testing whenever you find time, keep monitoring this thread...
- Dylan Graham (4/12) Jan 08 2018 I'm waiting on VS2015 and Windows SDK to install. Once that's
- Dylan Graham (27/31) Jan 08 2018 I've done a test that mimics that the planned plugin system for
- Benjamin Thaut (26/28) Jan 09 2018 Hi Dylan,
- Dylan Graham (14/44) Jan 09 2018 In all honesty, I'm not sure. I saw the instructions on your
- MrSmith (4/4) Jan 09 2018 Is it possible to put common code in exe, and use that code from
- Benjamin Thaut (15/21) Jan 09 2018 You can only export from dlls. I don't know of any use case where
- Andre Pany (12/31) Jan 09 2018 I am building a bridge between Delphi and D. At the moment the
- Benjamin Thaut (44/58) Jan 09 2018 First let me say that what you are describing is a very uncommon and
- Andre Pany (17/65) Jan 09 2018 Thanks for your deep analysis. There are several reasons I want
- Bastiaan Veelo (14/25) Jan 09 2018 I wrote a mixed language app with interdependent components (no D
- Domain (3/8) Jan 09 2018 I am glad to see this happen. But my use case is not working:
- Benjamin Thaut (9/18) Jan 10 2018 Hi Domain,
- Domain (5/23) Jan 10 2018 Sorry, my mistake. But I cannot use your binary:
- Benjamin Thaut (6/13) Jan 10 2018 This works just fine for me. What is the output when you execute "dmd
- Domain (100/110) Jan 10 2018 I restart my computer, and it can produce dll now. But when I
- Benjamin Thaut (14/34) Jan 11 2018 As I said in the first post, I'm not interrested in linker errors due to...
- Domain (4/20) Jan 11 2018 I misunderstand what you mean. I thought -useshared is used when
- Domain (3/13) Jan 11 2018 So I cannot use phobos as a static library when I use dll?
- Benjamin Thaut (8/13) Jan 11 2018 If you have a single D-dll that is used from a C program then you can
- Domain (6/16) Jan 10 2018 D:\git\testdll\source>dmd --version
I'm currently back on dll support and I'm applying finishing touches to my dll support PR. Now I want to know if I missed any corner cases and it would be great if a few more people gave the dll support a try. -To try it out you will need to build dmd, druntime and phobos yourself. I'm not going to provide a binary distribution. -You will need to target the microsoft linker. E.g. either use -m64 or -m32mscoff when compiling your programs. -be warned, the state of the dll support is not final and subject to change. There is no garantuee that there won't be any breaking changes to dll support. You can find a quick start guide here: http://stuff.benjamin-thaut.de/D/getting_started.html If you need more information and examples take a look here: https://github.com/Ingrater/DIPs/blob/ReviveDIP45/DIPs/DIP45.md Not all of phobos/druntime has correct export annotations yet as this is not the goal of my initial pull request. If you use a function from druntime/phobos that does not have a correct export annotation you will get a linker error. I'm not interrested in those. I'm interrested in cases where export is correctly used and you will still get linker errors / incorrect program behavior. So if you encounter a linker error first check if the declaration has a export annotation or not. Try adding it and see if the error goes away. If it does not go away, report it here or send me an e-mail to code at benjamin-thaut.de If you find anything, small repro cases would be appreciated as it makes my life a lot easier. -- Kind Regards Benjamin Thaut
Jan 06 2018
Looks good. If you want testers though, providing binaries would be beneficial. Compiling dmd/druntime/phobos on Windows can be a pain.
Jan 06 2018
Am 07.01.2018 um 00:42 schrieb Rubn:Looks good. If you want testers though, providing binaries would be beneficial. Compiling dmd/druntime/phobos on Windows can be a pain.I made a binary distribution. I updated http://stuff.benjamin-thaut.de/D/getting_started.html with the details. -- Kind Regards Benjamin Thaut
Jan 07 2018
+infinity Few things I would like answered: - Why -useShared and not -fPIC? - If -useShared why not use it on *nix to turn on -fPIC? - Why isn't DllIsUsedFromC.no automatically detected? Regarding C-runtime, yes we need to distribute every version that we support on Windows. The compiler will pick the latest (or the installer I guess) to use, but we should be able to switch between them. Either that or we ship a static lib of Phobos to be linked into a dll upon first request of a specific C-runtime.
Jan 06 2018
Am 07.01.2018 um 03:57 schrieb rikki cattermole:+infinity Few things I would like answered: - Why -useShared and not -fPIC? - If -useShared why not use it on *nix to turn on -fPIC?Because the DIP says that -useshared and -fPIC are loosley comparable. This does not mean that they are the same or interchangeable. In fact they are not. On linux when building a executable that uses a shared library -fPIC is not neccessary, unless your distribution requires position independend code everywhere. On windows on the other hand you will need to pass -useshared when building a executable that uses shared libraries.- Why isn't DllIsUsedFromC.no automatically detected?Because its not possible. I don't know of any way to detect wether a dll is loaded by a c-executable or d-executable. As a result the user has to specify it. The main problem here is that currently D Dlls hijack all threads. This is neccessary because currently there is no shared version of phobos, so the information about the threads can't be shared between multiple D dlls. One possibility would also be to remove the thread hijacking alltogether and require the user to manually add threads that have been created from C. This is also the current state on linux if I'm not mistaken. But doing so would break backwards compatibility.Regarding C-runtime, yes we need to distribute every version that wesupport on Windows. The compiler will pick the latest (or the installer I guess) to use, but we should be able to switch between them. Either that or we ship a static lib of Phobos to be linked into a dll upon first request of a specific C-runtime. That really is a problem I'm not going to solve. It is more a problem of distributing dmd and building the installer which is beyond the scope of my current PR. -- Kind Regards Benjamin Thaut
Jan 07 2018
On Saturday, 6 January 2018 at 19:32:51 UTC, Benjamin Thaut wrote:You can find a quick start guide here: http://stuff.benjamin-thaut.de/D/getting_started.html If you need more information and examples take a look here: https://github.com/Ingrater/DIPs/blob/ReviveDIP45/DIPs/DIP45.mdDoes the implementation support dynamically loaded dlls?
Jan 07 2018
Am 07.01.2018 um 15:08 schrieb MrSmith:Does the implementation support dynamically loaded dlls?Yes. There is even a test for it -- Kind Regards Benjamin Thaut
Jan 07 2018
On Saturday, 6 January 2018 at 19:32:51 UTC, Benjamin Thaut wrote:I'm currently back on dll support and I'm applying finishing touches to my dll support PR. Now I want to know if I missed any corner cases and it would be great if a few more people gave the dll support a try. -To try it out you will need to build dmd, druntime and phobos yourself. I'm not going to provide a binary distribution. -You will need to target the microsoft linker. E.g. either use -m64 or -m32mscoff when compiling your programs. -be warned, the state of the dll support is not final and subject to change. There is no garantuee that there won't be any breaking changes to dll support. You can find a quick start guide here: http://stuff.benjamin-thaut.de/D/getting_started.html If you need more information and examples take a look here: https://github.com/Ingrater/DIPs/blob/ReviveDIP45/DIPs/DIP45.md Not all of phobos/druntime has correct export annotations yet as this is not the goal of my initial pull request. If you use a function from druntime/phobos that does not have a correct export annotation you will get a linker error. I'm not interrested in those. I'm interrested in cases where export is correctly used and you will still get linker errors / incorrect program behavior. So if you encounter a linker error first check if the declaration has a export annotation or not. Try adding it and see if the error goes away. If it does not go away, report it here or send me an e-mail to code at benjamin-thaut.de If you find anything, small repro cases would be appreciated as it makes my life a lot easier.I would volunteer, but I don't know how much I can do in my exam session. Maybe in February, until then not much.
Jan 07 2018
Am 08.01.2018 um 00:06 schrieb solidstate1991:On Saturday, 6 January 2018 at 19:32:51 UTC, Benjamin Thaut wrote: I would volunteer, but I don't know how much I can do in my exam session. Maybe in February, until then not much.Just do some testing whenever you find time, keep monitoring this thread foor upates. -- Kind Regards Benjamin Thaut
Jan 08 2018
On Monday, 8 January 2018 at 09:01:29 UTC, Benjamin Thaut wrote:Am 08.01.2018 um 00:06 schrieb solidstate1991:I'm waiting on VS2015 and Windows SDK to install. Once that's done, I'll begin testing. Also, thanks a tonne for doing this.On Saturday, 6 January 2018 at 19:32:51 UTC, Benjamin Thaut wrote: I would volunteer, but I don't know how much I can do in my exam session. Maybe in February, until then not much.Just do some testing whenever you find time, keep monitoring this thread foor upates.
Jan 08 2018
On Tuesday, 9 January 2018 at 03:50:25 UTC, Dylan Graham wrote:On Monday, 8 January 2018 at 09:01:29 UTC, Benjamin Thaut wrote: I'm waiting on VS2015 and Windows SDK to install. Once that's done, I'll begin testing. Also, thanks a tonne for doing this.I've done a test that mimics that the planned plugin system for my game. There is a core/engine which is built as a DLL. It exports a class called PluginBase. It also exports a function called getPlugins (to be run from an executable) that searches for plugin DLLs and calls a function from those plugin DLLs that returns their own override of PluginBase. It then runs a few functions on the object and prints the typeid(). The core is built with: dmd -m64 -shared -useshared -version=Shared -H pluginbase.d -L/IMPLIB:pluginbase.lib The resulting pluginbase.di and pluginbase.lib is copied into the directory of Plugin1 which builds against them. Command: dmd -m64 -shared -useshared plugin1.d pluginbase.lib I then made an executable that builds against pluginbase and calls getPlugins(). Command: dmd -m64 -useshared app.d pluginbase.lib pluginbase.dll and plugin1.dll are placed next to the executable. Running it prints this: PS C:\dmd-dll\test\execut> ./app.exe Plugin1 -- (name of plugin defined by overriden class) Hello world from Plugin1 -- (function of that class) plugin1.Plugin1 -- (typeid of that class) It's pretty basic but I'm glad it works. I'll try doing something more advanced.
Jan 08 2018
Am 09.01.2018 um 05:19 schrieb Dylan Graham:It's pretty basic but I'm glad it works. I'll try doing something more advanced.Hi Dylan, I'm glad that it works for you. I'm curios though, why are you using an import library for your plugin? Normally plugins are build without and import library (the -L/IMPLIB parameter) and then loaded dynamically through LoadLibrary by your main executable. This way you can add/remove plugins without the need to recompile your main executable. Usually such plugin systems are done like this: You have some common library that defines shared functionality and the base interfaces such as a Plugin base class or Plugin interface. This common library is build into a dll with import library. You have one ore multiple plugins that link against the common library and implement the plugin interface / plugin base class. Each of these plugins provides a function "getPluginImpl" or something along the lines which can be used to get an instance of the Plugin implementation. You have the main executable, which links against the common library. It dynamically loads the plugin.dlls and calls the getPluginImpl method on them to retrieve the implementation. No import library involved here. What your doing is also a valid use case. It is usually done when link times get to long or if you want to have clean interface between the different subsystems in your application. Your codebase is usually split into multiple dlls each with a import library which are then all used by the main executable. -- Kind Regards Benjamin Thaut
Jan 09 2018
On Tuesday, 9 January 2018 at 08:10:56 UTC, Benjamin Thaut wrote:Am 09.01.2018 um 05:19 schrieb Dylan Graham:In all honesty, I'm not sure. I saw the instructions on your website and just adapted it. Also, please excuse me, I'm fairly new to compiling native programs. I've been using DUB this entire time. With the common library (plugin base) DLL don't I need to generate a .lib for plugin implementations to compile/link against?It's pretty basic but I'm glad it works. I'll try doing something more advanced.Hi Dylan, I'm glad that it works for you. I'm curios though, why are you using an import library for your plugin? Normally plugins are build without and import library (the -L/IMPLIB parameter) and then loaded dynamically through LoadLibrary by your main executable.This way you can add/remove plugins without the need to recompile your main executable. Usually such plugin systems are done like this: You have some common library that defines shared functionality and the base interfaces such as a Plugin base class or Plugin interface. This common library is build into a dll with import library. You have one ore multiple plugins that link against the common library and implement the plugin interface / plugin base class. Each of these plugins provides a function "getPluginImpl" or something along the lines which can be used to get an instance of the Plugin implementation.Check. I'm doing that.You have the main executable, which links against the common library. It dynamically loads the plugin.dlls and calls the getPluginImpl method on them to retrieve the implementation. No import library involved here.I'm doing that but the getPluginImpl call is done in the common library. The executable is only a bootstrap.What your doing is also a valid use case. It is usually done when link times get to long or if you want to have clean interface between the different subsystems in your application. Your codebase is usually split into multiple dlls each with a import library which are then all used by the main executable.I am doing that. I don't need to recompile anything. I can add as many plugin implementations without recompiling the common library/executable.
Jan 09 2018
Is it possible to put common code in exe, and use that code from dlls? Or anything can be exported only by dll? Is it possible to have circular dependencies between dlls? Tips for doing dlls with dub?
Jan 09 2018
Am 09.01.2018 um 12:02 schrieb MrSmith:Is it possible to put common code in exe, and use that code from dlls? Or anything can be exported only by dll?You can only export from dlls. I don't know of any use case where exporting from a executable would make sense. No, you can't put common code into a executable and use that code from dlls. Thats not how dlls are designed to work on windows. If you absoutely still want to export from an executable you can still use -L/EXPORT:"mangledSymbolName"Is it possible to have circular dependencies between dlls?No. You will get linker errors. Same as in C/C++.Tips for doing dlls with dub?Well, first my PR will have to get merged. Then you'll have to wait until a release exists that actually has my changes and then maybe there is support added in dub. Before that I think trying to use dub to create dlls is wasted effort. -- Kind Regards Benjamin Thaut
Jan 09 2018
On Tuesday, 9 January 2018 at 14:43:43 UTC, Benjamin Thaut wrote:Am 09.01.2018 um 12:02 schrieb MrSmith:I am building a bridge between Delphi and D. At the moment the executable is written in D and the Dll (Firemonkey UI) is written in Delphi. But I think I want to enable also the other way around. The D coding which is then located in the Dll should be able to call Delphi methods located in the executable. The whole idea idea is that all logic is written in D and you only use the Framework (ui) and libraries Delphi provides. I think this might be a valid use case for a Dll calling functionality located in the exe. Kind regards AndreIs it possible to put common code in exe, and use that code from dlls? Or anything can be exported only by dll?You can only export from dlls. I don't know of any use case where exporting from a executable would make sense. No, you can't put common code into a executable and use that code from dlls. Thats not how dlls are designed to work on windows. If you absoutely still want to export from an executable you can still use -L/EXPORT:"mangledSymbolName"Is it possible to have circular dependencies between dlls?No. You will get linker errors. Same as in C/C++.Tips for doing dlls with dub?Well, first my PR will have to get merged. Then you'll have to wait until a release exists that actually has my changes and then maybe there is support added in dub. Before that I think trying to use dub to create dlls is wasted effort.
Jan 09 2018
Am 09.01.2018 um 16:03 schrieb Andre Pany:I am building a bridge between Delphi and D. At the moment the executable is written in D and the Dll (Firemonkey UI) is written in Delphi. But I think I want to enable also the other way around. The D coding which is then located in the Dll should be able to call Delphi methods located in the executable. The whole idea idea is that all logic is written in D and you only use the Framework (ui) and libraries Delphi provides. I think this might be a valid use case for a Dll calling functionality located in the exe. Kind regards AndreFirst let me say that what you are describing is a very uncommon and ill-advised use case. As such there is not going to be any nice to use workflow to acieve what you are trying to do. Still this doesn't mean that it won't be possible. Why ill-advised? What you're describing is a cyclic dependency between your main executable and your dll written in delphi. If you google for "cyclic dependency dll" you will usually get the advice to break your cylic dependency by splitting your code into more dlls. My personal experience shows the same. Cyclic dependencies in dlls are usually not worth the additional effort and hassle. Also you want to export things from your executable, which is also very uncommon. What you should be doing is having 2 dlls and one executable. You have one common library written in D that is build into a dll. Then you have your delphi library which uses the common.dll. Finally you have your main executable written in D which uses both the common.dll and your delphi.dll. This should make it possibly to break the cycle and get you an easy setup. If you absolutley must do it the way you describe it, its still possible. You will have to compile all modules that export something from your executable with the "-c -shared" parameters. E.g. dmd -m64 -c -shared moduleThatExports1.d moduleThatExports2.d -ofexports.obj Now you link the resulting exports.obj file into your executable by calling dmd again dmd -m64 restOfModules.d exports.obj delphi.lib -ofmain.exe Finally you have to get the handle to your main executable by calling HMODULE handle; GetModuleHandleExA(0, null, &handle); in your delphi dll and then fetching the function pointer for each and every function you want to call from delphi via: GetProcAddress(handle, "mangeledFunctionSymbol") Now finally you can call these functions pointers from delphi and they will call into the D code within your executable. Instead of all that hassle you could instead just have a function in your delphi dll: void recieveFunctionPointer(const(char)* name, void* ptr); which you call for every function that you want to make available from D to delphi. Your delphi code then stores away these pointers depending on the name. That way you don't need to export anything from your executable and can build it normally. Instead of having a function call per function you could obviosuly also use a struct that is defined the same way in D and delphi and contains all relevant functions pointers. -- Kind Regards Benjamin Thaut
Jan 09 2018
On Tuesday, 9 January 2018 at 18:32:24 UTC, Benjamin Thaut wrote:Am 09.01.2018 um 16:03 schrieb Andre Pany:Thanks for your deep analysis. There are several reasons I want to have the exe as Delphi application: 1) I faced some minor (Delphi) IDE/Libraries bugs with having the Delphi gui within a dll. 2) The Delphi IDE provides you the possibility to e.g. easily change the exe icon/attach additional resources to the exe, ... 3) Delphi lets you also create android/iPhone applications. I assume there will be no other way than place the D coding within a shared object for this scenario. I completely agree with you, it is mad. My gut feeling is, you have the greatest benefit from the IDE and convenience if the executable is written in Delphi. I try to support both ways in my library, so the developer can decide. Kind regards Andre[...]First let me say that what you are describing is a very uncommon and ill-advised use case. As such there is not going to be any nice to use workflow to acieve what you are trying to do. Still this doesn't mean that it won't be possible. Why ill-advised? What you're describing is a cyclic dependency between your main executable and your dll written in delphi. If you google for "cyclic dependency dll" you will usually get the advice to break your cylic dependency by splitting your code into more dlls. My personal experience shows the same. Cyclic dependencies in dlls are usually not worth the additional effort and hassle. Also you want to export things from your executable, which is also very uncommon. What you should be doing is having 2 dlls and one executable. You have one common library written in D that is build into a dll. Then you have your delphi library which uses the common.dll. Finally you have your main executable written in D which uses both the common.dll and your delphi.dll. This should make it possibly to break the cycle and get you an easy setup. If you absolutley must do it the way you describe it, its still possible. You will have to compile all modules that export something from your executable with the "-c -shared" parameters. E.g. dmd -m64 -c -shared moduleThatExports1.d moduleThatExports2.d -ofexports.obj Now you link the resulting exports.obj file into your executable by calling dmd again dmd -m64 restOfModules.d exports.obj delphi.lib -ofmain.exe Finally you have to get the handle to your main executable by calling HMODULE handle; GetModuleHandleExA(0, null, &handle); in your delphi dll and then fetching the function pointer for each and every function you want to call from delphi via: GetProcAddress(handle, "mangeledFunctionSymbol") Now finally you can call these functions pointers from delphi and they will call into the D code within your executable. Instead of all that hassle you could instead just have a function in your delphi dll: void recieveFunctionPointer(const(char)* name, void* ptr); which you call for every function that you want to make available from D to delphi. Your delphi code then stores away these pointers depending on the name. That way you don't need to export anything from your executable and can build it normally. Instead of having a function call per function you could obviosuly also use a struct that is defined the same way in D and delphi and contains all relevant functions pointers.
Jan 09 2018
On Tuesday, 9 January 2018 at 20:07:03 UTC, Andre Pany wrote:On Tuesday, 9 January 2018 at 18:32:24 UTC, Benjamin Thaut wrote: Thanks for your deep analysis. There are several reasons I want to have the exe as Delphi application: 1) I faced some minor (Delphi) IDE/Libraries bugs with having the Delphi gui within a dll. 2) The Delphi IDE provides you the possibility to e.g. easily change the exe icon/attach additional resources to the exe, ... 3) Delphi lets you also create android/iPhone applications. I assume there will be no other way than place the D coding within a shared object for this scenario.I wrote a mixed language app with interdependent components (no D though). The exe is minimal and does not export anything, its main function is practically a one liner that calls into one of the DLLs; but it could contain a lot more. First only the export library is built for component 1. With it, component 2 is built completely, giving a DLL and export lib. Now the DLL for component 1 can be built and the exe. I don’t know if this is possible in your case, but you may be able to have a Delphi exe wth the things that must be there but no exports, then have a Delphi DLL and D DLL with exports to each other. Not sure if it would make a difference, but this construction works well for us.
Jan 09 2018
On Saturday, 6 January 2018 at 19:32:51 UTC, Benjamin Thaut wrote:I'm currently back on dll support and I'm applying finishing touches to my dll support PR. Now I want to know if I missed any corner cases and it would be great if a few more people gave the dll support a try. [...]I am glad to see this happen. But my use case is not working: http://forum.dlang.org/post/giywzmvfeuddvmvkrpal forum.dlang.org
Jan 09 2018
Am 10.01.2018 um 05:18 schrieb Domain:On Saturday, 6 January 2018 at 19:32:51 UTC, Benjamin Thaut wrote:Hi Domain, what your describing is a very simple use case and should definitly work. Did you try it using my binary distribution? Please post a repro-case. I don't have the time to rebuild everyones use case and saying "My use case is not working" does not help at all. -- Kind Regards Benjamin ThautI'm currently back on dll support and I'm applying finishing touches to my dll support PR. Now I want to know if I missed any corner cases and it would be great if a few more people gave the dll support a try. [...]I am glad to see this happen. But my use case is not working: http://forum.dlang.org/post/giywzmvfeuddvmvkrpal forum.dlang.org
Jan 10 2018
On Wednesday, 10 January 2018 at 11:30:47 UTC, Benjamin Thaut wrote:Am 10.01.2018 um 05:18 schrieb Domain:Sorry, my mistake. But I cannot use your binary: D:\>dmd -m64 -shared dll.d -ofdll.dll Error: unrecognized file extension dllOn Saturday, 6 January 2018 at 19:32:51 UTC, Benjamin Thaut wrote:Hi Domain, what your describing is a very simple use case and should definitly work. Did you try it using my binary distribution? Please post a repro-case. I don't have the time to rebuild everyones use case and saying "My use case is not working" does not help at all.I'm currently back on dll support and I'm applying finishing touches to my dll support PR. Now I want to know if I missed any corner cases and it would be great if a few more people gave the dll support a try. [...]I am glad to see this happen. But my use case is not working: http://forum.dlang.org/post/giywzmvfeuddvmvkrpal forum.dlang.org
Jan 10 2018
Am 10.01.2018 um 13:39 schrieb Domain:Sorry, my mistake. But I cannot use your binary: D:\>dmd -m64 -shared dll.d -ofdll.dll Error: unrecognized file extension dllThis works just fine for me. What is the output when you execute "dmd --version"? -- Kind Regards Benjamin Thaut
Jan 10 2018
On Wednesday, 10 January 2018 at 13:14:10 UTC, Benjamin Thaut wrote:Am 10.01.2018 um 13:39 schrieb Domain:I restart my computer, and it can produce dll now. But when I compile exe: dmd -m64 -useshared app.d -ofapp.exe app.obj : error LNK2019: 无法解析的外部符号 _D3std12experimental6logger4core17stdThreadLocalLogFNdNfZCQCeQCdQBsQBo6Logger 该符号在函数 _D3std12experimental6logger4core__T18defaultLogFunctionVEQCdQCcQBrQBn8LogLeveli64Z__TQByVii9VAyaa5_6170702e64VQra8_6170702e6d61696eVQBna15_766f6964206170702e6d61696e2829VQCza3_617 70TQDmZQFwFNfLQDxZv 中被引用 app.obj : error LNK2019: 无法解析的外部符号 _D6object__T8__equalsTxaTxaZQqFNaNbNiNfAxaQdZb,该符号在函数 _D3std5array__T8AppenderTAyaZQo4Data11__xopEqualsFKxSQBzQBy__TQ vTQBpZQCdQBqKxQBaZb 中被引用 app.obj : error LNK2019: 无法解析的外部符号 _D3std12experimental6logger4core14globalLogLevelFNdNiNfZEQCdQCcQBrQBn8LogLevel 该符号在函数 _D3std12experimental6logger4core6Logger__T15memLogFunctionsVEQChQCgQBvQBr8LogLeveli64Z__T7logImplVii9VAyaa5_6170702e64VQra8_6170702e6d61696eVQBna15_766f6964206170702e6d61696e2829VQCza3_6170 0TQDmZQEdMFNfLQDyZv 中被引用 app.obj : error LNK2019: 无法解析的外部符号 _D3std11concurrency7thisTidFNdNfZSQBgQBf3Tid,该符号在函数 _D3std12experimental6logger4core6Logger__T15memLogFunctionsVEQChQCgQBvQBr8LogLeveli64Z__T7logImplVii9VAyaa5_6170702e64VQra8_6170702e6d61696eVQBna15_766f6964206170702e6d61696e2829VQCza3_6170 0TQDmZQEdMFNfLQDyZv 中被引用 app.obj : error LNK2019: 无法解析的外部符号 _D3std8datetime8timezone9LocalTime6opCallFNaNbNeZyCQBxQBwQBqQ k,该符号在函 数 _D3std12experimental6logger4core6Logger__T15memLogFunctionsVEQChQCgQBvQBr8LogLeveli64Z__T7logImplVii9VAyaa5_6170702e64VQra8_6170702e6d61696eVQBna15_766f6964206170702e6d61696e2829VQCza3_6170 0TQDmZQEdMFNfLQDyZv 中被引用 app.obj : error LNK2019: 无法解析的外部符号 _D3std12experimental6logger4core8MsgRange6__ctorMFNcNfCQCbQCaQBpQBl6LoggerZSQCwQCvQCkQCgQCe 该符号在函数 _D3std12experimental6logger4core6Logger__T15memLogFunctionsVEQChQCgQBvQBr8LogLeveli64Z__T7logImplVii9VAyaa5_6170702e64VQra8_6170702e6d61696eVQBna15_766f6964206170702e6d61696e2829VQCza3_6170 0TQDmZQEdMFNfLQDyZv 中被引用 app.obj : error LNK2019: 无法解析的外部符号 _D3std8datetime7systime7SysTime6__ctorMFNaNbNcNflyCQBxQBw8timezone8TimeZoneZSQCxQCwQCqQCl 该符号在函数 _D3std8datetime7systime5Clock__T8currTimeVE4core4time9ClockTypei0ZQBiFNfyCQCuQCt8timezone8TimeZon ZSQDuQDtQDn7SysTime 中被引用 app.obj : error LNK2019: 无法解析的外部符号 _D3std8datetime7systime17FILETIMEToStdTimeFNfMxPS4core3sys7windows7winbase8FILETIMEZl 该符号在函数 _D3std8datetime7systime5Clock__T11currStdTimeVE4core4time9Cl ckTypei0ZQBmFNdNeZl 中被引用 app.obj : error LNK2019: 无法解析的外部符号 _D3std12experimental6logger4core8MsgRange3putMFNfwZv,该符号在函数 _D3std5range10primitives__T5doPutTSQBh12experimental6logger4core8MsgRa geTaZQBxFNfKQBxKaZv 中被引用 app.obj : error LNK2001: 无法解析的外部符号 _D3std8datetime7systime7SysTime6toHashMxFNaNbNiNfZm app.obj : error LNK2001: 无法解析的外部符号 _D3std8datetime7systime7SysTime8opEqualsMxFNaNbNfKxSQByQBxQBrQBmZb app.obj : error LNK2001: 无法解析的外部符号 _D3std8datetime7systime7SysTime8__xopCmpFKxSQBqQBpQBjQBeKxQpZi app.obj : error LNK2001: 无法解析的外部符号 _D3std8datetime7systime7SysTime8toStringMxFNbNfZAya app.exe : fatal error LNK1120: 13 个无法解析的外部命令 Error: linker exited with status 1120 Sources: ///////app.d: import std.experimental.logger; import core.sys.windows.windows; import core.runtime; extern(C) alias void function() startFn; void main() { info("Loading dll1.dll"); auto handle1 = cast(HMODULE)Runtime.loadLibrary("dll1.dll"); auto fp1 = GetProcAddress(handle1, "start"); (cast(startFn)fp1)(); info("Loading dll2.dll"); auto handle2 = cast(HMODULE)Runtime.loadLibrary("dll2.dll"); auto fp2 = GetProcAddress(handle2, "start"); (cast(startFn)fp2)(); } ///////dll1.d import std.stdio; import std.experimental.logger; import core.sys.windows.dll; mixin SimpleDllMain!(DllIsUsedFromC.no); class MyLogger : Logger { this(LogLevel lv) safe { super(lv); } override protected void writeLogMsg(ref LogEntry entry) trusted { writefln("MyLogger: %s", entry.msg); } } export extern(C) void start() { info("dll1 starting"); sharedLog = new MyLogger(LogLevel.info); info("dll1 started"); } ///////dll2.d import std.stdio; import std.experimental.logger; import core.sys.windows.dll; mixin SimpleDllMain!(DllIsUsedFromC.no); export extern(C) void start() { info("dll2 started"); } dmd -m64 app.d -ofapp.exe dmd -m64 -shared dll1.d -ofdll1.dll dmd -m64 -shared dll2.d -ofdll2.dll output: 2018-01-11T12:04:51.635:app.d:main:9 Loading dll1.dll 2018-01-11T12:04:51.894:dll1.d:start:22 dll1 starting MyLogger: dll1 started 2018-01-11T12:04:51.897:app.d:main:14 Loading dll2.dll 2018-01-11T12:04:52.164:dll2.d:start:9 dll2 started I expected: 2018-01-11T12:04:51.635:app.d:main:9 Loading dll1.dll 2018-01-11T12:04:51.894:dll1.d:start:22 dll1 starting MyLogger: dll1 started MyLogger: Loading dll2.dll MyLogger: dll2 startedSorry, my mistake. But I cannot use your binary: D:\>dmd -m64 -shared dll.d -ofdll.dll Error: unrecognized file extension dllThis works just fine for me. What is the output when you execute "dmd --version"?
Jan 10 2018
Am 11.01.2018 um 05:10 schrieb Domain:I restart my computer, and it can produce dll now. But when I compile exe: dmd -m64 -useshared app.d -ofapp.exe app.obj : error LNK2019: 无法解析的外部符号 _D3std12experimental6logger4core17stdThreadLocalLogFNdNfZCQC QCdQBsQBo6Logger, 该符号在函数 _D3std12experimental6logger4core__T18defaultLogFunctionVEQCdQCcQBrQBn8LogLeveli64Z__TQByVii9VAyaa5_6170702e64VQra8_6170702e6d61696eVQBna15_766f6964206170702e6d61696e2829VQCza3_617 70TQDmZQFwFNfLQDxZv 中被引用As I said in the first post, I'm not interrested in linker errors due to missing 'export' annotation. std.experimental.logger does not have an export annotations and therefor will cause linker errors. If you absolutely must use std.experimental.logger you will have to annotate it with 'export' and recompile phobos. The idea behind my initial PR is to build in basic support for dlls, not to fully annotate all of phobos with 'export'.dmd -m64 app.d -ofapp.exe dmd -m64 -shared dll1.d -ofdll1.dll dmd -m64 -shared dll2.d -ofdll2.dllYour command line is wrong. You are missing the -useshared option and therefore your dlls / executable don't share the same version of druntime.output: 2018-01-11T12:04:51.635:app.d:main:9 Loading dll1.dll 2018-01-11T12:04:51.894:dll1.d:start:22 dll1 starting MyLogger: dll1 started 2018-01-11T12:04:51.897:app.d:main:14 Loading dll2.dll 2018-01-11T12:04:52.164:dll2.d:start:9 dll2 startedHow can you get the output of your program if it fails to link? -- Kind Regards Benjamin Thaut
Jan 11 2018
On Thursday, 11 January 2018 at 18:56:23 UTC, Benjamin Thaut wrote:Am 11.01.2018 um 05:10 schrieb Domain:I misunderstand what you mean. I thought -useshared is used when I want to use phobos as a dll.[...]As I said in the first post, I'm not interrested in linker errors due to missing 'export' annotation. std.experimental.logger does not have an export annotations and therefor will cause linker errors. If you absolutely must use std.experimental.logger you will have to annotate it with 'export' and recompile phobos. The idea behind my initial PR is to build in basic support for dlls, not to fully annotate all of phobos with 'export'.[...]Your command line is wrong. You are missing the -useshared option and therefore your dlls / executable don't share the same version of druntime.[...]How can you get the output of your program if it fails to link?
Jan 11 2018
On Thursday, 11 January 2018 at 18:56:23 UTC, Benjamin Thaut wrote:Am 11.01.2018 um 05:10 schrieb Domain:So I cannot use phobos as a static library when I use dll?[...]As I said in the first post, I'm not interrested in linker errors due to missing 'export' annotation. std.experimental.logger does not have an export annotations and therefor will cause linker errors. If you absolutely must use std.experimental.logger you will have to annotate it with 'export' and recompile phobos. The idea behind my initial PR is to build in basic support for dlls, not to fully annotate all of phobos with 'export'.
Jan 11 2018
Am 12.01.2018 um 04:02 schrieb Domain:On Thursday, 11 January 2018 at 18:56:23 UTC, Benjamin Thaut wrote:If you have a single D-dll that is used from a C program then you can use phobos as a static library. In all other cases you must use the dll version of phobos otherwise the sharing of objects between dlls/exe doesn't work correctly. -- Kind Regards Benjamin ThautAm 11.01.2018 um 05:10 schrieb Domain:So I cannot use phobos as a static library when I use dll?[...]
Jan 11 2018
On Wednesday, 10 January 2018 at 13:14:10 UTC, Benjamin Thaut wrote:Am 10.01.2018 um 13:39 schrieb Domain:D:\git\testdll\source>dmd --version DMD64 D Compiler v2.078.0 Copyright (C) 1999-2018 by The D Language Foundation, All Rights Reserved written by Walter BrightSorry, my mistake. But I cannot use your binary: D:\>dmd -m64 -shared dll.d -ofdll.dll Error: unrecognized file extension dllThis works just fine for me. What is the output when you execute "dmd --version"?
Jan 10 2018