因此,有很多关于从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
答案 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