title: Implementing a C API in D
body: <p>So there's plenty of information about calling C APIs from within D, but how about the reverse?  What do you need to do to write a library in D that works like a normal C shared library?  Here's an easy case:</p>
  
  <p>main.c</p>
  
  <pre><code>extern int foo(int x);
  void main() {
      printf("foo(5)=%d\n",foo(5));
  }
  </code></pre>
  
  <p>foo.d</p>
  
  <pre><code>extern(C)
  {
      int foo(int x)
      {
           return x*x;
      }
  }
  </code></pre>
  
  <p>Naively trying to build and link these with gcc and dmd just results in linker errors.</p>
  
  <p>Linking with gcc main.o foo.o:</p>
  
  <pre><code>doFoo.o: In function `no symbol':
  doFoo.d:(.text+0x7): undefined reference to `_Dmodule_ref'
  collect2: ld returned 1 exit status
  </code></pre>
  
  <p>Linking with dmd main.o foo.o:</p>
  
  <pre><code>/usr/lib64/libphobos2.a(deh2_2eb_525.o): In function `_D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable':
  src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable+0xa): undefined reference to `_deh_beg'
  src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable+0x14): undefined reference to `_deh_beg'
  src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable+0x1e): undefined reference to `_deh_end'
  src/rt/deh2.d:(.text._D2rt4deh213__eh_finddataFPvZPS2rt4deh213DHandlerTable+0x46): undefined reference to `_deh_end'
  /usr/lib64/libphobos2.a(lifetime.o): In function `_D2rt8lifetime18_sharedStaticCtor9FZv':
  src/rt/lifetime.d:(.text._D2rt8lifetime18_sharedStaticCtor9FZv+0x15): undefined reference to `_tlsend'
  src/rt/lifetime.d:(.text._D2rt8lifetime18_sharedStaticCtor9FZv+0x29): undefined reference to `_tlsstart'
  /usr/lib64/libphobos2.a(thread_a3_258.o): In function `_D4core6thread6Thread6__ctorMFPFZvmZC4core6thread6Thread':
  src/core/thread.d:(.text._D4core6thread6Thread6__ctorMFPFZvmZC4core6thread6Thread+0x2b): undefined reference to `_tlsend'
  src/core/thread.d:(.text._D4core6thread6Thread6__ctorMFPFZvmZC4core6thread6Thread+0x36): undefined reference to `_tlsstart'
  /usr/lib64/libphobos2.a(thread_a3_258.o): In function `_D4core6thread6Thread6__ctorMFDFZvmZC4core6thread6Thread':
  src/core/thread.d:(.text._D4core6thread6Thread6__ctorMFDFZvmZC4core6thread6Thread+0x28): undefined reference to `_tlsend'
  src/core/thread.d:(.text._D4core6thread6Thread6__ctorMFDFZvmZC4core6thread6Thread+0x33): undefined reference to `_tlsstart'
  /usr/lib64/libphobos2.a(thread_a3_258.o): In function `_D4core6thread6Thread6__ctorMFZC4core6thread6Thread':
  src/core/thread.d:(.text._D4core6thread6Thread6__ctorMFZC4core6thread6Thread+0x26): undefined reference to `_tlsend'
  src/core/thread.d:(.text._D4core6thread6Thread6__ctorMFZC4core6thread6Thread+0x31): undefined reference to `_tlsstart'
  /usr/lib64/libphobos2.a(thread_a0_713.o): In function `thread_entryPoint':
  src/core/thread.d:(.text.thread_entryPoint+0x36): undefined reference to `_tlsend'
  src/core/thread.d:(.text.thread_entryPoint+0x41): undefined reference to `_tlsstart'
  collect2: ld returned 1 exit status
  --- errorlevel 1
  </code></pre>