Реализация C API в D - PullRequest
       6

Реализация C API в D

18 голосов
/ 20 сентября 2011

Так что есть много информации о вызове C API изнутри D, но как насчет обратного? Что нужно сделать, чтобы написать библиотеку в 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 ]

9 голосов
/ 20 сентября 2011

В соответствии с быстрым взглядом на исходный код компилятора , _Dmodule_ref представляет собой связанный список конструкторов модулей. Чтобы решить эту проблему, добавьте это к своему main.c:

void* _Dmodule_ref;

Программа теперь связывается и работает нормально.

(По крайней мере, я так думаю.)

9 голосов
/ 20 сентября 2011

Мой ответ об использовании D статических библиотек из C .Да, это немного не по теме, но общие библиотеки для 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, поэтому требуется основная D (проверено на dmd2+ gcc в Linux32). Это имя ссылки "_Dmain", и оно не будет смешиваться с символом C (реальным "main"). Поэтому можно просто добавить файл dfakemain.d с текстом void main(){}. dmd -c dfakemain.d создастdfakemain.o с пропущенными символами. Свяжите его с вашими объектными файлами, и вы будете счастливы. Пример : test_d_from_c_linux32.tar.gz

6 голосов
/ 20 сентября 2011

Если gcc компилируется как C ++, по умолчанию для extern будет использоваться компоновка C ++, а не C. Попробуйте вместо этого:

extern "C" int foo(int x);

Похоже, с синтаксисом D что-то не так.Здесь есть параграф, подтверждающий ваш подход: http://www.digitalmars.com/d/2.0/interfaceToC.html

...