Здесь будут приведены примеры импорта и экспорта функций, применительно к Borland C/C++.
Пусть наш проект состоит из файла на C++ (CPPFILE.CPP) и файла на ассемблере (ASMFILE.ASM), а результирующий EXE-шник называется EXEFILE.EXE.
И пусть мы хотим вызывать функции, написанные в си-шном исходнике из ассемблерного кода, и наоборот; а также экспортировать и си-шные и ассемблерные функции из полученного PE EXE файла.
Пусть также есть некоторая внешняя библиотека ANYDLL.DLL, функции из которой мы хотим использовать в обоих частях проекта, т.е. и на ассемблере и на си.
Вот как тогда будет выглядеть файл СPPFILE.CPP:
#include <stdio.h>
extern "C"
{
int __cdecl CodeInASM_UseInCPP_CName (int x);
int _import __cdecl CodeInEXTPE_UseInCPP_Cname (int x);
int _import __cdecl CodeInEXTPE_UseInCPP_Ordinal (int x);
int __cdecl CodeInCPP_UseInASM_CName (int x) { return x; }
int _export __cdecl CodeInCPP_UseInEXTPE_CName (int x) { return x; }
}
extern "C++"
{
int __cdecl CodeInASM_UseInCPP_CPPName (int x);
int _import __cdecl CodeInEXTPE_UseInCPP_CPPname (int x);
int __cdecl CodeInCPP_UseInASM_CPPName (int x) { return x; }
int _export __cdecl CodeInCPP_UseInEXTPE_CPPName (int x) { return x; }
}
int RegisterUsage()
{
return (int)&CodeInASM_UseInCPP_CName +
(int)&CodeInASM_UseInCPP_CPPName +
(int)&CodeInEXTPE_UseInCPP_Cname +
(int)&CodeInEXTPE_UseInCPP_CPPname +
(int)&CodeInEXTPE_UseInCPP_Ordinal +
(int)&CodeInCPP_UseInASM_CName +
(int)&CodeInCPP_UseInASM_CPPName +
(int)&CodeInCPP_UseInEXTPE_CName +
(int)&CodeInCPP_UseInEXTPE_CPPName;
}
int main()
{
RegisterUsage();
}
|
В свою очередь, ASMFILE.ASM будет выглядеть так:
public _CodeInASM_UseInCPP_CName
_CodeInASM_UseInCPP_CName:
mov eax, [esp+4]
retn
public @CodeInASM_UseInCPP_CPPName$qi
@CodeInASM_UseInCPP_CPPName$qi:
mov eax, [esp+4]
retn
publicdll CodeInASM_UseInEXTPE
CodeInASM_UseInEXTPE:
mov eax, [esp+4]
retn
public CodeInASM_UseInEXTPE_RenameInDef
CodeInASM_UseInEXTPE_RenameInDef:
mov eax, [esp+4]
retn
extern CodeInEXTPE_UseInASM_Name:PROC
call CodeInEXTPE_UseInASM_Name
extern CodeInEXTPE_UseInASM_Ordinal:PROC
call CodeInEXTPE_UseInASM_Ordinal
|
Для успешной компиляции всего этого потребуется EXEFILE.DEF файл, в котором будут описаны соответствия внутренних и внешних имен функций проекта:
EXPORTS AsmFunc = CodeInASM_UseInEXTPE_RenameInDef IMPORTS _CodeInEXTPE_UseInCPP_Cname = ANYDLL._CodeInEXTPE_UseInCPP_Cname @CodeInEXTPE_UseInCPP_CPPname$qi = ANYDLL.@CodeInEXTPE_UseInCPP_CPPname$qi _CodeInEXTPE_UseInCPP_Ordinal = ANYDLL.666 CodeInEXTPE_UseInASM_Name = ANYDLL.CodeInEXTPE_UseInASM_Name CodeInEXTPE_UseInASM_Ordinal = ANYDLL.777 |
Теперь, чтобы все это скомпилировать, понадобится файл MAKE.BAT:
@echo off set X=d:\whatever\borland\bcc55 %X%\bin\bcc32.exe -eEXEFILE -I%X%\include -L%X%\lib cppfile.cpp asmfile.asm |
С другой стороны, можно было бы сделать ANYDLL.LIB, посредством
IMPLIB.EXE -f anydll.lib anydll.dllпосле чего вместо IMPORTS-части EXEFILE.DEF файла, использовать ANYDLL.LIB; при этом надо не забыть подать ANYDLL.LIB в командную строку bcc32.exe.
Вот часть TDUMP'а от полученного EXEFILE.EXE:
Exports from EXEFILE.exe
RVA Ord. Hint Name
-------- ---- ---- ----
00001168 3 0000 CodeInCPP_UseInEXTPE_CPPName(int)
000011C7 6 0001 AsmFunc
000011C2 4 0002 CodeInASM_UseInEXTPE
00001160 2 0003 _CodeInCPP_UseInEXTPE_CName
Imports from ANYDLL.DLL
_CodeInEXTPE_UseInCPP_Cname
CodeInEXTPE_UseInCPP_CPPname(int)
CodeInEXTPE_UseInASM_Name
(ord. = 777)
(ord. = 666)
|