在D中实现C API

时间:2011-09-20 04:09:23

标签: c d

因此,有很多关于从D内部调用C API的信息,但反过来怎么样?在D中编写一个像普通C共享库一样工作的库需要做什么?这是一个简单的案例:

的main.c

extern int foo(int x);
void main() {
    printf("foo(5)=%d\n",foo(5));
}

foo.d

extern(C)
{
    int foo(int x)
    {
         return x*x;
    }
}

天真地尝试使用gcc和dmd构建和链接它们只会导致链接器错误。

与gcc main.o foo.o链接:

doFoo.o: In function `no symbol':
doFoo.d:(.text+0x7): undefined reference to `_Dmodule_ref'
collect2: ld returned 1 exit status

与dmd main.o foo.o链接:

/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

3 个答案:

答案 0 :(得分:9)

根据compiler source code的快速浏览,_Dmodule_ref是模块构造函数的链接列表。要解决此问题,请将其添加到main.c

void* _Dmodule_ref;

该程序现在链接并运行良好。

(至少,我认为这是有效的。)

答案 1 :(得分:9)

我的回答是关于使用 C 中的 D静态库。 是的,这有点偏离主题,但是 Windows 的共享库在D的文档(http://www.d-programming-language.org/dll.html)和中有所描述。 Linux 仍在建设中(http://www.digitalmars.com/d/2.0/changelog.html)。附上两个系统的工作示例。

  • Win32 :dmd + dmc效果很好。 示例test_d_from_c_win32.zip

  • Linux32 :dmd在找到D main函数后添加了一些必需的东西,因此需要D的主要内容(在Linux32上测试dmd2 + gcc)。 它的链接名称是“_Dmain”,它不会与C的(真正的“主”)混合。 因此,只需添加文本dfakemain.d即可void main(){}dmd -c dfakemain.d将创建带有缺少符号的dfakemain.o。将它与您的目标文件链接,您会很高兴。 示例test_d_from_c_linux32.tar.gz

答案 2 :(得分:6)

如果gcc正在编译为C ++,那么用于extern的默认链接将是C ++,而不是C.尝试这样做:

extern "C" int foo(int x);

您的D语法似乎没有任何问题。这里有一段确认您的方法:http://www.digitalmars.com/d/2.0/interfaceToC.html