2011-09-20 88 views
18

所以有很多关于在D中调用C API的信息,但相反呢?你需要做什么才能在D中编写一个类似于普通C共享库的库?下面是一个简单的情况:在D中实现一个C API

的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 
+2

嗯,你不要离开我们犹豫不决......什么是错误的? – Mehrdad

+0

链接器错误是:'foo.o:In function'no symbol': foo.d :(。text + 0x7):未定义对'_Dmodule_ref''的引用 –

回答

9

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

  • 的Win32:DMD + DMC的伟大工程。 test_d_from_c_win32.zip

  • linux32镜像:一旦它已找到d主要功能,因此需要D的主(测试DMD2 + GCC上linux32镜像)DMD增加了一些所需的东西。 它的链接名称是“_Dmain”,它不会与C的一个(真正的“主”)混合。 所以你可以添加文件dfakemain.d与文本void main(){}dmd -c dfakemain.d将创建带缺少符号的dfakemain.o。将它与你的目标文件链接起来,你会很高兴。test_d_from_c_linux32.tar.gz

+1

嗯,linux方法为我工作,但它仍然有一些问题。一个是它需要你使用dmd作为你的链接器。是否有一些图书馆可以解决这个问题?其次,它看起来像是粘在一个虚假的主体中,使得图书馆不能使用D库,并且可能与使用相同技巧的其他库不兼容。 – sholte

+0

不,它不会要求您使用dmd作为您的链接器(并且它不能,因为dmd无法链接,它只是调用外部链接器来执行此操作)。你只需要链接'dfakemain.o'。在我的linux例子中,gcc被用作“链接器的调用者”。 _是否有一些图书馆可以链接以解决该问题?_ 是的。它是'dfakemain.o'。例如,它不与D库(dlibrary.o)链接,也不应该链接。如果它使用一些D库,它应该每个可执行文件链接一次。 – Denis

+0

啊,我看到我的回答实际上是在你的例子的build.sh中。我错过了解决方案的-lrt -lphobos2 -lpthread -lm部分。 – sholte

6

,如果GCC被编译为C++,用于缺省联动外部将是C++,而不是C.试试这个:

extern "C" int foo(int x); 

你的D语法似乎没有什么问题。有一个段落确认你的方法在这里:http://www.digitalmars.com/d/2.0/interfaceToC.html

+1

不能编译为C++。只是普通的旧gcc -c main.c – sholte

9

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

void* _Dmodule_ref; 

现在程序链接和运行正常。

(至少,这就是我想它的工作原理。)

+2

我确定你实际上不得不打电话来初始化D运行时,而不是只修复链接器错误,但我以前从来没有真正做过,所以我不'不知道。我知道新闻组中的一些人一直在为Windows GUI应用程序做这件事,所以_someone_在那里知道该怎么做。我刚在D.Learn上发布了一个关于它的问题。希望那些做过它的人会在这里回应。 –

+0

是的,如果你想要像内存分配甚至静态构造函数的花式东西,那么你显然需要设置它:)但如果你想使用D作为更好的C,这可以工作。 –

+0

这似乎适用于这种情况,但我想给它一个更彻底的安定。你知道这个符号应该做什么吗? – sholte