Импорты и экспорты

Здесь будут приведены примеры импорта и экспорта функций, применительно к 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)