January 09, 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.
January 09, 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
January 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:
>> 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.

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?

> 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.


January 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?

January 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
January 09, 2018
On Tuesday, 9 January 2018 at 14:43:43 UTC, Benjamin Thaut wrote:
> 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.

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
Andre
January 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
> 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.

-- 
Kind Regards
Benjamin Thaut
January 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:
>> [...]
>
> 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.

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
January 10, 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.


January 10, 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