Thread overview
How to setup DLL and EXE projects in one VS solution
May 17, 2017
Igor
May 17, 2017
solidstate1991
May 17, 2017
Igor
May 17, 2017
Igor
May 18, 2017
MGW
May 18, 2017
Rainer Schuetze
May 18, 2017
Igor
May 18, 2017
Mike Parker
May 18, 2017
Rainer Schuetze
May 18, 2017
Igor
May 17, 2017
At the moment I have:

EXEProject:
  app.d - it does loadlibrary of dllproj and uses data structures defined in dllproj.d (it imports dllproj). On the file system this file is under <solutiondir>/platform/win32/ and is defined as module win32.app;

DLLProject
  dllproj.d - exports functions and contains data structures those function use. On file system this file is under <solutiondir>/source and is defined as module dllproj;

EXEProject depends on DLLProject. DLL project compiles and builds DLL fine but, of course EXE project breaks with an error:

module dllproj is in file dllproj.d which cannot be read.

I could just copy all the structs from dllproj.d to app.d and remove the import and I guess it would all work but there has to be a better way to structure code so structs are only written in one place?
May 17, 2017
On Wednesday, 17 May 2017 at 16:56:13 UTC, Igor wrote:
> At the moment I have:
>
> EXEProject:
>   app.d - it does loadlibrary of dllproj and uses data structures defined in dllproj.d (it imports dllproj). On the file system this file is under <solutiondir>/platform/win32/ and is defined as module win32.app;
>
> DLLProject
>   dllproj.d - exports functions and contains data structures those function use. On file system this file is under <solutiondir>/source and is defined as module dllproj;
>
> EXEProject depends on DLLProject. DLL project compiles and builds DLL fine but, of course EXE project breaks with an error:
>
> module dllproj is in file dllproj.d which cannot be read.
>
> I could just copy all the structs from dllproj.d to app.d and remove the import and I guess it would all work but there has to be a better way to structure code so structs are only written in one place?

I think you should make a binding for your DLL file. On the other hand I successfully set up a static library and an application in the same solution (now it has 2 apps, one is my map editor and file converter, the other is a window layout editor, going to add a third one for testing other functions later on) by adding the engine's sources and library files to the app.
May 17, 2017
On Wednesday, 17 May 2017 at 17:48:50 UTC, solidstate1991 wrote:
> I think you should make a binding for your DLL file. On the
> other hand I successfully set up a static library and an application in the same solution (now it has 2 apps, one is my map editor and file converter, the other is a window layout editor, going to add a third one for testing other functions later on) by adding the engine's sources and library files to the app.

What exactly do mean by "binding"?

If I understand the rest you are saying that I could just use "Add existing item" to add the dllproj.d file to EXEProject as well, but that would cause all of the code from it to be linked in the EXE and I only want that code in the DLL.

I should also mention that I don't want to statically bind to DLL using a lib file because I want to be able to reload the DLL while the application is running.
May 17, 2017
On Wednesday, 17 May 2017 at 18:03:04 UTC, Igor wrote:
> What exactly do mean by "binding"?
>
> If I understand the rest you are saying that I could just use "Add existing item" to add the dllproj.d file to EXEProject as well, but that would cause all of the code from it to be linked in the EXE and I only want that code in the DLL.
>
> I should also mention that I don't want to statically bind to DLL using a lib file because I want to be able to reload the DLL while the application is running.

I managed to get it to work by extracting all common structs to dllprojInterface.d module that sits at <solutionDir>/source/dllprojInterface.d on the file system but is added to both projects in the solution.

I am still wondering if there is a better solution?

Also I am wondering if using extern(C) as opposed to extern(D) only affects name mangling or am I losing some DLang possibilities since I am only calling DLang DLL from DLang EXE?
May 18, 2017

On 17.05.2017 18:56, Igor wrote:
> At the moment I have:
>
> EXEProject:
>   app.d - it does loadlibrary of dllproj and uses data structures
> defined in dllproj.d (it imports dllproj). On the file system this file
> is under <solutiondir>/platform/win32/ and is defined as module win32.app;
>
> DLLProject
>   dllproj.d - exports functions and contains data structures those
> function use. On file system this file is under <solutiondir>/source and
> is defined as module dllproj;
>
> EXEProject depends on DLLProject. DLL project compiles and builds DLL
> fine but, of course EXE project breaks with an error:
>
> module dllproj is in file dllproj.d which cannot be read.
>
> I could just copy all the structs from dllproj.d to app.d and remove the
> import and I guess it would all work but there has to be a better way to
> structure code so structs are only written in one place?

You have to add an import path to the folder with dllproj inside to the project configuration of the exeproject.

If you want to limit the imported code to the declarations, you can enable "generate interface headers" and add an import path to these instead.

Sharing data or resources between executable and DLL is currently limited to separate ownership as each binary contains its own copy of the runtime. (There is currently work being done to have a shared runtime, though). You might also run into other cross module dependencies...
May 18, 2017
On Wednesday, 17 May 2017 at 19:48:42 UTC, Igor wrote:
> On Wednesday, 17 May 2017 at 18:03:04 UTC, Igor wrote:
>> What exactly do mean by "binding"?
>>
> Also I am wondering if using extern(C) as opposed to extern(D) only affects name mangling or am I losing some DLang possibilities since I am only calling DLang DLL from DLang EXE?

Look at these materials, there can be they will are useful.

https://vk.com/vk_dlang?z=photo-471951_456239025%2Fwall-471951_2095
https://www.youtube.com/watch?time_continue=2&v=HTgJaRRfLPk

May 18, 2017
On Thursday, 18 May 2017 at 07:10:54 UTC, Rainer Schuetze wrote:
>
> You have to add an import path to the folder with dllproj inside to the project configuration of the exeproject.
>
> If you want to limit the imported code to the declarations, you can enable "generate interface headers" and add an import path to these instead.
>
> Sharing data or resources between executable and DLL is currently limited to separate ownership as each binary contains its own copy of the runtime. (There is currently work being done to have a shared runtime, though). You might also run into other cross module dependencies...

I tried just adding import paths to project and to di files and although compilation passes I still get link errors like:

error LNK2019: unresolved external symbol _D10handmade_h10game_input6__initZ (handmade_h.game_input.__init) referenced in function _D8platform5win324main9myWinMainFPvPvPaiZi (int platform.win32.main.myWinMain(void*, void*, char*, int))

where game_input is a struct in interface file. I also tried adding the di file to the exeproject but it still doesn't work. It seems VisualD doesn't add di files to compiler invocation arguments like it does with *.d and *.def files.
May 18, 2017
On Thursday, 18 May 2017 at 07:53:02 UTC, Igor wrote:

> I tried just adding import paths to project and to di files and although compilation passes I still get link errors like:
>
> error LNK2019: unresolved external symbol _D10handmade_h10game_input6__initZ (handmade_h.game_input.__init) referenced in function _D8platform5win324main9myWinMainFPvPvPaiZi (int platform.win32.main.myWinMain(void*, void*, char*, int))
>
> where game_input is a struct in interface file. I also tried adding the di file to the exeproject but it still doesn't work. It seems VisualD doesn't add di files to compiler invocation arguments like it does with *.d and *.def files.

.di files don't need to be passed to the compiler. They are neither compiled nor linked. The whole point of them is that they only provide the declarations, not the implementations. You still need to link to a compiled implementation, either in the form of an object or library file.

I've never used Visual D (or DMD for that matter) to create a DLL, but I assume an import library should have been produced along with the DLL. Are you linking to it in your executable project?
May 18, 2017

On 18.05.2017 09:53, Igor wrote:
> On Thursday, 18 May 2017 at 07:10:54 UTC, Rainer Schuetze wrote:
>>
>> You have to add an import path to the folder with dllproj inside to
>> the project configuration of the exeproject.
>>
>> If you want to limit the imported code to the declarations, you can
>> enable "generate interface headers" and add an import path to these
>> instead.
>>
>> Sharing data or resources between executable and DLL is currently
>> limited to separate ownership as each binary contains its own copy of
>> the runtime. (There is currently work being done to have a shared
>> runtime, though). You might also run into other cross module
>> dependencies...
>
> I tried just adding import paths to project and to di files and although
> compilation passes I still get link errors like:
>
> error LNK2019: unresolved external symbol
> _D10handmade_h10game_input6__initZ (handmade_h.game_input.__init)
> referenced in function _D8platform5win324main9myWinMainFPvPvPaiZi (int
> platform.win32.main.myWinMain(void*, void*, char*, int))

That's what I meant with "other cross module dependencies". In this case it might work if you export _D10handmade_h10game_input6__initZ from your DLL with the help of a def-file, but that's not something that scales well.

This talk will give you some details on the complications involved: https://www.youtube.com/watch?v=MQRHxI2SrYM

May 18, 2017
On Thursday, 18 May 2017 at 18:00:02 UTC, Rainer Schuetze wrote:
>
> That's what I meant with "other cross module dependencies". In this case it might work if you export _D10handmade_h10game_input6__initZ from your DLL with the help of a def-file, but that's not something that scales well.
>
> This talk will give you some details on the complications involved: https://www.youtube.com/watch?v=MQRHxI2SrYM

Thanks for the link Rainer. I actually watched that a few days ago but it didn't help me understand what I just figured out. It slipped my mind that structs in D are not just structs like the ones in C. In D they have default initializer which is actually a function and as you said I am not exporting that function and it doesn't scale well to hunt all hidden functions that you need to export for all common datatypes. Even if I did, since I am loading DLL and its functions dynamically using GetProcAddress, how could I even tell D to use loaded function pointer as initialization function for a type...

Anyway I will stick with the solution of using a separate file where all common datatypes are defined in both projects and see how far I get with it.