Eugene Kotlyarov
ek@oris.ru
Чтобы скомпилировать программу под Borland C/C++, которая будет использовать crtdll.dll нужно:
implib crtdll.lib crtdll.dll
tlink32 -Tpd -x xxx.obj, xxx.dll,, import32.lib crtdll.lib
Проблемы могут возникнуть, если программа написана на C++,
а не на C. В таком случае некоторые функции (например, strchr) объявляются
как extern c++, соответственно их имена в obj-файле получаются
mangled (типа strchr$qpci) и не могут линковаться. Решается это
путем написания своего .h файла и объявления этих функций в нем, как
extern "C".
Поскольку даже при #include <windows.h> в BC
подключаются все rtl-ные .h-файлы, нужно добавить соответствующий #define,
чтобы не подключились стандартные хедеры. Например для string.h - #define __STRING_H.
Этот .h-файл нужно подключать перед всеми остальными. Подобный заголовочный файл может
выглядеть следующим образом:
// crtdll.h
#ifdef __cplusplus
extern "C" {
#endif
typedef unsigned size_t;
/* stdio.h */
int sprintf(char *buffer, const char *format, ...);
/* stdlib.h (alloc.h) */
void *malloc(size_t size);
void *realloc(void *block, size_t size);
void free(void *block);
/* mem.h */
void *memcpy(void *dest, const void *src, size_t n);
void *memset(void *s, int c, size_t n);
int memcmp(const void *s1, const void *s2, size_t n);
/* string.h */
int strncmp(const char *s1, const char *s2, size_t maxlen);
char *strchr(char *s, int c);
char *strrchr(char *s, int c);
/* not include standard string.h */
#define __STRING_H
#ifdef __cplusplus
};
#endif
Еще одна проблема в том, что такая функция, как
wsprintf в import32.lib
объявлена с подчеркиванием и соответственно при компиляции с опцией /u-
линковаться не будет. Решение - либо использовать sprintf из crtdll.dll, либо
линковать напрямую к user32.lib. Для этого нужно создать аналогично user32.lib -
implib user32.lib user32.dllи добавить user32.lib в строку запуска tlink32
Более удобный, правильный и совместимый вариант - объявить прототипы нужных RTL функций внутри своего пространства имен, например:
#ifdef __cplusplus
namespace crt {
extern "C" {
#endif
typedef unsigned size_t;
int strncmp(const char *s1, const char *s2, size_t maxlen);
char *strchr(char *s, int c);
char *strrchr(char *s, int c);
#ifdef __cplusplus
}
}
#endif
В результате исчезают проблемы с совпадением имен, однако для
использования функций объявленных extern "C++" нужно непосредственно указывать
namespace, т.е. вместо strchr нужно писать crt::strchr.
Если этой информации Вам не хватает, то
"типичный" пример использования crtdll.dll можно
посмотреть в исходниках плагина QuakePAK.
04.04.2000
Rev. 24.06.2000