Thread overview
Compililng C++ and D together without going mad
Apr 29, 2020
Jan Hönig
Apr 29, 2020
Johan
Apr 29, 2020
Jan Hönig
Apr 29, 2020
Jan Hönig
Apr 29, 2020
Johan
Apr 29, 2020
Jan Hönig
Apr 29, 2020
IGotD-
April 29, 2020
In my pet project, I am using some C++ libraries. The main file/function is also C++. All of it successfully compiles with cmake. Now I want to add some functionality by calling my own D functions (which use some other modules/projects/phobos).

My questions is, what is the "proper" building tool/way.
Do I extend my CMakeFile.txt with additional instructions, which basically do a "dmd -c ...".
Do I use dub to compile the D part as a library, and use that in the cmake file?
Do I use dub to compile the C++ part as well?

Surely somebody has done something similar.
Can you pinpoint me to some examples? I could go from there.
April 29, 2020
On Wednesday, 29 April 2020 at 10:25:31 UTC, Jan Hönig wrote:
> In my pet project, I am using some C++ libraries. The main file/function is also C++. All of it successfully compiles with cmake. Now I want to add some functionality by calling my own D functions (which use some other modules/projects/phobos).
>
> My questions is, what is the "proper" building tool/way.
> Do I extend my CMakeFile.txt with additional instructions, which basically do a "dmd -c ...".
> Do I use dub to compile the D part as a library, and use that in the cmake file?
> Do I use dub to compile the C++ part as well?
>
> Surely somebody has done something similar.
> Can you pinpoint me to some examples? I could go from there.

LDC is a (somewhat complex) project with D and C++ code (and external C++ libraries).
I think it will help you if your main() is in D (such that druntime is automatically initialized for you).
https://github.com/ldc-developers/ldc

-Johan
April 29, 2020
On Wednesday, 29 April 2020 at 11:38:16 UTC, Johan wrote:
> LDC is a (somewhat complex) project with D and C++ code (and external C++ libraries).
> I think it will help you if your main() is in D (such that druntime is automatically initialized for you).
> https://github.com/ldc-developers/ldc
>
> -Johan

Hmmm, a D main means i need to do quite some C++ bindings, with which I have 0 experience. I cannot even say if it will be possible.

I will probably need:
https://github.com/jupyter-xeus/xeus/blob/master/include/xeus/xkernel.hpp
https://github.com/jupyter-xeus/xeus/blob/master/include/xeus/xkernel_configuration.hpp
c++ stdlib's unique_ptr.
And then i need to subclass a C++ class and extern this D subclass.

It sounds easier to me, to manually initialize D's runtime (i imagine it being some function calls), build everything with C++, and just call D functions from C++.

Or do you think it is worth the hassle with bindings?

I have done C++ bindings once,years ago in python and it was a not pleasent.
April 29, 2020
On Wednesday, 29 April 2020 at 13:02:36 UTC, Jan Hönig wrote:
> I will probably need:
Also this thing: https://github.com/nlohmann/json
April 29, 2020
On Wednesday, 29 April 2020 at 13:02:36 UTC, Jan Hönig wrote:
> On Wednesday, 29 April 2020 at 11:38:16 UTC, Johan wrote:
>> LDC is a (somewhat complex) project with D and C++ code (and external C++ libraries).
>> I think it will help you if your main() is in D (such that druntime is automatically initialized for you).
>> https://github.com/ldc-developers/ldc
>>
>> -Johan
>
> Hmmm, a D main means i need to do quite some C++ bindings, with which I have 0 experience. I cannot even say if it will be possible.
>
> I will probably need:
> https://github.com/jupyter-xeus/xeus/blob/master/include/xeus/xkernel.hpp
> https://github.com/jupyter-xeus/xeus/blob/master/include/xeus/xkernel_configuration.hpp
> c++ stdlib's unique_ptr.
> And then i need to subclass a C++ class and extern this D subclass.
>
> It sounds easier to me, to manually initialize D's runtime (i imagine it being some function calls), build everything with C++, and just call D functions from C++.

Manually initializing D's runtime is also possible. You need to call rt_init and rt_term: https://dlang.org/phobos/core_runtime.html#.rt_init

What I meant is to
- add a `int main(....)` in a D source file
- rename your current `main` in the C++ source file to something like `the_real_main`
- add a forward reference to the D file: `extern(C) int the_real_main(....);`
- call `the_real_main` from the `main` in the D file

That way you don't have to think about how to correctly initialize D's runtime.

-Johan




April 29, 2020
On Wednesday, 29 April 2020 at 13:12:50 UTC, Johan wrote:
> Manually initializing D's runtime is also possible. You need to call rt_init and rt_term: https://dlang.org/phobos/core_runtime.html#.rt_init
>
> What I meant is to
> - add a `int main(....)` in a D source file
> - rename your current `main` in the C++ source file to something like `the_real_main`
> - add a forward reference to the D file: `extern(C) int the_real_main(....);`
> - call `the_real_main` from the `main` in the D file
>
> That way you don't have to think about how to correctly initialize D's runtime.
>
> -Johan

I thought it was a good idea to ask in the forum!
This actually helps me a lot, thanks!
April 29, 2020
On Wednesday, 29 April 2020 at 10:25:31 UTC, Jan Hönig wrote:
> In my pet project, I am using some C++ libraries. The main file/function is also C++. All of it successfully compiles with cmake. Now I want to add some functionality by calling my own D functions (which use some other modules/projects/phobos).
>
> My questions is, what is the "proper" building tool/way.
> Do I extend my CMakeFile.txt with additional instructions, which basically do a "dmd -c ...".
> Do I use dub to compile the D part as a library, and use that in the cmake file?
> Do I use dub to compile the C++ part as well?
>
> Surely somebody has done something similar.
> Can you pinpoint me to some examples? I could go from there.

For mixed language project use Cmake only, you do not need to involve dub.

You extend Cmake to compile D files. You add these files with the contents.

CMakeDCompiler.cmake.in:
set(CMAKE_D_COMPILER "@CMAKE_D_COMPILER@")
set(CMAKE_D_COMPILER_LOADED 1)
set(CMAKE_D_SOURCE_FILE_EXTENSIONS @CMAKE_D_SOURCE_FILE_EXTENSIONS@)
set(CMAKE_D_OUTPUT_EXTENSION @CMAKE_D_OUTPUT_EXTENSION@)
set(CMAKE_D_COMPILER_ENV_VAR "@CMAKE_D_COMPILER_ENV_VAR@")


CMakeDetermineDCompiler.cmake:
# Find the D compiler
find_program(
    CMAKE_D_COMPILER
        NAMES "ldc2"
        HINTS "${CMAKE_SOURCE_DIR}"
        DOC "LDC compiler"
)
mark_as_advanced(CMAKE_D_COMPILER)

set(CMAKE_D_SOURCE_FILE_EXTENSIONS d)
set(CMAKE_D_OUTPUT_EXTENSION .obj)
set(CMAKE_D_COMPILER_ENV_VAR "D")

# Configure variables set in this file for fast reload later on
configure_file(${CMAKE_CURRENT_LIST_DIR}/CMakeDCompiler.cmake.in
               ${CMAKE_PLATFORM_INFO_DIR}/CMakeDCompiler.cmake)


CMakeDInformation.cmake:
if(NOT CMAKE_D_COMPILE_OBJECT)
    set(CMAKE_D_COMPILE_OBJECT "<CMAKE_D_COMPILER> ${CMAKE_D_FLAGS} -c --of=<OBJECT> <SOURCE>")
endif()
set(CMAKE_D_INFORMATION_LOADED 1)


CMakeTestDCompiler.cmake:
# For now just do nothing in here
set(CMAKE_D_COMPILER_WORKS 1 CACHE INTERNAL "")


Put these files somewhere and tell Cmake were to find them.

set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" ${THE_PATH_TO_THE_FILES}" CACHE INTERNAL "")

You need to enable D language to use it with.

enable_language(D)



You can make this more complex but this will make you start quickly. Now Cmake will compile D files as soon as it encounters source files with the .d extension. You can gladly mix C++ and D files and it will link them all together.