{"id":1257,"date":"2017-12-05T15:52:46","date_gmt":"2017-12-05T15:52:46","guid":{"rendered":"http:\/\/dlang.org\/blog\/?p=1257"},"modified":"2021-10-08T11:07:00","modified_gmt":"2021-10-08T11:07:00","slug":"interfacing-d-with-c-getting-started","status":"publish","type":"post","link":"https:\/\/dlang.org\/blog\/2017\/12\/05\/interfacing-d-with-c-getting-started\/","title":{"rendered":"Interfacing D with C: Getting Started"},"content":{"rendered":"<p><img loading=\"lazy\" class=\"alignleft size-full wp-image-181\" src=\"http:\/\/dlang.org\/blog\/wp-content\/uploads\/2016\/08\/d6.png\" alt=\"\" width=\"200\" height=\"200\" \/>One of the early design goals behind the D programming language was the ability to <a href=\"https:\/\/dlang.org\/spec\/interfaceToC.html\">interface with C<\/a>. To that end, it provides ABI compatibility, allows access to the C standard library, and makes use of the same object file formats and system linkers that C and C++ compilers use. Most built-in D types, even structs, are directly compatible with their C counterparts and can be passed freely to C functions, provided the functions have been declared in D with the appropriate <a href=\"https:\/\/dlang.org\/spec\/attribute.html#linkage\">linkage attribute<\/a>. In many cases, one can copy a chunk of C code, paste it into a D module, and compile it with minimal adjustment. Conversely, appropriately declared D functions can be called from C.<\/p>\n<p>That\u2019s not to say that D carries with it all of C\u2019s warts. It includes features intended to eliminate, or more easily avoid, some of the errors that are all too easy to make in C. For example, bounds checking of arrays is enabled by default, and a safe subset of the language provides compile-time enforcement of memory safety. D also changes or avoids some things that C got wrong, such as what Walter Bright sees as <a href=\"http:\/\/www.drdobbs.com\/architecture-and-design\/cs-biggest-mistake\/228701625\">C\u2019s biggest mistake<\/a>: conflating pointers with arrays. It\u2019s in these differences of implementation that surprises lurk for the uninformed.<\/p>\n<p>This post is the first in a series exploring the interaction of D and C in an effort to inform the uninformed. I\u2019ve previously written about the basics of this topic in <a href=\"https:\/\/www.gamedev.net\/articles\/programming\/general-and-gameplay-programming\/binding-d-to-c-r3122\/\">an article at GameDev.net<\/a>, and in my book, \u2018<a href=\"http:\/\/amzn.to\/1IlQkZX\">Learning D<\/a>\u2019, where the entirety of Chapter 9 covers it in depth.<\/p>\n<p>This blog series will focus on those aforementioned corner cases so that it\u2019s not necessary to buy the book or to employ trial and error in order to learn them. As such, I\u2019ll leave the basics to the GameDev.net article and recommend that anyone interfacing D with C (or C++) give it a read along with <a href=\"https:\/\/dlang.org\/spec\/interfaceToC.html\">the official documentation<\/a>.<\/p>\n<p>The C and D code that I provide to highlight certain behavior is intended to be compiled and linked by the reader. The code demonstrates both error and success conditions. Recognizing and understanding compiler errors is just as important as knowing how to fix them, and seeing them in action can help toward that end. That implies some prerequisite knowledge of compiling and linking C and D source files. Happily, that\u2019s the focus of the next section of this post.<\/p>\n<p>For the C code, we\u2019ll be using the Digital Mars C\/C++ and Microsoft C\/C++ compilers on Windows, and GCC and Clang elsewhere. On the D side, we\u2019ll be working exclusively with the D reference compiler, DMD. Windows users unfamiliar with setting up DMD to work with the Microsoft tools will be well served by the post on this blog titled, \u2018<a href=\"https:\/\/dlang.org\/blog\/2017\/10\/25\/dmd-windows-and-c\/\">DMD, Windows, and C<\/a>\u2019.<\/p>\n<p>We\u2019ll finish the post with a look at one of the corner cases, one that is likely to rear its head early on in any exploration of interfacing D with C, particularly when creating bindings to existing C libraries.<\/p>\n<h3 id=\"compilingandlinking\">Compiling and linking<\/h3>\n<p>The articles in this series will present example C source code that is intended to be saved and compiled into object files for linking with D programs. The command lines for generating the object files look pretty much the same on every platform, with a couple of caveats. We\u2019ll look first at Windows, then lump all the other supported systems together in a single section.<\/p>\n<p>In the next two sections, we\u2019ll be working with the following C and D source files. Save them in the same directory (for convenience) and make sure to keep the names distinct. If both files have the same name in the same directory, then the object files created by the C compiler and DMD will also have the same name, causing the latter to overwrite the former. There are compiler switches to get around this, but for a tutorial we\u2019re better off keeping the command lines simple.<\/p>\n<p><strong>chello.c<\/strong><\/p>\n<pre class=\"prettyprint lang-c_cpp\" data-start-line=\"1\" data-visibility=\"visible\" data-highlight=\"\" data-caption=\"\">#include &lt;stdio.h&gt;\r\nvoid say_hello(void) \r\n{\r\n    puts(\"Hello from C!\");\r\n}<\/pre>\n<p><strong>hello.d<\/strong><\/p>\n<pre class=\"prettyprint lang-d\" data-start-line=\"1\" data-visibility=\"visible\" data-highlight=\"\" data-caption=\"\">extern(C) void say_hello();\r\nvoid main() \r\n{\r\n    say_hello();\r\n}<\/pre>\n<p>The <code>extern(C)<\/code> bit in the declaration of the C function in the D code is <a href=\"https:\/\/dlang.org\/spec\/attribute.html#linkage\">a linkage attribute<\/a>. That&#8217;s covered by the other material I referenced above, but it&#8217;s a potential gotcha we&#8217;ll look at later in this series.<\/p>\n<h4 id=\"windows\">Windows<\/h4>\n<p>The official DMD packages for Windows, <a href=\"https:\/\/dlang.org\/download.html\">available at dlang.org<\/a> as a zip archive and an installer, are the only released versions of DMD that do not require any additional tooling to be installed as a prerequisite to compile D files. These packages ship with everything they need to compile 32-bit executables in the OMF format (again, I refer you to \u2018<a href=\"https:\/\/dlang.org\/blog\/2017\/10\/25\/dmd-windows-and-c\/\">DMD, Windows, and C<\/a>\u2019 for the details).<\/p>\n<p>When linking any foreign object files with a D program, it\u2019s important that the object file format and architecture match the D compiler output. The former is an issue primarily on Windows, while attention must be paid to the latter on all platforms.<\/p>\n<p>Compiling C source to a format compatible with vanilla DMD on Windows requires <a href=\"http:\/\/digitalmars.com\/download\/freecompiler.html\">the Digital Mars C\/C++ compiler<\/a>. It\u2019s a free download and ships with some of the same tools as DMD. It outputs object files in the OMF format. With both it and DMD installed and on the system path, the above source files can be compiled, linked, and executed like so:<\/p>\n<pre class=\"prettyprint lang-plain_text\" data-start-line=\"1\" data-visibility=\"visible\" data-highlight=\"\" data-caption=\"\">dmc -c chello.c\r\ndmd hello.d chello.obj\r\nhello<\/pre>\n<p>The <code>-c<\/code> option tells DMC to forego linking, causing it to only compile the C source and write out the object file <code>chello.obj<\/code>.<\/p>\n<p>To get 64-bit output on Windows, DMC is not an option. In that case, DMD requires the Microsoft build tools on Windows. Once the MS build tools are installed and set up, open the preconfigured x64 Native Tools Command Prompt from the Start menu and execute the following commands (again, see \u2018<a href=\"https:\/\/dlang.org\/blog\/2017\/10\/25\/dmd-windows-and-c\">D, Windows, and C<\/a>\u2019 on this blog for information on how to get the Microsoft build tools and open the preconfigured command prompt, which may have a slightly different name depending on the version of Visual Studio or the MS Build Tools installed):<\/p>\n<pre class=\"prettyprint lang-plain_text\" data-start-line=\"1\" data-visibility=\"visible\" data-highlight=\"\" data-caption=\"\">cl \/c chello.c\r\ndmd -m64 hello.d chello.obj\r\nhello<\/pre>\n<p>Again, the <code>\/c<\/code> option tells the compiler not to link. To produce 32-bit output with the MS compiler, open a preconfigured x86 Native Tools Command Prompt and execute these commands:<\/p>\n<pre class=\"prettyprint lang-plain_text\" data-start-line=\"1\" data-visibility=\"visible\" data-highlight=\"\" data-caption=\"\">cl \/c hello.c\r\ndmd -m32mscoff hello.c chello.obj\r\nhello<\/pre>\n<p>DMD recognizes the <code>-m32<\/code> switch on Windows, but that tells it to produce 32-bit OMF output (the default), which is not compatible with Microsoft\u2019s linker, so we must use <code>-m32mscoff<\/code> here instead.<\/p>\n<h4 id=\"otherplatforms\">Other platforms<\/h4>\n<p>On the other platforms D supports, the system C compiler is likely going to be GCC or Clang, one of which you will already have installed if you have a functioning <code>dmd<\/code> command. On Mac OS, <code>clang<\/code> can be installed via <code>XCode<\/code> in the App Store. Most Linux and BSD systems have a GCC package available, such as via the often recommended command line, <code>apt-get install build-essential<\/code>, on Debian and Debian-based systems. Please see the documentation for your system for details.<\/p>\n<p>On these systems, the environment variable <code>CC<\/code> is often set to the system compiler command. Feel free to substitute either <code>gcc<\/code> or <code>clang<\/code> for <code>CC<\/code> in the lines below as appropriate for your system.<\/p>\n<pre class=\"prettyprint lang-plain_text\" data-start-line=\"1\" data-visibility=\"visible\" data-highlight=\"\" data-caption=\"\">CC -c chello.c\r\ndmd hello.d chello.o\r\n.\/hello<\/pre>\n<p>This will produce either 32-bit or 64-bit output, depending on your system configuration. If you are on a 64-bit system and have 32-bit developer tools installed, you can pass <code>-m32<\/code> to both <code>CC<\/code> and <code>dmd<\/code> to generate 32-bit binaries.<\/p>\n<h3 id=\"thelongway\">The <code>long<\/code> way<\/h3>\n<p>Now that we\u2019re configured to compile and link C and D source in the same binary, let\u2019s take a look at a rather common gotcha. To fully appreciate this one, it helps to compile it on both Windows and another platform.<\/p>\n<p>One of the features of D is that all of the integral types have a fixed size. A <code>short<\/code> is always 2 bytes and an <code>int<\/code> is always 4. This never changes, no matter the underlying system architecture. This is quite different from C, where the spec only imposes relative requirements on the size of each integral type and leaves the specifics to the implementation. Even so, there are wide areas of agreement across modern compilers such that on every platform D currently supports the sizes for almost all the integral types match those in D. The exceptions are <code>long<\/code> and <code>ulong<\/code>.<\/p>\n<p>In D, <code>long<\/code> and <code>ulong<\/code> are always 8 bytes across all platforms. This never changes. It lines up with the corresponding C types just fine on most 64-bit systems under the <code>version(Posix)<\/code> umbrella, where the C\u00a0<code>long<\/code> and <code>unsigned long<\/code> are also 8 bytes. However, they are 4 bytes on 32-bit architectures. Moreover, they\u2019re <em>always<\/em> 4 bytes on Windows, even on a 64-bit architecture.<\/p>\n<p>Most C code these days will account for these differences either by using the preprocessor to define custom integral types or by making use of the C99 <code>stdint.h<\/code> where types such as <code>int32_t<\/code> and <code>int64_t<\/code> are unambiguously defined. Yet, it\u2019s still possible to encounter C libraries using <code>long<\/code> in the wild.<\/p>\n<p>Consider the following C function:<\/p>\n<p><strong>maxval.c<\/strong><\/p>\n<pre class=\"prettyprint lang-c_cpp\" data-start-line=\"1\" data-visibility=\"visible\" data-highlight=\"\" data-caption=\"\">#include &lt;limits.h&gt;\r\nunsigned long max_val(void)\r\n{\r\n    return ULONG_MAX;\r\n}<\/pre>\n<p>The naive D implementation looks like this:<\/p>\n<p><strong>showmax1.d<\/strong><\/p>\n<pre class=\"prettyprint lang-d\" data-start-line=\"1\" data-visibility=\"visible\" data-highlight=\"\" data-caption=\"\">extern(C) ulong max_val();\r\nvoid main()\r\n{\r\n    import std.stdio : writeln;\r\n    writeln(max_val());\r\n}<\/pre>\n<p>What this does depends on the C compiler and architecture. For example, on Windows with <code>dmc<\/code> I get <code>7316910580432895<\/code>, with x86\u00a0<code>cl<\/code>\u00a0I get\u00a0<code>59663353508790271<\/code>, and\u00a0<code>4294967295<\/code> with x64 <code>cl<\/code>. The last one is actually the correct value, even though the size of the <code>unsigned long<\/code>\u00a0on the C side is still 4 bytes as it is in the other two scenarios. I assume this is because the x64 ABI stores return values in the 8-byte <code>RAX<\/code> register, so it can be read into the 8-byte <code>ulong<\/code>\u00a0on the D side with no corruption. The important point here is that the two values in the x86 code are garbage because the D side is expecting a 64-bit return value from 32-bit registers, so it&#8217;s reading more than it&#8217;s being given.<\/p>\n<p>Thankfully, DRuntime provides a way around this in <code>core.c.config<\/code>, where you\u2019ll find <code>c_long<\/code> and <code>c_ulong<\/code>. Both of these are conditionally configured to match the compile-time C runtime implementation and architecture configuration. With this, all that\u2019s needed is to change the declaration of <code>max_val<\/code> in the D module, like so:<\/p>\n<p><strong>showmax2.d<\/strong><\/p>\n<pre class=\"prettyprint lang-d\" data-start-line=\"1\" data-visibility=\"visible\" data-highlight=\"\" data-caption=\"\">import core.stdc.config : c_ulong;\r\nextern(C) c_ulong max_val();\r\n\r\nvoid main()\r\n{\r\n    import std.stdio : writeln;\r\n    writeln(max_val());\r\n}<\/pre>\n<p>Compile and run with this\u00a0and you\u2019ll find it does the right thing everywhere. On Windows, it&#8217;s\u00a0<code>4294967295<\/code>\u00a0across the board.<\/p>\n<p>Though less commonly encountered, <code>core.stdc.config<\/code> also declares a portable <code>c_long_double<\/code> type to match any <code>long double<\/code> that might pop up in a C library to which a D module must bind.<\/p>\n<h3 id=\"lookingahead\">Looking ahead<\/h3>\n<p>In this post, we\u2019ve gotten set up to compile and link C and D in the same executable and have looked at the first of several potential problem spots. We used DMD here, but it should be possible to substitute one of the other D compilers (<code>ldc<\/code>\u00a0or <code>gdc<\/code>) without changing the command line (with the exception of <code>-m32mscoff<\/code>, which is specific to DMD). The next post in this series will focus entirely on getting D arrays and C arrays to cooperate. See you there!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>One of the early design goals behind the D programming language was the ability to interface with C. To that end, it provides ABI compatibility, allows access to the C standard library, and makes use of the same object file formats and system linkers that C and C++ compilers use. Most built-in D types, even structs, are directly compatible with their C counterparts and can be passed freely to C functions, provided the functions have been declared in D with the appropriate linkage attribute. In many cases, one can copy a chunk of C code, paste it into a D module, and compile it with minimal adjustment. Conversely, appropriately declared D functions can be called from C.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[26,29,30],"tags":[],"_links":{"self":[{"href":"https:\/\/dlang.org\/blog\/wp-json\/wp\/v2\/posts\/1257"}],"collection":[{"href":"https:\/\/dlang.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dlang.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dlang.org\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dlang.org\/blog\/wp-json\/wp\/v2\/comments?post=1257"}],"version-history":[{"count":20,"href":"https:\/\/dlang.org\/blog\/wp-json\/wp\/v2\/posts\/1257\/revisions"}],"predecessor-version":[{"id":1367,"href":"https:\/\/dlang.org\/blog\/wp-json\/wp\/v2\/posts\/1257\/revisions\/1367"}],"wp:attachment":[{"href":"https:\/\/dlang.org\/blog\/wp-json\/wp\/v2\/media?parent=1257"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dlang.org\/blog\/wp-json\/wp\/v2\/categories?post=1257"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dlang.org\/blog\/wp-json\/wp\/v2\/tags?post=1257"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}