Cómo utilizar la tecla Ctrl en una unidad en Delphi en C++Builder proyecto?(o enlace a C++Builder C runtime library)
-
24-10-2019 - |
Pregunta
Tengo una unidad en Delphi que es enlazar estáticamente C .obj archivo utilizando el {$L xxx}
directiva.El C archivo es compilado con C++Builder el compilador de línea de comandos.Para satisfacer la C del archivo de biblioteca de tiempo de ejecución de dependencias (_assert, memmove, etc), estoy incluyendo la crtl
unidad de Allen Bauer mencionado aquí.
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.
Si puedo compilar la unidad en un proyecto de Delphi (.dproj) todo funciona correctamente.
Si puedo compilar la unidad de C++Builder de proyecto (.cbproj) se produce un error con el error:
[ILINK32 Error] Fatal: Unable to open file 'CRTL.OBJ'
Y, de hecho, no hay un crtl.obj
en el archivo de RAD Studio carpeta de instalación.Hay una .dcu, pero no .pas.Tratando de agregar crtdbg
a la cláusula uses (el encabezado de C donde _assert se define) da un error de que no puede encontrar crtdbg.dcu
.
Si puedo quitar el utiliza cláusula, en lugar de con errores que __assert
y _memmove
no se encuentran.
Así, en una unidad en Delphi en C++Builder proyecto, ¿cómo puedo exportar las funciones de la C biblioteca de tiempo de ejecución por lo que están disponibles para el enlace?
Ya soy consciente de Rudy Velthuis del artículo.Me gustaría evitar manualmente escrito en Delphi envolturas si es posible, ya que yo no los necesitan en Delphi y C++Builder ya debe incluir las funciones necesarias.
Editar
Para cualquier persona que quiera jugar en casa, el código está disponible en Abbrevia del repositorio de Subversion en https://tpabbrevia.svn.sourceforge.net/svnroot/tpabbrevia/trunk.Me he tomado David Heffernan y el asesoramiento que se ha añadido una "AbCrtl.pas" de la unidad que imita la tecla ctrl.dcu cuando se compila en C++Builder.Que consiguió el PPMd de trabajo de apoyo, pero la Lzma y WavPack bibliotecas de ambos errores con errores de enlace:
[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, todos ellos se declaran correctamente, y el _beginthreadex que uno es en realidad declarado en AbLzma.pas, por lo que es utilizado por el puro Delphi compilar así.
A ver a ti mismo, sólo tienes que descargar el tronco (o simplemente la "fuente" y "paquetes" directorios), desactivar el {$IFDEF BCB} bloque en la parte inferior de AbDefine.inc, y tratar de compilar el C++Builder "Abbrevia.cbproj" del proyecto.
Solución
Mi opinión sobre esto es que solo necesita la unidad Delphi en la versión Delphi del proyecto.
En la versión de C ++ Builder, simplemente compila y enlace Foolib.c como si fuera un archivo C (¡lo es!) En la versión Delphi del programa crea el .OBJ con BCC32, usa CTRL, etc. como se describe.
¿Por qué quieres concluir una biblioteca C en un envoltorio de Delphi para ser consumido en C ++?
Edición 1
Has agregado aclaraciones en los comentarios.
Otra opción a considerar sería evitar CRTL e implementar las funciones faltantes en Foowrapper. Lo hago de esa manera en lugar de usar CRTL porque eso me da más control y entiendo cómo se llama. Por ejemplo, no quiero ninguna llamada para printf()
goteo en mi aplicación GUI o mi dll.
Esta podría ser una opción atractiva si solo le falta un puñado de funciones. A menudo, la forma más ordenada de obtenerlos es vincularlos desde msvcrt.dll, que es un componente del sistema estándar en estos días. Por supuesto, parece un poco pesado vincular en msvcrt.dll solo para llegar a memset()
, memcpy()
etc.
¿Cuántas funciones faltantes hay cuando compilas la unidad Delphi sin CRTL?
Edición 2
Estoy agregando esto a la respuesta para mostrar algún código. De mi propia base de código, ofrezco esto:
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. *)
Para ftol
Enlace en ftol.obj que supongo que extraí de uno de los archivos lib en el compilador BCC55 que uso.
pienso strncmp
Debería ser bastante rutinario para implementar en Pascal.
sprintf
es más difícil en general, pero puede encontrar que solo se usa para algo trivial como el entero para la cadena. En cuyo caso, podría falsificar el código C para llamar a una rutina dedicada a eso e implementarla de manera trivial.
Para ser honesto contigo, creo que 'msvcrt.dll' se ve bastante atractivo.
Edición 3
¿Hablé pronto? Puedes tirar de un perfectamente útil sprintf
Fuera del usuario32.dll que casi todos los procesos se han cargado de todos modos. Asegúrate de elegir wsprintfA
Si es una versión ANSI que necesitas.
Edición 4
me doy cuenta _beginthreadex
. Dices que esto se define en una unidad Delphi diferente. Para que el compilador lo vea, debe redeclarlo en abctrl.pas y desde allí llame a la versión real en ablzma.pas.
Cuando incluye un .obj en un archivo Delphi .pas, el compilador debe poder resolver todas las referencias en el archivo .obj desde la unidad Delphi que se vincula a .OBJ. Todo este juego es tratado por el compilador en lugar del enlazador.
A veces se enreda en nudos con el orden en que incluye los archivos .obj y la solución es usar declaraciones de avance, pero esa es otra historia.
Otros consejos
En este caso, se supone que las funciones que le interesan están disponibles directamente desde el C RTL, por lo que fingir el enlazador con un archivo obj ficticio (vacío) debería funcionar, ya que satisfará el enlazador que busca el archivo OBJ que Delphi le dijo Necesitas, pero aún encuentro las funciones en el RTL.
Tarde, pero más completo: CRTL.DCU funciona sin problemas desde D2005 hasta XE2.
Para D6 y D7 hay una dependencia de Midaslib.dcu. Bueno, en realidad no, la DCU se distribuye con una cláusula de usos sucios.
Para D6 y D7, debe crear un sustituto de midas vacío.pas, como:
unit midaslib;
interface
implementation
end.
¡Ahora puede usar CRTL.DCU sin los errores internos!