Программный интерфейс: различия между версиями
(Новая страница: «Под программным интерфейсом, если не оговорено иное, понимаетс…») |
|||
Строка 44: | Строка 44: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== | ===Межъязыковая совместимость интерфейсов=== | ||
====Язык C++==== | |||
=====Определение интерфейса===== | |||
<syntaxhighlight lang=cpp> | <syntaxhighlight lang=cpp> | ||
struct ICalculator | struct ICalculator | ||
{ | { | ||
virtual int __stdcall Add(int A, int B) = 0; | virtual int __stdcall Add(int A, int B) = 0; | ||
}; | }; | ||
extern "C" void* __stdcall GetObject(); | |||
</syntaxhighlight> | </syntaxhighlight> | ||
=====Реализация сервера===== | |||
<syntaxhighlight lang=cpp> | |||
struct Implementation:ICalculator | |||
{ | |||
virtual int __stdcall Add(int A, int B); | |||
}; | |||
int __stdcall Implementation::Add(int A, int B) | |||
{ | |||
return A + B; | |||
} | |||
<syntaxhighlight lang= | extern "C" void* __stdcall GetObject() | ||
/ | { | ||
struct ICalculator; | static Implementation instance; | ||
return &instance; | |||
} | |||
</syntaxhighlight> | |||
=====Реализация клиента===== | |||
<syntaxhighlight lang=cpp> | |||
#include <iostream> | |||
int main(int, char**) | |||
{ | |||
ICalculator* pObject = (ICalculator*) GetObject(); | |||
std::cout << "Summ of 2 and 3 is " << pObject->Add(2, 3) << ".\n"; | |||
return 0; | |||
} | |||
</syntaxhighlight> | |||
====Язык C==== | |||
=====Определение интерфейса===== | |||
В языке нет понятия классов с методами, поэтому интерфейс определяется как структура с указателем на список указателей на функции-реализации методов интерфейса. Указатель на объект класса, над которым вызывается метод, передается в каждую функцию-метод как первый параметр. В архитектуре x86 и языке C++ этот параметр обычно передается через регистр <tt>ecx</tt> (см. [https://en.wikipedia.org/wiki/X86_calling_conventions#thiscall thiscall]), поэтому методы реализуются согласно спецификации stdcall, требующей передачу всех параметров через стек. Для x64 данное требование не применимо, так как в этом случае для функций и методов используется единая (для платформы) [https://en.wikipedia.org/wiki/X86_calling_conventions#x86-64_calling_conventions конвенция вызовов]. | |||
<syntaxhighlight lang="c"> | |||
struct ICalculator; | |||
struct ICalculator_functionlist | struct ICalculator_functionlist | ||
{ | { | ||
int (__stdcall * Add)(struct | int (__stdcall * Add)(struct ICalculator* pThis, int A, int B); | ||
}; | }; | ||
Строка 72: | Строка 109: | ||
}; | }; | ||
int main(int argc, char** argv) | void* __stdcall GetObject(); | ||
</syntaxhighlight> | |||
=====Реализация сервера===== | |||
<syntaxhighlight lang=c> | |||
int __stdcall Add(struct ICalculator* pThis, int A, int B) | |||
{ | |||
return A + B; | |||
} | |||
void* __stdcall GetObject() | |||
{ | |||
static struct ICalculator_functionlist vtbl = {Add}; | |||
static struct ICalculator impl = {{&vtbl}}; | |||
return &impl; | |||
} | |||
</syntaxhighlight> | |||
=====Реализация клиента===== | |||
<syntaxhighlight lang=c> | |||
#include <stdio.h> | |||
int main(int argc, char** argv) | |||
{ | { | ||
struct ICalculator* pInst = GetObject(); | |||
printf("Summ of 2 and 3 is %d.\n", pInst->pFunc->Add(pInst, 2, 3)); | |||
return 0; | |||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> |
Версия 18:05, 23 января 2016
Под программным интерфейсом, если не оговорено иное, понимается набор число виртуальных функций, вызываемых над скрытым указателем на объект, либо согласно спецификации thiscall, либо (для обеспечения межъязыковой совместимости) stdcall с первым скрытым параметром - указателем на объект.
Пусть интерфейс определен как
struct IFace
{
virtual void Method() = 0;
};
Такой интерфейс связан с объектом, обычно получаемым через компонент фабрику-класса
IClassFactory$ refFactory = get(); //Экземпляр порождающего класса, полученный откуда-то
IFace& inst = refFactory->CreateInstance(/*Аргументы*/);
либо через точку входа, имеющую связывание в стиле C
/*Импортируемая откуда-то функция, связывание C*/
extern "C" void* /*dllimport*/ GetObject(/*параметры*/);
struct IFace
{
virtual void Method() = 0;
};
int main(int argc, char** argv)
{
IFace* object_ptr = (struct IFace*) GetObject(/*аргументы*/);
object_ptr->Method();
return 0;
}
либо предоставляется как параметр какой-либо функции
void caller(IFace* object_ptr)
{
object_ptr->Method();
}
Межъязыковая совместимость интерфейсов
Язык C++
Определение интерфейса
struct ICalculator
{
virtual int __stdcall Add(int A, int B) = 0;
};
extern "C" void* __stdcall GetObject();
Реализация сервера
struct Implementation:ICalculator
{
virtual int __stdcall Add(int A, int B);
};
int __stdcall Implementation::Add(int A, int B)
{
return A + B;
}
extern "C" void* __stdcall GetObject()
{
static Implementation instance;
return &instance;
}
Реализация клиента
#include <iostream>
int main(int, char**)
{
ICalculator* pObject = (ICalculator*) GetObject();
std::cout << "Summ of 2 and 3 is " << pObject->Add(2, 3) << ".\n";
return 0;
}
Язык C
Определение интерфейса
В языке нет понятия классов с методами, поэтому интерфейс определяется как структура с указателем на список указателей на функции-реализации методов интерфейса. Указатель на объект класса, над которым вызывается метод, передается в каждую функцию-метод как первый параметр. В архитектуре x86 и языке C++ этот параметр обычно передается через регистр ecx (см. thiscall), поэтому методы реализуются согласно спецификации stdcall, требующей передачу всех параметров через стек. Для x64 данное требование не применимо, так как в этом случае для функций и методов используется единая (для платформы) конвенция вызовов.
struct ICalculator;
struct ICalculator_functionlist
{
int (__stdcall * Add)(struct ICalculator* pThis, int A, int B);
};
struct ICalculator
{
struct ICalculator_functionlist* pFunc;
};
void* __stdcall GetObject();
Реализация сервера
int __stdcall Add(struct ICalculator* pThis, int A, int B)
{
return A + B;
}
void* __stdcall GetObject()
{
static struct ICalculator_functionlist vtbl = {Add};
static struct ICalculator impl = {{&vtbl}};
return &impl;
}
Реализация клиента
#include <stdio.h>
int main(int argc, char** argv)
{
struct ICalculator* pInst = GetObject();
printf("Summ of 2 and 3 is %d.\n", pInst->pFunc->Add(pInst, 2, 3));
return 0;
}