Как использовать Crtl в модуле Delphi в проекте C ++ Builder?(или ссылка на библиотеку времени выполнения C ++ Builder C) - PullRequest
2 голосов
/ 14 марта 2011

У меня есть модуль Delphi, который статически связывает файл C .obj с помощью директивы {$L xxx}. Файл C компилируется с помощью компилятора командной строки C ++ Builder. Чтобы удовлетворить зависимости библиотеки времени выполнения файла C (_assert, memmove и т. Д.), Я включаю модуль crtl, упомянутый Алленом Бауэром здесь .

unit FooWrapper;

interface

implementation

uses
 Crtl; // Part of the Delphi RTL

{$L FooLib.obj}  // Compiled with "bcc32 -q -c foolib.c"

procedure Foo; cdecl; external;

end.

Если я скомпилирую этот модуль в проекте Delphi (.dproj), все будет работать правильно.

Если я скомпилирую этот модуль в проекте C ++ Builder (.cbproj), произойдет сбой с ошибкой:

[ILINK32 Error] Fatal: Unable to open file 'CRTL.OBJ'

И действительно, в папке установки RAD Studio нет файла crtl.obj. Есть .dcu, но нет .pas. Попытка добавить crtdbg к предложению использования (заголовок C, в котором определен _assert) выдает ошибку, которую он не может найти crtdbg.dcu.

Если я удалю предложение использует , вместо этого произойдет сбой с ошибками, которые __assert и _memmove не найдены.

Итак, как в модуле Delphi в проекте C ++ Builder я могу экспортировать функции из библиотеки времени выполнения C, чтобы они были доступны для связывания?

Мне уже известна статья Руди Велтуиса . Я хотел бы по возможности избегать написания оболочек Delphi вручную, поскольку они не нужны в Delphi, и C ++ Builder уже должен включать необходимые функции.

Редактировать

Для тех, кто хочет играть дома, код доступен в хранилище Abvervia Subversion по адресу https://tpabbrevia.svn.sourceforge.net/svnroot/tpabbrevia/trunk. Я воспользовался советом Дэвида Хеффернана и добавил модуль «AbCrtl.pas», который имитирует crtl.dcu, когда скомпилирован в C ++ Builder. При этом работала поддержка PPMd, но библиотеки Lzma и WavPack не работают с ошибками соединения:

[ILINK32 Error] Error: Unresolved external '_beginthreadex' referenced from ABLZMA.OBJ
[ILINK32 Error] Error: Unresolved external 'sprintf' referenced from ABWAVPACK.OBJ
[ILINK32 Error] Error: Unresolved external 'strncmp' referenced from ABWAVPACK.OBJ
[ILINK32 Error] Error: Unresolved external '_ftol' referenced from ABWAVPACK.OBJ

AFAICT, все они объявлены правильно, а _beginthreadex один фактически объявлен в AbLzma.pas, поэтому он также используется чистой компиляцией Delphi.

Чтобы увидеть это самостоятельно, просто загрузите транк (или просто каталоги "source" и "packages"), отключите блок {$ IFDEF BCB} в нижней части AbDefine.inc и попробуйте скомпилировать C ++ Строитель проекта "Abbrevia.cbproj".

Ответы [ 3 ]

4 голосов
/ 14 марта 2011

Я полагаю, что вам нужен только модуль Delphi в Delphi-версии проекта.

В версии C ++ builder вы просто компилируете и связываете foolib.c, как если бы это был файл C (это так!). В Delphi-версии программы вы создаете .obj с bcc32, используете ctrl и т. Д., Как описано.

Почему вы хотите обернуть это библиотеку C в оболочку Delphi для использования в C ++?

РЕДАКТИРОВАТЬ 1

Вы добавили пояснения в комментарии.

Другой вариант, который следует рассмотреть, - это избежать crtl и реализовать недостающие функции в FooWrapper. Я делаю это таким образом, а не использую crtl, потому что это дает мне больше контроля, и я понимаю, что называется. Например, я не хочу, чтобы какие-либо вызовы printf() просачивались в мое приложение с графическим интерфейсом или в мою DLL.

Это может быть привлекательным вариантом, если вам не хватает только нескольких функций. Часто самый лучший способ получить их - связать их с msvcrt.dll, который в наши дни является стандартным компонентом системы. Конечно, кажется, что ссылка на msvcrt.dll немного тяжеловата, чтобы получить memset(), memcpy() и т. Д.

Сколько недостающих функций при компиляции модуля Delphi без crtl?

РЕДАКТИРОВАТЬ 2

Я добавляю это к ответу, чтобы показать код. Из своей базы кода я предлагаю это:

const
  __turboFloat: Longint=0;
  (* We don't actually know the type but it is 4 bytes long and initialised to zero.  This can be determined
     using tdump initcvt.obj.  It doesn't actually matter how we define this since it is ultimately not
     referred to and is stripped from the executable by the linker. *)

Для ftol я ссылаюсь на ftol.obj, который, как я полагаю, я извлек из одного из файлов lib в компиляторе BCC55, который я использую.

Я думаю, strncmp должно быть довольно обычным для реализации на простом Паскале.

sprintf сложнее в полной общности, но вы можете обнаружить, что он используется только для чего-то тривиального, такого как целое число в строку. В этом случае вы могли бы выдумать код C, чтобы вызвать подпрограмму, выделенную для этого, и реализовать ее тривиально.

Если честно, я думаю, что msvcrt.dll выглядит довольно привлекательно!

РЕДАКТИРОВАТЬ 3

Я говорил с скоро? Вы можете извлечь совершенно исправный sprintf из user32.dll, который в любом случае загружен почти всеми процессами. Убедитесь, что вы выбрали wsprintfA, если вам нужна версия ANSI.

РЕДАКТИРОВАТЬ 4

Я замечаю _beginthreadex. Вы говорите, что это определено в другом модуле Delphi. Чтобы компилятор увидел его, вам нужно переопределить его в AbCtrl.pas и оттуда вызвать реальную версию в AbLzma.pas.

Когда вы включаете .obj в файл .pas Delphi, компилятор должен иметь возможность разрешать все ссылки в файле .obj внутри модуля Delphi, который ссылается на .obj. Вся эта игра рассматривается компилятором, а не компоновщиком.

Иногда вы запутываетесь в узлах с порядком, в котором вы включаете файлы .obj, и решение состоит в том, чтобы использовать предварительные объявления, но это другая история.

0 голосов
/ 08 января 2012

Поздно, но более полно: crtl.dcu работает без проблем с D2005 до XE2.

Для D6 и D7 существует зависимость от midaslib.dcu. Ну, не совсем, dcu распространяется с предложением «грязного использования».

Для D6 и D7 вы должны создать ПУСТОЙ суррогат midaslib.pas, например:

unit midaslib;
interface
implementation
end.

Теперь вы можете использовать crtl.dcu без внутренних ошибок!

0 голосов
/ 15 марта 2011

В этом случае интересующие вас функции предполагаются доступными непосредственно из C RTL, поэтому подделка компоновщика с помощью фиктивного (пустого) файла obj должна работать, так как он удовлетворит компоновщик, ищущий файл obj, которыйDelphi сказал, что вам нужно, но все же найдите функции в RTL.

...